gcc でアセンブリコードを出力する
gcc -S でアセンブリコードが出力されることを初めて知った(滝汗)
やばいくらい面白いぞ!!
(gcc のバージョンは gcc version 4.0.1 (Apple Computer, Inc. build 5370))
簡単なプログラムで C のソースとアセンブリコードを比較してみる。
int main() { int x = 0; return 0; }
gcc -S するとこうなる。
.text .globl _main _main: pushl %ebp movl %esp, %ebp subl $24, %esp movl $0, -12(%ebp) movl $0, %eax leave ret .subsections_via_symbols
ちなみに gcc -S -O2 してもアセンブリソースは変わらなかった。
引越し準備とかあるのでちょっと中断
アセンブリコードを読み解いたりする予定。
さて、再開。
.text
Apple の資料
http://developer.apple.com/documentation/DeveloperTools/Reference/Assembler/ASMDirectives/chapter_5_section_2.html#//apple_ref/doc/uid/TP30000823-TPXREF102
を読んでも良く分からず……。"machine instruction" だけを書く section らしいのだが、"machine instruction" って何だ?
とりあえず必要なお呪いだと理解して、次に進む。
.globl _main
う〜ん、「.globl は "_main" を "external" にする」とあるがどういうことだ?
「ラベル名を展開する」という意味だろうか……?
一先ずは関数呼び出しに使えるようだということだけ理解して、次に進む。
C のソースで言う main 関数の中身。
_main: pushl %ebp movl %esp, %ebp subl $24, %esp movl $0, -12(%ebp) movl $0, %eax leave ret .subsections_via_symbols
main のところにブレークポイントを作って止めて、info register してみた。
Breakpoint 1, 0x00001fa4 in main () (gdb) info register eax 0x1 1 ecx 0x1 1 edx 0x0 0 ebx 0xbffff8f4 -1073743628 esp 0xbffff870 0xbffff870 ebp 0xbffff888 0xbffff888 esi 0xbffff950 -1073743536 edi 0xbffff8ec -1073743636 eip 0x1fa4 0x1fa4 <main+6> eflags 0x282 642 cs 0x17 23 ss 0x1f 31 ds 0x1f 31 es 0x1f 31 fs 0x0 0 gs 0x37 55
これは、step してみたところ。
(gdb) step Single stepping until exit from function main, which has no line number information. 0x00001f82 in _start () (gdb) info register eax 0x0 0 ecx 0x1 1 edx 0x0 0 ebx 0xbffff8f4 -1073743628 esp 0xbffff890 0xbffff890 ebp 0xbffff8c8 0xbffff8c8 esi 0xbffff950 -1073743536 edi 0xbffff8ec -1073743636 eip 0x1f82 0x1f82 <_start+216> eflags 0x282 642 cs 0x17 23 ss 0x1f 31 ds 0x1f 31 es 0x1f 31 fs 0x0 0 gs 0x37 55
ちなみにもう一度 step するとプログラムが(正常)終了するので、上記のスタックの2つ状態の違いは x に 0 を代入した影響だと分かる。
変化している部分だけ取り出すと、
eax 0x1 1 esp 0xbffff870 0xbffff870 ebp 0xbffff888 0xbffff888 eip 0x1fa4 0x1fa4 <main+6>
↓
pushl %ebp movl %esp, %ebp subl $24, %esp movl $0, -12(%ebp) movl $0, %eax leave ret .subsections_via_symbols
↓
eax 0x0 0 esp 0xbffff890 0xbffff890 ebp 0xbffff8c8 0xbffff8c8 eip 0x1f82 0x1f82 <_start+216>
ブレークポイントが 0x1fa4 に作られているので、eip はプログラムコードの現在位置を示しているらしい。eax は変数として使うはずなので、x に相当するのだろう。ebp は確か "exteded base pointer"、esp は "extended stack pointer" の意味だから、メモリの位置を覚えておく変数なのだが、役目は何だったっけ?追々確認していく。