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)

出力番号は正しいのですが、セグフォルトの原因は何ですか?

4

2 に答える 2

0

32ビットスタックでワードをプッシュしています。これは「合法」ですが、おそらく悪い考えです。あなたはそれを機能させるかもしれませんが、add [ebp + 6], esiキリンです。これは、意図した2バイトだけでなく、スタック上の4バイトを破壊しています。これをsi「可能性がある」に変更するだけで修正できますが、全体でdwordを使用することをお勧めします。ret 4スタックから2つの(単語!)パラメータを削除しています。これは「stdcall」です。これはLinuxでは珍しいことですが、「機能するはずです」。私はcoolbartekが示すようにそれをします。

于 2012-10-02T15:55:40.470 に答える
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 に答える