Posted on 2012-12-27 11:41
鑫龙 阅读(322)
评论(0) 编辑 收藏 引用 所属分类:
c++
(1) _stdcall调用
_stdcall 是Standard Call的缩写,是C++的标准调用方式,也是Pascal程序的缺省调用方式,参数采用从右到左的压栈方式,如果是调用类成员的话,最后一个入栈的是this指针。这些堆栈中的参数由被调函数自身在返回前清空,
使用的指令是 retn X,X表示参数占用的字节数,CPU在ret之后自动弹出X个字节的堆栈空间。称为自动清栈。
WIN32 Api都采用_stdcall调用方式,这样的宏定义说明了问题:
#define WINAPI _stdcall
按C编译方式,_stdcall调用约定在输出函数名前面加下划线,后面加“@”符号和参数的字节数,形如_functionname@number。
(2) _cdecl调用
_cdecl是C Declaration[声明]的缩写,表示C/C++语言默认的函数调用方法,也是C/C++的缺省调用方式,所有参数从右到左依次入栈,这些参数由调用者清除,称为手动清栈。_cedcl约定的函数只能被C/C++调用,每一个调用它的
函数都包含清空堆栈的代码,所以产生的可执行文件大小会比调用_stdcall函数的大。被调用函数无需要求调用者传递多少参数,调用者传递过多或者过少的参数,甚至完全不同的参数都不会产生编译阶段的错误。
由于_cdecl调用方式的参数内存栈由调用者维护,所以变长参数的函数能(也只能)使用这种调用约定。
由于Visual C++默认采用_cdecl 调用方式,所以VC中中调用DLL时,用户应使用_stdcall调用约定。
按C编译方式,_cdecl调用约定仅在输出函数名前面加下划线,形如_functionname。
(3) _fastcall调用
_fastcall 是编译器指定的快速调用方式。由于大多数的函数参数个数很少,使用堆栈传递比较费时。因此_fastcall通常规定将前两个(或若干个)参数由寄存器传递,其余参数还是通过堆栈传递。不同编译器编译的程序规定的寄
存器不同。返回方式和_stdcall相当。
_fastcall调用较快,它通过CPU内部寄存器传递参数。
(4)PASCAL调用
PASCAL 是Pascal语言的函数调用方式,也可以在C/C++中使用,参数压栈顺序与_cdecl和_stdcall相反。
归纳如下:
调用约定 入栈参数清理 参数入栈顺序
----------- -------------- ----------------
cdecl 调用者处理 右->左
stdcall 函数自己处理 右->左
fastcall 函数自己处理 依赖于编译器
pascal 函数自己处理 左->右