2012-10-02 80 views
0

所以這是一個使用遞歸的Fibonacci程序, 但最後還是出現了「分段錯誤(代碼轉儲)」。是什麼原因造成的 代碼:nasm program:遞歸分段錯誤

_start: 
mov eax, 4 ; ask for a number 
mov ebx, 1 
mov ecx, prompt 
mov edx, promptLen 
int 80h 

mov eax, 3 ; scan input 
mov ebx, 0 
mov ecx, n 
int 80h 

sub byte [n], 30h 

mov esi, 1 
push word 0 
push word [n] 
call fibo 

exit: 
    mov eax, 1 
    mov ebx, 0 
    int 80h 

fibo: 
    mov ebp, esp 

    mov edi, [ebp+6] 

    add byte [ebp+6],30h  
    mov eax, 4    ; print number 
    mov ebx, 1 
    lea ecx, [ebp+6] 
    mov edx, 1 
    int 80h 
    sub byte [ebp+6],30h 

    mov eax, 4 ; print space 
    mov ebx, 1 
    mov ecx, space 
    mov edx, 1 
    int 80h 

    cmp byte [ebp+4],0 
    je bye 

    add [ebp+6],esi 
    mov esi, edi 

    push word [ebp+6] 

    dec word [ebp+4] 
    push word [ebp+4] 

    call fibo 

    bye: 
    ret 4 

SAMPE輸出:

Enter a number: 5 
0 1 1 2 3 5 Segmentation fault (code dumped) 

輸出數字是正確的,但什麼原因導致了賽格故障?

+0

gdb是否能夠告訴你導致seg故障的確切指令? –

+0

我不知道gdb是什麼。抱歉。 –

+0

Linux調試器。 –

回答

0

我看不到你彈出或向esp添加任何值。確保具有與通話開始時相同的值。您可以通過將基指針保存在堆棧上來實現此目的。 在每個功能記住要做到這一點:

push ebp 
mov ebp,esp 
;at the end of the function 
pop ebp 

打電話,你推一些寄存器的功能後,務必做到:

add esp, 4*x 
;where x is the number of registers you pushed. 
0

你是個32位堆棧上推的話。這是「合法」,但可能是一個壞主意。你「可能」只是得到它的工作,但add [ebp + 6], esi是殺了你。這是堆棧中的4個字節,而不僅僅是你打算的2個字節。只是將其更改爲si「可能」會修復此問題,但我建議您始終使用雙字。您的ret 4正在從堆棧中刪除2個字(word!)參數 - 這是「stdcall」,這在Linux中並不常見,但「應該」起作用。我會按照coolbartek展示的方式去做。