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" にする」とあるがどういうことだ?
「ラベル名を展開する」という意味だろうか……?
一先ずは関数呼び出しに使えるようだということだけ理解して、次に進む。

http://developer.apple.com/documentation/DeveloperTools/Reference/Assembler/ASMDirectives/chapter_5_section_5.html#//apple_ref/doc/uid/TP30000823-TPXREF157


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" の意味だから、メモリの位置を覚えておく変数なのだが、役目は何だったっけ?追々確認していく。