Win64 vs System V ABI(x86_64):Win64跳过寄存器?

时间:2017-08-15 18:23:05

标签: c++ c x86-64 abi

假设我们有一个带有以下签名的C(或C ++)函数:

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

在Linux,Mac或使用System V ABI(x86_64)的任何操作系统上编译时,ac传递rdirsibd传递给xmm0xmm1。好的,没错。但是我在Windows(x86_64)中做了同样的事情,看起来它跳过了一些寄存器。 ac传递了rcxr8rdx已跳过),bd被传入{ {1}}和xmm1xmm3xmm0已跳过)。为什么Win64会这样做而不是"压缩" System V这样的论点?使用System V,我想能够传递4个qwords和4个双精度而无需在堆栈上传递任何东西,而Win64,正如我猜测的那样,会传递任何超过堆栈的第4个参数

我知道在Win64与SysV中传递的参数中寄存器的顺序不同,但顺序不应该是相关的。我只是好奇为什么Win64会跳过寄存器,特别是当它只有4个非堆栈参数传递时。

1 个答案:

答案 0 :(得分:2)

Microsoft的文档

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

声明它们在寄存器中传递最多4个参数。如果一个参数不适合特定寄存器,则只跳过该寄存器。

"浮点和双精度参数在XMM0 - XMM3(最多4个)中传递,整数槽(RCX,RDX,R8和R9)通常用于基本槽被忽略(见例),反之亦然。"

链接页面上的示例3正是您的示例,并解释了您所看到的效果:

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

因此,他们最多使用4个寄存器作为参数,RCX或XMM0中的第一个参数,RDX或XMM1中的第二个参数等。

那么为什么这样做呢?将8个寄存器参数传递给函数的想法似乎并不是一个重要的用例。