调用约定总结
以前做 Function 的时候恰好取巧避免掉了,这些天在做 Bind,不得已要把每个调用约定罗列一遍。顺手把这些东西复习一下,总结如下——
(所有内容针对 VC 编译平台)
一、x86
名称 | 传参方式 | 栈清理 | C 语言函数重命名(例:int func(int, double)) |
__cdecl | 从右至左压栈 | 主调函数 | 前面加“_”(_func) |
__stdcall | 从右至左压栈 | 被调函数 | 前面加“_”,后面加“@”再加参数十进制字节数(_func@12) |
__fastcall | 前两个不大于DWORD长度的参数从左至右分别存到 ECX、EDX,其余从右至左压栈 | 被调函数 | 前面加“@”,后面加“@”再加参数十进制字节数(@func@12) |
__thiscall | ECX 存 this,其余从右至左压栈 | 被调函数 | 仅用于 C++ |
二、x64
名称 | 传参方式 | 栈清理 | |
__fastcall | 前四个整数/浮点数放在 RCX/XMM0、RDX/XMM1、R8/XMM2、R9/XMM3,其余压栈。 如果前 4 个参数分别为 int、float、long、double,它们将分别被存到 RCX、XMM1、R8、XMM3 | 被调函数 |
64位编译环境下,可以指定 __cdecl、__stdcall、__fastcall,但是编译器会忽略它们。两个显示指定了不同调用约定的函数不构成重载,而构成重定义错误。