现在的位置: 首页 > 综合 > 正文

cdecl和stdcall等函数调用约定(function call convention)的区别与联系

2013年08月28日 ⁄ 综合 ⁄ 共 1173字 ⁄ 字号 评论关闭

我们知道,函数调用是靠栈来实现的,编译器帮助我们做了压栈和恢复堆栈工作,使我们在调用任一个函数时,都不用进行压栈和恢复堆栈工作。而又由于实现的方式很多,那我们怎么告诉编译器按照哪种方式呢?


答案是函数调用约定(function
call convention).


函数调用约定(function
call convention)是什么?

 
  函数调用约定本质上是告诉编译器怎么把高级语言编译成汇编代码。

这里编译器要解决几个问题:

 
  1 决定参数的压栈顺序的问题。如果函数的参数多于一个,是按照从右向左的顺序压栈,还是其它。

 
  2 谁来负责函数调用堆栈恢复的问题。是调用者还是函数自身去恢复?


首先我们先来看一下cdecl方式,这是C/C++语言的默认处理方式。cdecl告诉编译器,参数要从右向左压栈,并且调用者负责恢复堆栈(正式因为这个,才能实现可变参数,support
variable parameter length,参考http://blog.csdn.net/hongchangfirst/article/details/8765549,也是因为这个,二进制体积比较大)。

在C/C++中,我们可以这样使用cdecl

int __cdecl f(int a, int b);

其实,cdecl可以省略,因为这是默认的方式。


对于stdcall方式,这是pascal的处理方式,stdcall告诉编译器,参数要从右向左压栈,并且函数自身恢复堆栈。

对于函数f,我们可以改变其调用约定:

int __stdcall f(int a, int b);

至于stdcall,还有另外一项说明,即告诉编译器怎么处理函数名:前加下划线,后加@,之后跟参数总大小,如上述函数f,就变成了_f@8。

cdecl和stdcall最大的区别就是cdecl是由调用者恢复堆栈,而stdcall由函数自身恢复堆栈。它们都是函数调用约定的一种方式。


常见的其它函数调用约定有:

  fastcall 
  thiscall 


fastcall和stdcall差不多,区别是,fastcall规定第一第二的比双字节小的参数通过寄存器传递,而不通过压栈的方式。


thiscall是C++中成员函数默认的调用约定。由于成员函数还有一个this指针,它也是参数的一部分,所以必须特殊处理。

它是这样的方式:

1 参数从右向左入栈。

2 如果参数个数确定,this指针通过ecx传递给函数,并且函数自己恢复堆栈,类似stdcall方式。

3 如果参数个数不确定,this指针在所有参数压栈后被压入堆栈,这相当于 T* const this是第一个参数,调用者恢复堆栈,类似cdecl方式。


转载请注明出处:

原文:http://blog.csdn.net/hongchangfirst/article/details/8765549

作者:hongchangfirst



抱歉!评论已关闭.