x86 x64调用约定及传参顺序
x86平台下的调用约定
_cdecl __fastcall与 __stdcall,三者都是调用约定(Calling convention),它决定以下内容:
1)函数参数的压栈顺序
2)由调用者还是被调用者把参数弹出栈
3)以及产生函数修饰名的方法。
1、__stdcall调用约定:
__stdcall是Windows API默认调用约定,微软的WINAPI、CALLBACK等宏都是这个调用约定
函数的参数自右向左通过栈传递,被调用的函数在返回前清理传送参数的内存栈,
2、__cdecl:
__cdecl是C/C++的默认调用约定,如果不显示声明调用约定的情况下,就是该调用约定。
函数的参数自右向左通过栈传递,每一个调用它的函数都包含清理堆栈的代码,所以产生的可执行文件大小会比调用_stdcall函数的大。
注意:对于可变参数的成员函数,始终使用__cdecl的转换方式。
3、__fastcall调用约定:它是通过自右向左寄存器传参(实际上,它用ECX和EDX传送前两个双字(DWORD)或更小的参数,剩下的参数仍旧自右向左压栈传送,被调用的函数在返回前清理传送参数的内存栈)。
x64平台下的调用约定
x64平台取消了上文的_cdecl __fastcall __stdcall这些调用约定。而传参是寄存器和栈相结合实现。
优先寄存器传参. 前4个参数分别是 rcx rdx r8 r9进行传参.多余的通过栈传参.从右向左入栈.
函数传参顺序
32位函数入栈传参
从右到左依次入栈
64位函数寄存器传参
前四个参数从左到右依次入寄存器:rdx, rcx, r8, r9, 后面的依次从 右向左 入栈(和32位汇编一样)