x86におけるスタック操作

自分用メモ

以下のプログラムでx86における関数呼び出し時のスタックの使い方

start:
// ...
push 3
push 2
push 1
call func  // func(1,2,3)
sub esp, 12
// ...

func:
push ebp
mov ebp, esp
// -- 関数の処理 --
mov esp, ebp //espの復元
pop ebp // ebpの復元
ret

1.スタックに積まれる順番

1.引数
2.リターンアドレス
3.退避されたebp

退避されたebpの次(スタックの先頭方向)にはローカル変数が格納される。

2.引数について

pushされる順番

arg3,arg2,arg1の順でpushされる。

関数内での引数へのアクセス

[ebp+8] : 第一引数
[ebp+12] : 第二引数
[ebp+16] : 第三引数
(以下省略)

3.ローカル変数について

ローカル変数の確保

関数内で以下の命令が実行される。

sub esp, 4 * (確保するローカル変数の個数)

ローカル変数の破棄

ret命令直後、つまりcall命令の次のデータ列で以下の命令が実行される。

add esp, 4 * (確保するローカル変数の個数)

関数内でのローカル変数へのアクセス

[ebp-4],[ebp-8],[ebp-12]など

4.その他

leave命令は以下と等価

mov esp,ebp
pop ebp

enter命令は以下と等価

push ebp
mov ebp,esp
sub esp,N