C/C++函数的调用约定(MS VC)

来源:互联网 发布:java 监听器 编辑:程序博客网 时间:2024/04/29 14:54



1. __cdecl (the default)  
这是缺省的C/C++函数调用约定,和其他的调用约定最大的不同是
堆栈由调用者caller维护,因此相比__stdcall和__fastcall该调用约定生成的
可执行文件将偏大;
在ARM和X64环境下,函数参数也会尽量采用寄存器方式传递;

函数名称修饰方式: 在函数名称前加前导的下划线'_'
变长参数的函数一般采用该调用约定

当编译器选项指定/Gd(默认为该选项)时,所有的函数采用该调用约定;

2. __stdcall   
如果编译器指定/Gz编译选项,则所有的函数如果没有特殊指定其他调用约定,默认为__stdcall

该调用约定在VC环境下定义为
#define WINAPI __stdcall
#define APIENTRY    WINAPI
#define PASCAL      __stdcall

采用该调用约定时,堆栈由被调用者callee负责清理,所有当传递参数占用堆栈时,
最后由被调用者负责弹出这些参数;

编译器名称修饰规则:
在函数名前面加下划线'_',后面跟'@'符号,再加上十进制的函数形参大小
如:  int func(float a, double b) 修饰后为: _func@12

3. __fastcall  
该调用约定仅适用于X86, X64, ARM体系架构的编译器,
采用该调用约定时,函数调用时,会将一定数量的形参采用寄存器传递,加快函数的调用速度;
在VC环境下,当指定/Gr编译选项时,所有的函数调用如果没有特殊指定其他调用约定,都采用__fastcall调用
约定(main函数比较特殊,将不采用该调用约定)
如:
X86编译器将形参最左边两个大小不超过DWORD的参数使用ECX, EDX寄存器传递,剩下的参数从右到左依次压入堆栈传递;
X64编译器的前4个参数采用寄存器传递(整形通过 RCX, RDX, R8, and R9寄存器,如果是float或double,则通过XMM0L, XMM1L, XMM2L,

and XMM3L四个寄存器传递)

采用这种调用方式时,堆栈维护方式同__stdcall由被调用者callee负责清理;

编译器名称修饰类似__stdcall但是前导的'_'在__fastcall时变为‘@’

4. __thiscall
C++成员函数默认的调用约定
采用该调用约定时,由被调用函数(callee)清理堆栈;
所有的函数形参中this指针通过ECX寄存器传递,其他的参数从右到左通过堆栈传递;





0 0