web-dev-qa-db-ja.com

アセンブリのCALLEEで「PushEBP」と「MOVEBP、ESP」を使用するのはなぜですか?

アセンブリ関数の呼び出し先の最初のアクションとして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
8
Artur Grigio

呼び出し元のスタックフレームを保持しながら、呼び出し先内に新しい スタックフレーム を確立しています。スタックフレームを使用すると、関数内の任意の場所でEBPに関連する固定オフセットを使用して、渡されたパラメーターとローカル変数に一貫してアクセスできます。一方、ESPは、関数の実行中に必要に応じて自由に変更できます。 ESPは移動するターゲットであるため、関数がスタックをどのように使用するかによっては、ESPに関連する動的オフセットを使用してパラメーターや変数にアクセスするのは、不可能ではないにしても注意が必要です。スタックフレームの作成は、呼び出し元のスタックフレームへのポインタを保持するために数バイトのスタックスペースを使用するという犠牲を払って、一般的に安全です。

9
Remy Lebeau

レミーからの答えは完璧ですが、ここに小さな追加が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など)によって異なります。

3
Belial