アセンブリ関数の呼び出し先の最初のアクションとしてPush ebp
するのはなぜですか?
次に、mov edi, [ebp+8]
を使用して渡された変数を取得することを理解していますが、esp
はすでに呼び出し元関数の戻りアドレスを指しています。渡された変数には、mov edi, [esp+4]
を使用して簡単にアクセスできます。または、呼び出し先レジスタをプッシュした場合は、mov edi, [esp+16]
を使用します。
では、なぜ後で関数で管理する必要があるCPU(ebp
)にその余分なレジスタがあるのでしょうか。つまり.
Push ebp
mov ebp, esp
...
mov esp, ebp
pop ebp
呼び出し元のスタックフレームを保持しながら、呼び出し先内に新しい スタックフレーム を確立しています。スタックフレームを使用すると、関数内の任意の場所でEBP
に関連する固定オフセットを使用して、渡されたパラメーターとローカル変数に一貫してアクセスできます。一方、ESP
は、関数の実行中に必要に応じて自由に変更できます。 ESP
は移動するターゲットであるため、関数がスタックをどのように使用するかによっては、ESP
に関連する動的オフセットを使用してパラメーターや変数にアクセスするのは、不可能ではないにしても注意が必要です。スタックフレームの作成は、呼び出し元のスタックフレームへのポインタを保持するために数バイトのスタックスペースを使用するという犠牲を払って、一般的に安全です。
レミーからの答えは完璧ですが、ここに小さな追加が1つあります。これは、直後にも表示される可能性があります。
mov ebp, esp
次のような指示を見ることが非常に可能です。
sub esp, 20h ; creating space for local variables with size 20h
sub esp, CCh ; creating space for local variables with size CCh
aND呼び出しと一緒に時々(そしてesp、0FFFFFFF0hのように)。これもスタックの処理の一部であり、スタックを整列して16で割り切れるようにするために行われます。もちろん、これはすべて、使用される呼び出し規約(cdecl、fastcall、stdcallなど)によって異なります。