x64 调用约定,参数传递以及函数返回值

从 x86 到 x64 的两个重要修改是:64 位寻址功能和一组平面的用于常规使用的 16 个 64 位寄存器。对于展开的寄存器集,x64 仅使用 __fastcall 调用约定和基于 RISC 的异常处理模型。__fastcall 模型使用寄存器(对前四个变量)和堆栈帧传递其他参数。


调用约定

x64 应用程序二进制接口 (ABI) 是一个 4 寄存器快速调用调用约定,具有用于这些寄存器的堆栈后备功能。函数中的参数与这些参数的寄存器之间有一对一的对应关系。任何大于 8 个字节或不是 1、2、4 或 8 个字节的参数必须由引用传递。不尝试将单个参数在多个寄存器间传播。没有使用 x87 寄存器堆栈。可以使用它,但是必须认为它在函数调用之间是易失性的。所有浮点操作都是使用 16 个 XMM 寄存器完成的。参数在寄存器 RCX、RDX、R8 和 R9 中传递。如果参数是浮点/双精度型,则它们在 XMM0L、XMM1L、XMM2L 和 XMM3L 中传递。16 字节的参数由引用传递。 参数传递中详细描述了参数传递。除这些寄存器外,RAX、R10、R11、XMM4 和 XMM5 也是易失性的。其他所有寄存器都是非易失性的。 寄存器使用和 由调用方或被调用方保存的寄存器中详细记录了寄存器用法。

调用方负责为被调用方的参数分配空间,并且必须始终为 4 个寄存器参数分配足够的空间,即使被调用方没有这么多参数。这有助于简化对 C 非原型函数和 vararg C/C++ 函数的支持。对于 vararg 或非原型函数,任何浮点值都必须在相应的常规用途的寄存器中复制。超过前 4 个的任何参数必须存储在堆栈上,位置在前 4 个的后备存储器之上,在调用之前。 Varargs 中提供了 Vararg 函数的详细信息。 非原型函数中提供了关于非原型函数的详细信息。

参数传递

前四个整型参数将被传入寄存器中。整数值将被传入 RCX、RDX、R8 和 R9 中(按从左至右的顺序)。前四个参数及后面的参数将传递到堆栈中。在寄存器中,所有参数都是右对齐的。因此,被调用方可以根据需要忽略寄存器中上面的位,并且只访问所需的寄存器部分。

浮点型和双精度参数传入 XMM0、XMM1、XMM2、XMM3(最大可达 4 个)中,并忽略常用于该基槽的整型槽(RCX、RDX、R8 和 R9)(请参见 示例),反之亦然。

__m128 类型、数组和字符串从来不按即时值进行传递,但会向调用方分配的内存中传递指针。大小为 8、16、32 或 64 位的结构/联合以及 __m64 将被视为具有相同大小的整数进行传递。其他大小的结构/联合将作为指针传递到调用方分配的内存中。对于这些作为指针(包括 __m128)传递的聚合类型,调用方分配的临时内存将是 16 字节对齐的。

由于编译器与内部函数实现之间存在紧密的绑定,因此不分配堆栈空间且不调用其他函数的内部函数可以使用其他易失寄存器来传递附加的寄存器参数。这样便可以进一步改进性能。

被调用方负责根据需要将寄存器参数转储到它们的阴影空间中。

下表总结了传递参数的方式:


参数类型                传递方式

浮点
前 4 个参数传入 XMM0、XMM1、XMM2 和 XMM3 中。其他参数传递到堆栈中。

整数
前 4 个参数传入 RCX、RDX、R8 和 R9 中。其他参数传递到堆栈中。

聚合(8、16、32 或 64 位)和 __m64

前 4 个参数传入 RCX、RDX、R8 和 R9 中。其他参数传递到堆栈中。

聚合(其他)

通过指针传递。前 4 个参数作为 RCX、RDX、R8 和 R9 中的指针传递

__m128

通过指针传递。前 4 个参数作为 RCX、RDX、R8 和 R9 中的指针传递


函数返回值

适合于 64 位的返回值是通过 RAX 返回的(包括 __m64 类型),但 __m128、 __m128i、 __m128d、浮点值和双精度值除外,它们是在 XMM0 中返回的。如果返回值不适合于 64 位,则由调用方为返回值分配指针并将其作为第一个参数传递。然后,后续参数将向右侧移动一个参数的位置。RAX 中的被调用方必须返回相同的指针。要返回的用户定义类型的长度必须为 1、2、4、8、16、32 或 64 位。
  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值