関数呼び出し

(C言語の)関数の呼び出し方に関するコンベンション類。原典がどこにあるか良く分からないので、ソースは日本語だったり観察から得られた事実だったりします。
環境は、gas 2.17.50 gcc 4.1.2 x86(Pentium M) Ubuntu Feisty Fawn ってな感じです。


関数に入るときと出るときとで変化してはいけないレジスタEBP, ESP, EDI, ESI, EBX
戻り値を格納するレジスタEAX


関数呼び出し側では引数をスタックにプッシュしてcallするだけ。
呼び出された関数では EBP をスタック上に保存し、 ESP は関数を抜けるときに復元する。
EDI・ESI・EBXは(必要に応じて)スタック上に保存しておき、戻る前に元通りにする。
この辺はマクロ化しても良いくらいの常套句になってるぽ。
ただし、EDIやESIを使わない場合はわざわざ保存しないことも多々あるらしい。

func:
        pushl   %ebp
        movl    %esp, %ebp
        pushl   %edi
        pushl   %esi
        pushl   %ebx
# ここに処理が入るなんです♪
        popl    %ebx
        popl    %esi
        popl    %edi
        popl    %ebp
        ret


main関数では、次の数命令が定型文になっている模様。

main:
	leal	4(%esp), %ecx
	andl	$-16, %esp
	pushl	-4(%ecx)
	 pushl	%ebp
	 movl	%esp, %ebp
	pushl	%ecx
# ここに関数本体が入るなんです♪
	popl	%ecx
	 popl	%ebp
	leal	-4(%ecx), %esp
	ret

一文字ぶん字下げしたところは通常の関数と同じことをしている部分。それらに挟まれて、ECXの値をpushしてる。これはプログラムの最後にECXからESPを復元したいがため。


andl $-16, %esp は、ESPの値の下四桁をオフしているってことですね。オフするってことはESPは減少する、つまりスタックが伸びる方向へ移動する。
leal 4(%esp), %ecx と、ECXをスタックの伸びる方向とは逆の位置に指定しているのは、andl $-16, %esp したあとのESPの位置が変わらなかった場合に備えているのだと思う。・・・たぶん。(あれ、でも、考えてみるとこれだけの命令だったらなんも効果が無いな・・・)
で、mainが終わったあとにはECXやEBPを復元したあと、そのECXからESPの値を元通り復元すれば出来上がり。ってなもんだ。


__attribute__((constructor))と__attribute__((destructor))で定義された関数については、

.globl premain
	.type	premain, @function
premain:
	pushl	%ebp
	movl	%esp, %ebp
# ここに処理が入るなんです♪
	popl	%ebp
	ret
	.size	premain, .-premain
	.section	.ctors,"aw",@progbits
	.align 4
	.long	premain
	.text
.globl postmain
	.type	postmain, @function
postmain:
	pushl	%ebp
	movl	%esp, %ebp
# ここに処理が入るなんです♪
	popl	%ebp
	ret
	.size	postmain, .-postmain
	.section	.dtors,"aw",@progbits
	.align 4
	.long	postmain
	.section	.rodata

ごく普通の関数と同じであって、「main関数を呼び出す、ひとつながりの関数」ということは無い。単に、main関数の前とあとに呼ばれるだけの関数。
じゃあやっぱり、(プロセスごとに仮想メモリ空間が使用される今となっては)main関数の前後で各レジスタの値をストアしておく必要って特にない気がする。


あと、グローバル変数はシンボルでアクセスしてた。たぶんロード時に具体的な数値と入れ替えるんじゃないかと思う。ロード時の動作とかその読み方についてはまだ全然分かんないけど。
リンク時にやるっぽい。


今日の参考ページ:
http://ja.wikipedia.org/wiki/%E5%91%BC%E5%87%BA%E8%A6%8F%E7%B4%84
http://lily.fan.gr.jp/~kmd/adhoc/memo/sutakku.txt
http://practical-scheme.net/docs/stack-j.html
http://labs.cybozu.co.jp/blog/takesako/2007/05/fizzbuzz_x86.html
http://hp.vector.co.jp/authors/VA014520/asmhsp/chap4.html
http://d.hatena.ne.jp/Yamami/20041208
http://homepage1.nifty.com/herumi/prog/prog11.html
http://www.sol.dti.ne.jp/~yoshinor/program/prog0002.html


あと、http://www.sandpile.org/ia32/index.htmここは何やら面白い。説明こそ無いけれど、様々な仕様について書かれていて、場合によってはとても便利。