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に実行することも原理的には可能なはず(実際に行われるかは知らないが)