posts - 200, comments - 8, trackbacks - 0, articles - 0

函数调用约定:_stdcall,_cdecl,_fastcall (转)

Posted on 2012-12-27 11:41 鑫龙 阅读(305) 评论(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             函数自己处理        左->右

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理