我々は、以下の署名で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
およびd
がxmm0
およびxmm1
に渡されます。さて、何も間違っていません。しかし、私はWindows(x86_64)でも同じことをしており、いくつかのレジスタをスキップするように見えます。 a
とc
(rdx
はスキップ)rcx
とr8
に渡される、とb
とd
はxmm1
とxmm3
に渡されます(xmm0
とxmm2
はスキップ)。なぜ、Win64はSystem Vのような引数を「圧縮」する代わりにこれを行いますか? System Vでは、スタック上に何も渡す必要なく、例えば4つのqwordsと4つのdoubleを渡すことができると想像していますが、Win64はスタック上の4番目の引数を超えて何かを渡します。
私はWin64とSysVの引数渡しのレジスタの順序の違いに気付いていますが、順序は関係ありません。 Win64がレジスタをスキップする理由について興味があります。特に、スタック以外の引数を渡すために4つしかない場合は特にそうです。
全く違うabi、私は古いabiがfastcallと呼ばれていたと思うと思います。約64ビットはわかりません...私はそれが異なっていることを知っています... –
答えが少し難しいですが、最終的なデザイナーは本当にその理由を知っています – harold
Win64 ABIはレジスタ内に最大4つの整数/ポインタ引数を渡しますが、System V ABIはレジスタを6つまで渡します(https://en.wikipedia.org/を参照)。 wiki/X86_calling_conventions)。 Win64の目的に使用されている4つは、System Vで使用されている6つのうちのすべてです。Win64のABI *スキップ*レジスタはそれほど適切ではないと言えるでしょう。しかし、なぜそれがそうするのかについては、あなたがここで説明することを疑う。 –