2012-05-20 5 views
8

多くの機能の前にfastcallの表記が追加されています。それはなぜ使用されますか? fastcall題しvisualcで使用されるfastcallキーワードは何ですか?

+1

これはCのものではなく、MSVCのものです。 –

+1

CxPなしでMSVCを綴ることはできません – Mehrdad

+7

これを閉じると投票した人には:これは本当の質問ではありません。はい、それは要点ですが、それは間違いありませんが、確かに非常に明確な答えではっきりとした質問です。 –

答えて

21

この関数の前の表記は、「呼び出し規約」と呼ばれます。コンパイラが入力パラメータを関数に渡し、その結果が実行されるとその結果を取り出す方法を(低レベルで)指定します。

多くの異なる呼び出し規約があります。最も一般的なものはstdcallcdeclです。

実際には1つの方法しかないと思うかもしれませんが、実際には関数を呼び出して変数を渡すことができます。入力パラメータをスタックに置くことができます(push、push、push to call、pop、pop、popは入力パラメータを読み込みます)。あるいは、あなたはむしろそれらをレジスタに張り付けることになります(これはfastcallです - それは速度のためにいくつかの入力パラメータをレジスタに収めようとします)。

しかし、注文についてはどうですか?それらを左から右に、または右から左に押しますか?結果はどうでしょうか?常に(参照パラメータがないと仮定して)1つしかないので、結果をスタック、レジスタ、特定のメモリアドレスに配置しますか?

また、通信にスタックを使用しているとします。つまり、関数が呼び出された後に呼び出し元または呼び出し先が実際にスタックをクリアするのは誰ですか?

(特定の)CPUレジスタの内容をバックアップしてから元の状態に戻すのはどうですか?呼び出し元がそれを行う場合、または呼び出し先がすべての状態を返すことを保証しますか?

最も一般的な呼び出し規約(これまでのところ)はcdeclで、これはCとC++の両方で標準的な呼び出し規約です。 WIN32 APIはstdcallを使用します。つまり、WIN32 APIを呼び出すコードでは、これらの関数呼び出しにstdcallを使用する必要があります。

fastcallは、1つの入出力パラメータで多くの関数で実現されていますが、メモリベースのスタックからのプッシュとポッピングは非常にオーバーヘッドであり、関数呼び出しを少し重くするので、異なるコンパイラは、より良いパフォーマンスのためにスタックに残りを配置する前にレジスタに1つまたは複数のパラメータを配置する呼び出し規約を導入しました(異なる)。問題は、すべてのコンパイラがどこに行き、どこで誰が何をするのかについて同じルールを使用しているわけではありません。その結果、誰が何をするのかわからないため、使用する際に注意する必要があります。最後に、fastcallのパフォーマンス上の利点に関する情報については、Is fastcall really faster?を参照してください。

複雑なもの。

重要なこと:覚えていない場合は、正確にの呼び出し元と呼び出し先の両方が呼び出し規約で一致しないため、呼び出し規約を追加または変更しないでください。あなたはたぶんスタックの破損とsegfaultで終わるでしょう。これは通常、関数がDLL /共有ライブラリで呼び出され、特定の呼び出し規約(たとえばcdecl)であるDLL/SO/dylibに依存するプログラムが記述され、ライブラリが異なる呼び出しで再コンパイルされたときに発生します(例えば、fastcall)。これで古いプログラムは新しいライブラリと通信できなくなりました。

2

Wikipedia states that

表記は標準化されていない、とコンパイラのベンダーに依存し、異なる方法で実装されています。典型的には、ファストコール呼び出し規約は、レジスタに1つまたは複数の引数を渡し、呼び出しに必要なメモリアクセスの数を減らします。