2017-08-15 4 views
1

我々は、以下の署名でC(またはC++)関数があるとします。Win64 vs System V ABI(x86_64):Win64レジストリをスキップしていますか?

void foo(int64_t a, double b, int64_t c, double d); 

Linuxでは、マック、またはシステムV ABI(x86_64版)を使用して任意のOS、a上でコンパイルし、cが渡さ取得するときrdiおよびrsiレジスタ、およびbおよびdxmm0およびxmm1に渡されます。さて、何も間違っていません。しかし、私はWindows(x86_64)でも同じことをしており、いくつかのレジスタをスキップするように見えます。 acrdxはスキップ)rcxr8に渡される、とbdxmm1xmm3に渡されます(xmm0xmm2はスキップ)。なぜ、Win64はSystem Vのような引数を「圧縮」する代わりにこれを行いますか? System Vでは、スタック上に何も渡す必要なく、例えば4つのqwordsと4つのdoubleを渡すことができると想像していますが、Win64はスタック上の4番目の引数を超えて何かを渡します。

私はWin64とSysVの引数渡しのレジスタの順序の違いに気付いていますが、順序は関係ありません。 Win64がレジスタをスキップする理由について興味があります。特に、スタック以外の引数を渡すために4つしかない場合は特にそうです。

+0

全く違うabi、私は古いabiがfastcallと呼ばれていたと思うと思います。約64ビットはわかりません...私はそれが異なっていることを知っています... –

+1

答えが少し難しいですが、最終的なデザイナーは本当にその理由を知っています – harold

+0

Win64 ABIはレジスタ内に最大4つの整数/ポインタ引数を渡しますが、System V ABIはレジスタを6つまで渡します(https://en.wikipedia.org/を参照)。 wiki/X86_calling_conventions)。 Win64の目的に使用されている4つは、System Vで使用されている6つのうちのすべてです。Win64のABI *スキップ*レジスタはそれほど適切ではないと言えるでしょう。しかし、なぜそれがそうするのかについては、あなたがここで説明することを疑う。 –

答えて

2

Microsoftのドキュメント

https://docs.microsoft.com/sv-se/cpp/build/parameter-passing

は、彼らがレジスタ内で最も4つのパラメータを渡すと述べています。 1つのパラメータが特定のレジスタに収まらない場合、そのレジスタはスキップされます。

"浮動小数点と倍精度の引数は、通常、無視されるその基本スロットに使用される整数スロット(RCX、RDX、R8、およびR9)とともにXMM0〜XMM3で渡されます(例を参照)、その逆も同様です。リンク先のページの

例3は、まさにあなたの一例であり、あなたが見てきた効果を説明しています

func3(int a, double b, int c, float d);  
// a in RCX, b in XMM1, c in R8, d in XMM3 

だから彼らはRCXまたはXMM0のいずれかのパラメータ、最初のパラメータのための4個のレジスタまで使用しています、 RDXまたはXMM1などの2番目のパラメータ

なぜこのようにするのですか?おそらく、8つのレジスタパラメータを関数に渡すという考えは、重要なユースケースのようには思えませんでした。

+0

Windowsが確かにオペレーティングシステムを冗談にしていないので、このレジスタのスキップ動作がパフォーマンスに何の影響も与えないかどうか不思議です。 –

+2

これは、パラメータのホームスペースの量が可変であることを意味し、バリデーション機能を実装するのがずっと難しくなります。 –

関連する問題