函数调用方式的区别详解
来源:优易学  2011-12-11 16:24:43   【优易学:中国教育考试门户网】   资料下载   IT书店
 通常在使用VC进行函数定义时会指定该函数调用方式,诸如:

  int __stdcall max(int a, int b)

  {

  return a>b?a:b;

  }

  int __cdecl min(int a, int b)

  {

  return a<b?a:b;

  }

  bool __fastcall equal(int a, int b)

  {

  return a=b?true:false;

  }

  首先,让我们来分个类,调用方法分为两大类另加一个较特殊的__thiscall.

  第一类:__stdcall类  别名:WINAPI,CALLBACK,PASCAL。该类特点是:主调函数负责参数入栈,由函数本身负责栈的恢复.

  第二类:__cdecl类    别名:C/C++中默认调用方式,若你定义函数未指定函数调用约定(Calling Conventions),例如在VC6中下面两个函数的调用约定是等价的:

  int max(int a, int b)

  {

  return a>b?a:b;

  }

  int __cdecl min(int a, int b)

  {

  return a<b?a:b;

  }

  该类调用约定的特点是:由主调函数负责参数入栈,并由主调函数负责线的恢复.

  第三类:__thiscall 该类比较特殊,只用于类成员函数调用,你甚至不能强制指定这个函数调用约定。它是由C/C++编译器自动添加的。在C/C++中类成员函数会默认传入一个this指针,对于此,在默入情况下,C/C++中类成员函数通过此类调用约定来指定this指针.

  接着介绍一下__thiscall,__thiscall是关于类的一种调用方式.

  它与其他调用方式的最大区别是:

  __thiscall对每个函数都增加了一个类指针参数

  class   aa

  {

  void   bb(int   cc);

  };

  实际上bb的函数原形是void   bb(aa   &this,   int   cc);

  __cdecl的调用方式介绍: C和C++缺省调用方式

  例子:

  void   Input(   int   &m,int   &n);/*相当于void   __cdecl   Input(int   &m,int   &n);*/

  以下是相应的汇编代码:

  00401068 lea eax,[ebp-8] ;取[ebp-8]地址(ebp-8),存到eax

  0040106B push eax ;然后压栈

  0040106C lea ecx,[ebp-4] ;取[ebp-4]地址(ebp-4),存到ecx

  0040106F push ecx ;然后压栈

  00401070 call @ILT+5(Input) (0040100a);然后调用Input函数

  00401075 add esp,8 ;恢复栈

  从以上调用Input函数的过程可以看出:在调用此函数之前,首先压栈ebp-8,然后压栈ebp-4,然后调用函数Input,最后 Input函数调用结束后,利用esp+8恢复栈。由此可见,在C语言调用中默认的函数修饰_cdecl,由主调用函数进行参数压栈并且恢复堆栈。

  下面看一下:地址ebp-8和ebp-4是什么? 在VC的VIEW->debug  windows->Registers,显示寄存器变量值,然后在选debug  windows->Memory,输入ebp-8的值和ebp-4的值(或直接输入ebp-8和-4),看一下这两个地址实际存储的是什么值,实际上是变量"n "的地址(ebp-8),m的地址(ebp-4).

  由此可以看出:在主调用函数中进行实参的压栈并且顺序是从右到左。另外,由于实参是相应的变量的引用,也证明实际上引用传递的是变量的地址(类似指针)。

  总结:在C或C++语言调用中默认的函数修饰_cdecl,由主调用函数进行参数压栈并且恢复堆栈,实参的压栈顺序是从右到左,最后由主调函数进行堆栈恢复。由于主调用函数管理堆栈,所以可以实现变参函数。另外,命名修饰方法是在函数前加一个下划 线(_).

  _stdcall调用约定介绍:实际上就是PASCAL,CALLBACK,WINAPI

  例子:

  void   WINAPI   Input(   int   &m,int   &n);

  看一下相应调用的汇编代码:

  00401068 lea eax,[ebp-8]

  0040106B push eax

  0040106C lea ecx,[ebp-4]

  0040106F push ecx

  00401070 call @ILT+5(Input) (0040100a)

[1] [2] 下一页

责任编辑:小草

文章搜索:
 相关文章
热点资讯
资讯快报
热门课程培训