c++ - Win64 与 System V ABI (x86_64) : Win64 Skipping registers?

标签 c++ c x86-64 calling-convention abi

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

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

在 Linux、Mac 或任何使用 System V ABI (x86_64) 的操作系统上编译时,acrdi 中获得通过和rsi寄存器,和bd传入xmm0xmm1 。好吧,这没什么问题。但后来我在 Windows (x86_64) 中做了同样的事情,看起来它跳过了一些寄存器。 ac传入rcxr8 ( rdx 已跳过)和 bd传入xmm1xmm3 (xmm0xmm2 已跳过)。为什么 Win64 这样做而不是像 System V 那样“压缩”参数?对于 System V,我想象能够传递 4 个 qword 和 4 个 double ,而不需要传递堆栈上的任何内容,而 Win64,正如我猜测的那样,会传递堆栈上第四个参数之后的任何内容。/p>

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

最佳答案

微软的文档

https://learn.microsoft.com/en-us/cpp/build/x64-calling-convention?view=msvc-160

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

“浮点和 double 参数在 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 个寄存器参数传递给函数的想法似乎不是一个重要的用例。

关于c++ - Win64 与 System V ABI (x86_64) : Win64 Skipping registers?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45699107/

相关文章:

c++ - 第一次用户的 devc++ 编译错误

linux - x86-64 System V ABI 记录在哪里?

c++ - 静态 libstdc++.a 中的全局符号在共享 libstdc++.so 中是局部的

比较C中的多个字符

c - 查找缓存性能

c - 从字符串读取大小后分配大小为 'n' 的缓冲区

c++ - 为什么除了最后一帧之外,反汇编的每一帧都没有调用命令

algorithm - 这个求平方根算法的名称是什么?

c++ - 网格类中损坏的顶点数据

c++ - 如何在 Eigen3 中调整 Vector 的大小