Binary2.0勉強会 4

前回5行目まで順に見ていったので、6行目からまた見ていってもいいのですが、ただ順を追って見ていってもどの部分がどの部分に対応しているか分からないと何ともなりませんね。
そんなわけで今回はまずCのソースコードとの対応を取るところから。
コンパイル時にデバッグ情報残すようにしてやって、

niha@hoge:~/src/c$ gcc -c -g bin01.c

objdump もオプションを変更してやります。

niha@hoge:~/src/c$ objdump -S bin01.o

bin01.o:     file format elf32-i386

Disassembly of section .text:

00000000 <main>:
int main(){
   0:	8d 4c 24 04          	lea    0x4(%esp),%ecx
   4:	83 e4 f0             	and    $0xfffffff0,%esp
   7:	ff 71 fc             	pushl  -0x4(%ecx)
   a:	55                   	push   %ebp
   b:	89 e5                	mov    %esp,%ebp
   d:	51                   	push   %ecx
  return 0;
   e:	b8 00 00 00 00       	mov    $0x0,%eax
}
  13:	59                   	pop    %ecx
  14:	5d                   	pop    %ebp
  15:	8d 61 fc             	lea    -0x4(%ecx),%esp
  18:	c3                   	ret    

Cのソースコードとの対応がこれでばっちりです。やったー。これまで見ていた1〜5行目と6行目は関数が呼び出された際に行われる処理だということが分かりました。
さて、続きを見ていきましょう。6行目。

push   %ecx
||
ecx をスタックにプッシュしています。 ecx は関数が呼び出された時点の esp + 4 でした。
7行目。return 0 の部分ですね。
>||
mov    $0x0,%eax

eax に 0 を積んでます。0 は返り値だと思うのですが、何故 eax に積んでいるのでしょうか。
8行目。関数内の処理が終わった後の部分ですね。

pop    %ecx

POP Pop a Value from the Stack
スタックから値を取り出してオペランドに入れて、スタックポインタをインクリメントって感じでしょうか。
スタックに最後に積まれたのは ecx でした。ということは何も変化なし、ですね。
9行目。

pop    %ebp

スタックに ecx の前に積まれたのは元の ebp でした。ということは、書き換えられていた値が関数が呼び出された状態に復元されたことになりますね。
10行目。

lea    -0x4(%ecx),%esp

esp = ecx - 4 ですが ecx = (元の)esp + 4 だったので、結局は esp の値が関数が呼び出された状態に復元されたことになりますね。
さて最後の行です。11行目。

ret    

RET Return from Procedure プログラム制御をスタックのトップにあるリターン・アドレスに移す。
リターンアドレス?何それ?という感じですが、関数から抜けるときに使われる命令ぽいことは分かります。
今回は一旦ここで切ります。次回は関数の呼び出しについて。