alabama_country @Wiki

後期実験-アセンブリ

最終更新:

alabama_country

- view
管理者のみ編集可

Twitter上での議論

xharaken
関数呼び出しの引数を載せるのをesp[4],esp[8],esp[12],...にしておいて,戻り番地をesp[0]に入れることにすれば,call時にesp-=4する手間やret時にesp+=4する手間が減る気がするんだが・・・・・・何か考え落としてるのかなぁ
yuyarin
@xharaken コーリングコンベンションって言うから cdecl でそんなことしてたっけと思ったけど,もしかして call, ret で 次のアドレスをスタックに push/pop する仕様の話?
xharaken
@yuyarin そのpush/popする話.なんでpush/popしなきゃいけないの?esp[4]以降に引数を積んでおいてesp[0]に戻り番地入れるんじゃダメなの?
yuyarin
@xharaken push/pop がデクリメント/インクリメント→ストアになっている理由は src のアドレス計算を考えれば分かるけど,push/pop esp を可能にするためです.
xharaken
@yuyarin ごめん.説明の下手で悪いんだけど,(1)一般のpush/popがデクリメント/インクリメント→ストア/ロードになっているのはすこぶる同意,(2)callの仕様が,espを減らした上でesp[0]に戻り番地を書き込む理由がわからない
xharaken
callの仕様がesp-=4してからesp[0]に戻り番地を入れる方式の場合,f(1,2,3)を呼ぶには,pushl 1; pushl 2; pushl 3; call f;となる.
xharaken
一方で,callの仕様が単にesp[0]に戻り番地を入れる方式の場合,f(1,2,3)を呼ぶには,pushl 1; pushl 2; pushl 3; pushl 0; call f;みたいに,callの直前で意図的に1個スタックをずらす操作が必要になる
xharaken
こう考えると,一見,esp-=4してからesp[0]に戻り番地を入れる方式の方が,命令数が少なくて望ましい様に見えるが・・・
xharaken
実際には(特に関数が複雑でない場合),フレーム開始時にsubl $100, espみたいにして,ガバッとフレームを確保してしまい,f(1,2,3)を呼び出す際には,esp[8]=3; esp[4]=2; esp[0]=1; call f;とする方が多い
xharaken
そうだとすれば,callの仕様を単にesp[0]に戻り番地を書き込むことにしておいて,esp[12]=3; esp[8]=2; esp[4]=1; call f;と書けるようにしておいた方が,関数呼び出しが微妙に軽くなるんじゃないか・・・という疑問.
xharaken
ごめん.さっきの例でpushlする順序間違えた.× pushl 1; pushl 2; pushl 3; call f; ○ pushl 3; pushl 2; pushl 1; call f;
xharaken
いや待てよ,そういうことをやりたければ,callなんか使わずに,esp[12]=3; esp[8]=2; esp[4]=1; esp[0]=eip+5; jmp f;とか書けば良い,って話なのかな...(なんか話題があまりに瑣末な気がしてきた)
yuyarin
@xharaken 一応確認しておきたいんだけど,esp[8] とか書いてる時の esp の基準は call 直前だよね?
xharaken
@yuyarin そう,esp[8]の基準はcall直前.
yuyarin
@xharaken push を使おうとする場合,auto var の確保のときに 4スタックポインタのサイズ分多めに取るとか,デクリメントしなきゃいけないので,難読化するし意味も無くなる.call が push を利用する方が統一的で美しい.
xharaken
@yuyarin というか,4スタックポインタどころか必要十分に大きく取っておけば良いし,現に最適化オプション付きのgccは,単純な関数に対してはたいていそういうコードを出力するみたい.
yuyarin
@xharaken なんで gcc がスタックの無駄遣いをしているのかは知らない...cdecl の規約としては cl の吐く asm の方が簡潔で分かりやすい.
xharaken
@yuyarin 無駄遣いしてるのは,単に速いからじゃない?クロック数は知らないけど,pushlよりはmovlの方が速そう(衝突も考えなくていい).gccは,変な最適化周りは相当がんばってる.
yuyarin
@xharaken まともにスタックを使えば push でも衝突はしない.速そうというのは多分当たっていて,理由は push だと毎回デクリメントする必要があるけど sub&mov ならばそれが必要ないからその分速いはず.
xharaken
@yuyarin processor consistencyを維持する範囲なら,複数のmovlをOut of orderに実行することも原理的には可能なはず(実際に行われるかは知らないが)
記事メニュー
目安箱バナー