質問

多くの関数の前にfastcall表記法を追加しました。なぜ使われるのか?

役に立ちましたか?

解決

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

多くの異なる呼び出し規則があり、最も人気のあるものはstdcallcdeclです。

あなたはそれをする方法が1つしかないと思うかもしれませんが、実際には、関数を呼び出して変数を出し入れにすることができる数十の方法があります。入力パラメータをスタックに配置することができます(PUSH、PUSH、呼び出しに押し込む; POP、POP、POP、入力パラメータを読み取る)。またはおそらくあなたはそれらをレジスタに貼り付けるでしょう(これはfastcallです - それは速度のためにレジスタの入力パラメータのいくつかをフィットしようとします)。

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

また、通信用のスタックを使用しているとしましょう - 誰がジョブの仕事が呼び出された後にスタックをクリアするのか - 発信者または着信者は?

バックアップについて(特定の)CPUレジスタの内容を復元してから、発信者が実行する場合、またはCalleeがそれがあった方法を返すことを保証しますか?

最も一般的な呼び出し規約(遠く)はcdeclです。これはCとC ++の両方で標準的な呼び出し規約です。 Win32 APIはstdcallを使用します。つまり、Win32 APIを呼び出すコードは、それらの関数呼び出しに対してstdcallを使用する必要があるコードを意味します(もう1つの一般的な選択)。

fastcallは奇妙なボールのビットである - メモリベースのスタックからのプッシュおよびポップを持つ多くの関数のために実現された人々はかなりのオーバーヘッドで、関数が少し重いので関数を呼び出すパフォーマンスを向上させるためにスタックに残りを配置する前に、1つ以上のパラメータをスタックに配置する前に、1つ以上のパラメータをレジスタに配置するようにするコンパイラが紹介されました。問題は、fastcallと同じルールを使用したのと同じルールを使用しているわけではなく、その結果としてそれを使用するときに注意しなければならないのに対して、あなたがそれを使用するときに注意しなければならないのです。最後に、は本当に速いですか?

複雑なもの

留意することが重要な何か:あなたがを知らないならば、あなたがを知らないならば、あなたがやっていること、呼び出し元と着信者の両方が同意しないならば呼び出し規約は、スタック破損とSEGFAULTに進むでしょう。これは通常、DLL /共有ライブラリで呼び出されている機能がある場合に発生し、DLL / SO / DYLIBが特定の呼び出し規約(言っている、fastcall)に依存するプログラムが書き込まれ、その後、ライブラリは別の呼び出しで再コンパイルされます。条約(言う、cdecl)。今古いプログラムは、新しいライブラリと通信できません。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top