0

所以这是一个使用递归的斐波那契程序,但最后有一个“分段错误(代码转储)”。是什么原因造成的?编码:

_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

样本输出:

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

输出数字是正确的,但是是什么导致了 seg 错误?

4

2 回答 2

0

我看不到您向 esp 弹出或添加任何值。确保 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.
于 2012-10-02T15:22:29.053 回答
0

您正在将单词压入 32 位堆栈。这是“合法的”,但可能是个坏主意。您“可能”只是让它工作,但add [ebp + 6], esi正在杀死你。这会破坏堆栈上的 4 个字节,而不仅仅是您想要的 2 个字节。只需将其更改为si“可能”修复它,但我建议始终使用 dwords。您ret 4正在从堆栈中删除 2 个(单词!)参数 - 这是“stdcall”,这在 Linux 中不常见,但“应该”工作。我会按照coolbartek展示的方式来做。

于 2012-10-02T15:55:40.470 回答