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