为什么Windows x64调用约定不使用XMM寄存器传递超过4个整数args?

时间:2011-06-08 06:21:22

标签: windows assembly x86-64 sse calling-convention

(Microsoft)x64 calling convention声明:

  

参数在寄存器RCX,RDX,R8和R9中传递。如果参数是float / double,则它们在XMM0L,XMM1L,XMM2L和XMM3L中传递。

那很好,但为什么只是漂浮/双打?为什么不通过XMM寄存器传递整数(也可能是指针)? 看起来有点浪费可用空间,不是吗?

2 个答案:

答案 0 :(得分:6)

因为非FP值(即整数和地址)上的大多数操作被设计为使用通用寄存器。

存在整数SSE操作,但它们只是算术算法。

因此,如果调用约定支持通过SSE寄存器传递整数和地址,则几乎总是需要将值复制到通用寄存器。

答案 1 :(得分:2)

函数通常希望将整数参数指针一起使用(作为索引,或者将终点指针计算为循环绑定),或者与GP寄存器中的其他整数args一起使用。或与其他要在GP寄存器中使用的从内存加载的整数

您不能在XMM reg中有效地使用整数作为循环计数器或绑定计数器,因为没有打包整数比较为分支指令设置整数标志。 (pcmpgtd创建一个0 / -1元素的掩码。

另请参见Why not store function parameters in XMM vector registers?和此处的其他答案。


但是,除此之外,Windows x64快速调用/矢量调用甚至都没有这种设计思想。

Windows x64选择浪费空间以简化可变参数功能。可以将寄存器args转储到返回地址上方的32字节“影子空间” /“本地空间”中,以形成args数组。

这就是为什么(例如)Windows x64在R8或XMM2中传递第三个arg的原因,而与早期args的类型无关。为什么调用可变参数的函数也需要将FP args复制到相应的整数寄存器,所以函数序言可以转储arg reg,而无需弄清楚哪个可变参数arg是FP,哪些是整数。

为使arg数组工作正常,无论您是否将整数和FP arg混合使用,寄存器中只能传递总共4个arg。有足够的GP整数寄存器可容纳寄存器args的最大数量,即使它们都是整数也是如此。


(与x86-64 System V不同,无论使用多少个整数/指针arg传递寄存器,第一个最多8个FP args都在xmm0..7中传递。)

Why does Windows64 use a different calling convention from all other OSes on x86-64?