Microsoftがx64 abiを手直ししていることは明らかです。彼らが何をしたのか、そしていつははっきりとはっきりしていないのか、ドキュメンテーションは不完全で、ばらばらになっていて、日付が間違いです。私は個人的にAgner Fogによって行われたreverse-engineering workを本当に信頼できる情報源とみなしています。しかし、マネージドコードの生成には取り組んでいません。
これが4.5で変更されたという主張は、むしろ信じられないほどです。より多くの可能性があるのは、これはRyuJIT(新しいx64ジッタ)で変更されました。これは、かなりバグがあり、維持できないレガシーx64ジッタを置き換えます。もともと4.5.3としてプレビューされ、おそらく4.5の主張を説明していましたが、後で4.6に増加しました。この変更の可能性が高いのは、.NETCoreプロジェクトです.UNIXコードジェネレータ(GNUとLLVM)とのMicrosoft x64 abiの違いはかなり苦しいです。
しかし、C++コンパイラコードジェネレータの変更(Agner Fog、gackによるVS2015アップデートで修正)とは異なり、この変更はかなり壊れそうにありません。不一致はピンボケでのみ発生する可能性があり、ジッタは決してCallingConventionをサポートしませんでした。幸いにも、あなたの質問は簡単に答えることができます:
バッファの意味は?
これは、「集約タイプ」を返すメソッドに対してのみ重要です。言い換えれば、CPUに合わない値はもはやレジスタになります。 struct
であるC#では、(2人以上のメンバーまたは非自明なフィールドタイプである)それほど重要ではないというさらなる規定があります。
メソッド呼び出し側は、戻り値( "バッファ")のスタックフレームに領域を割り当て、その領域にポインタを渡す必要があります。そのポインタは、隠された余分な引数としてメソッドに渡されます。伝統的に最初の引数、隠されたthis
引数の前。これはthis
を2番目の引数にしたため、RCXレジスタの代わりにRDXレジスタを通過しました。変更により、順序が逆になります。this
は常に最初の引数でRCXに渡され、戻り値ポインタは2番目です。呼び出されたメソッドは、戻り値が返される前にそのバッファに戻り値をコピーします。
どのように静的方法に、我々は静的クラスを使用する場合
についてのみ該当します。余分な隠されたthis
の引数がないので、単に省略されます。これまでのやり方から効果的に変更はありません。隠れた戻り値ポインタは常に自動的に第1引数であり、したがってRCXに渡されます。
この場合、デバッガの[デバッグ]> [Windows]> [逆アセンブリ]ウィンドウを必ず利用してください。小さなテストプログラムで実行すると、どのレジスタが使用されているかが簡単にわかります。
リターンバッファは、x64呼び出し規約のMSDNドキュメントの[Return Values](https://msdn.microsoft.com/en-us/library/7572ztz4.aspx)に記載されています。*それ以外の場合、呼び出し元はメモリを割り当て、最初の引数として戻り値のポインタを渡す責任があります。 –