忍者ブログ
  • 2024.03«
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • » 2024.05
[PR]
×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

【2024/04/27 06:59 】 |
呼出規約の縮小(gcc)
呼出規約とは呼出側(caller)と呼び出された側(callee)の受け渡し規約のこと。

・callerの選択肢はクリーンアップするか、しないか
・calleeの選択肢はクリーンアップするか、しないか

stdcallの特徴は
・calleeはクリーンアップする
・callerはクリーンアップしない

cdeclの特徴は
・calleeはクリーンアップしない
・callerはクリーンアップする

考えてみてほしい。

callerとcalleeのどちらでクリーンアップするほうが良いか

・calleeでやる場合の特徴はクリーンアップが呼出回数に比例し
 プログラムサイズは小さくなる。

・callerでやる場合の特徴は下記のような場合、
 クリーンアップしなくてもいいという選択肢が生まれる。
 しかし、プログラムサイズは大きくなる
 func1(1)
 func2(1, 2)

拍手[0回]

●gccの呼出規約の縮小とは

stdcallの特徴は
・calleeはクリーンアップする

cdeclの特徴は
・calleeはクリーンアップしない

とし、callerの選択肢を限定しないことにある。

一番融通が効くのはcalleeもcallerもクリーンアップしないである。

クリーンアップしないことの問題は
pushが連続してスタックオーバーフローを引き起こす

gccは逆転の発想で最初に、その関数で呼び出す関数の引数の上限だけ
espレジスタを減算してスタック領域を確保している。
室内で一番大きい置物の高さに天井を合わせればその上の階も立てるという仕組みらしい。

void func()
{
int p1_wrk, p2_wrk; //←これが上の階までの距離でコンパイラが確保
int p1, p2, p3;
func2(p1, p2);//p1_wrk←p1, p2_wrk←p2
func3(p3);//p1_wrk←p3
}


さらに言うと、もはやpushでなくてもいいから
引数の個数だけespレジスタをずらす必要もない。

逆に言うと、上の階の人に何もしてほしくないため
stdcallにすると天井を降ろされた場合、上げ直して
上限を確保しなおすというオーバーヘッドが発生する。

逆転の発想は・・コストまで逆転する。
stdcallはクリーンアップが呼出回数×2回発生し
cdeclは発生しなくなる。

いつからなんだろう。
あまりにもpush&popが出回りすぎてこの大きな違いに気付くのが難しかった。
PR
【2012/02/26 20:21 】 | C/C++ | 有り難いご意見(2)
<<CにもVMあったんだ~ | ホーム | Singleton Shell>>
有り難いご意見
無題
思い出せませんが(何を(汗))

FORTRANの呼び出し構造も?


  ヒットしねぇとぼやいてみる( ̄▽ ̄;
【2012/03/01 21:38】| URL | ゼンガイチ #2ac026978f [ 編集 ]


無題
cdeclで呼び出せそうなので
きっと関数側は何もしない。

fortran側はどうなんだろう。。
www.mlab.ice.uec.ac.jp/~ej-sib/prog/prog_mixed.html
【2012/03/01 21:56】| | nwpfh #29ef1c77e8 [ 編集 ]


貴重なご意見の投稿















前ページ | ホーム | 次ページ

忍者ブログ [PR]