您的位置:首页 > 其它

函数调用约定:_stdcall,_cdecl,_fastcall

2008-02-25 10:47 411 查看
(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 函数自己处理 左->右
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: