0

宿題のために、数字をスキャンし、1 ずつ増やして答えを出力するように求められました。ただし、コードではセグメンテーション エラーが発生する傾向があります。

.global main

mystring: .asciz "Assignment 3: inout\n"

string: .asciz "%d"

main:   pushl $mystring
        call printf
        jmp inout

end:    pushl $0
        call exit

これは基本的に私たちがやっていることです。ジャンプせずにこのようなコードを実行するとうまくいきます。問題は inout メソッドにあります

inout:  subl $0, %esp             ;what is happening here
        leal -4(%ebp), %eax       ;what am i doing here
        pushl %ebp                ;why do i need to push the base pointer
        movl %esp, %ebp
        pushl %eax
        pushl $string
        call scanf
        incl %eax
        pushl %eax
        pushl $string
        call printf

うまくいかないようです。また、先頭(減算、アドレスのこと)が何を意味するのかわかりません。詳細については、解説を参照してください。前もって感謝します!

4

1 に答える 1

0

部分的な回答ですが、問題を追跡するのに役立つかもしれません:

subl $0, %esp 定数がゼロでない場合、スタックが大きくなります。スタックの一番上は、通常、x86 の最も低いメモリ アドレスにあります。つまり、スタックは下に向かって成長します。

leal -4(%ebp), %eax%ebp - 4に絶対アドレスをロードします%eaxscanfこれは、 d 整数を格納するメモリ位置へのポインタです。

なぜpushベースポインターを使用しているのかは、実際に関連する質問です。通常、後で変更し、何かを実行し、pop完了したらそれを実行するため、通常はそうしますが、そうではないようです。これは通常、ユーザーが使用する関数と共に使用されますcall。ここで問題になる可能性があります。メソッドを呼び出しますが、それをのみinoutのラベルとして使用していますjmp。あなたが投稿したコードは、元の場所に戻る可能性がありませんjmp

Wikibooksには、x86 スタック フレームのかなり簡潔な紹介があります。

于 2013-09-30T10:39:38.030 に答える