函数调用方式__stdecl _stdcall _fastcall __thiscall介绍

   __cdecl 是C DECLaration的缩写(declaration,声明),表示C语言默认的函数调用方法:所有参数从右到左依次入栈,这些参数由调用者清除,称为手动清栈。被调用函数不会要求调用者传递多少参数,调用者传递过多或者过少的参数,甚至完全不同的参数都不会产生编译阶段的错误。

 

_stdcall 是StandardCall的缩写,是C++的标准调用方式:所有参数从右到左依次入栈,如果是调用类成员的话,最后一个入栈的是this指针。这些堆栈中的参数由被调用的函数在返回时清除,使用的指令是 retnX,X表示参数占用的字节数,CPU在ret之后自动弹出X个字节的堆栈空间。称为自动清栈。函数在编译的时候就必须确定参数个数,并且调用者必须严格的控制参数的生成,不能多,不能少,否则返回后会出错。

 

_fastcall 是编译器指定的快速调用方式。由于大多数的函数参数个数很少,使用堆栈传递比较费时。因此_fastcall通常规定将前两个(或若干个)参数由寄存器传递,其余参数还是通过堆栈传递。不同编译器编译的程序规定的寄存器不同。返回方式和_stdcall相当。

 

 

   __thiscall 是为了解决类成员调用中this指针传递而规定的。__thiscall要求把this指针放在特定寄存器中,该寄存器由编译器决定。VC使用ecx,Borland的C++编译器使用eax。返回方式和_stdcall相当。

 

 

  _fastcall 和 __thiscall涉及的寄存器由编译器决定,因此不能用作跨编译器的接口。所以Windows上的COM对象接口都定义为_stdcall调用方式。

 

 

调用类型

参数入栈顺序

由谁负责清栈

寄存器传递

__stdecl

从右到左依次入栈

调用函数

this

_stdcall 

从右到左依次入栈

调用函数

this

_fastcall

从右到左依次入栈

调用函数

this  和参数

__thiscall

从右到左依次入栈

调用函数

this

默认(vs2005)

从右到左依次入栈

调用函数

this

 

 

 

 

 

 

 

 

下面来通过代码来查看一下他们到底是如何传递参数和出入栈:

 

 

[cpp]  view plain  copy  print ?
  1. class TestCallType  
  2. {  
  3. public:  
  4.     int default_call(int ,int);  
  5.     int __cdecl     __cdecl_call(int a, int b);  
  6.     int _stdcall    _stdcall_call(int a, int b);  
  7.     int _fastcall   _fastcall_call(int a, int b);  
  8.     int __thiscall  _thiscall_call(int,int);  
  9.     int x;  
  10. };  
  11. int TestCallType::default_call(int a, int b)  
  12. {  
  13.     this->x = a + b;  
  14.     return this->x;  
  15. }  
  16. int TestCallType::__cdecl_call(int a, int b)  
  17. {  
  18.     this->x = a + b;  
  19.     return this->x;  
  20. }  
  21. int TestCallType::_stdcall_call(int a, int b)  
  22. {  
  23.     this->x = a + b;  
  24.     return this->x;  
  25. }  
  26. int TestCallType::_fastcall_call(int a, int b)  
  27. {  
  28.     this->x = a + b;  
  29.     return this->x;  
  30. }  
  31. int TestCallType::_thiscall_call(int a, int b)  
  32. {  
  33.     this->x = a + b;  
  34.     return this->x;  
  35. }  
 

 

调用的地方反汇编出来如下:

[cpp]  view plain  copy  print ?
  1. int _tmain(int argc, _TCHAR* argv[])  
  2. {  
  3. 004115B0  push        ebp    
  4. 004115B1  mov         ebp,esp   
  5. 004115B3  sub         esp,0CCh   
  6. 004115B9  push        ebx    
  7. 004115BA  push        esi    
  8. 004115BB  push        edi    
  9. 004115BC  lea         edi,[ebp-0CCh]   
  10. 004115C2  mov         ecx,33h   
  11. 004115C7  mov         eax,0CCCCCCCCh   
  12. 004115CC  rep stos    dword ptr es:[edi]   
  13.     TestCallType call_type;  
  14.     call_type.default_call(1, 2);  
  15. 004115CE  push        2                      /* 参数入栈 */  
  16. 004115D0  push        1                      /* 参数入栈 */  
  17. 004115D2  lea         ecx,[call_type]        /* this指针 */  
  18. 004115D5  call        TestCallType::default_call (411113h)   
  19.     call_type.__cdecl_call(1, 2);  
  20. 004115DA  push        2                     /* 参数入栈 */  
  21. 004115DC  push        1                     /* 参数入栈 */  
  22. 004115DE  lea         eax,[call_type]       /* this指针 */  
  23. 004115E1  push        eax    
  24. 004115E2  call        TestCallType::__cdecl_call (41112Ch)   
  25. 004115E7  add         esp,0Ch               /* 调用者负责清栈 */  
  26.     call_type._fastcall_call(1,2);  
  27. 004115EA  push        2                     /* 参数入栈 */  
  28. 004115EC  mov         edx,1                 /* 第一个参数通过寄存器传递 */  
  29. 004115F1  lea         ecx,[call_type]       /* this指针 */  
  30. 004115F4  call        TestCallType::_fastcall_call (41100Ah)   
  31.     call_type._stdcall_call(1,2);  
  32. 004115F9  push        2      
  33. 004115FB  push        1      
  34. 004115FD  lea         eax,[call_type]       /* this指针 */  
  35. 00411600  push        eax    
  36. 00411601  call        TestCallType::_stdcall_call (4110EBh)   
  37.     call_type._thiscall_call(1, 2);  
  38. 00411606  push        2      
  39. 00411608  push        1      
  40. 0041160A  lea         ecx,[call_type]       /* this指针 */  
  41. 0041160D  call        TestCallType::_thiscall_call (41117Ch)   
  42.     return 0;  
  43. 0041161E  xor         eax,eax   
  44. }  
 

 

函数定义的地方反汇编:

[cpp]  view plain  copy  print ?
  1. int TestCallType::default_call(int a, int b)  
  2. {  
  3. 004113D0  push        ebp    
  4. 004113D1  mov         ebp,esp   
  5. 004113D3  sub         esp,0CCh   
  6. 004113D9  push        ebx    
  7. 004113DA  push        esi    
  8. 004113DB  push        edi    
  9. 004113DC  push        ecx    
  10. 004113DD  lea         edi,[ebp-0CCh]   
  11. 004113E3  mov         ecx,33h   
  12. 004113E8  mov         eax,0CCCCCCCCh   
  13. 004113ED  rep stos    dword ptr es:[edi]   
  14. 004113EF  pop         ecx    
  15. 004113F0  mov         dword ptr [ebp-8],ecx   
  16.     this->x = a + b;  
  17. 004113F3  mov         eax,dword ptr [a]   
  18. 004113F6  add         eax,dword ptr [b]   
  19. 004113F9  mov         ecx,dword ptr [this]   
  20. 004113FC  mov         dword ptr [ecx],eax   
  21.     return this->x;  
  22. 004113FE  mov         eax,dword ptr [this]   
  23. 00411401  mov         eax,dword ptr [eax]   
  24. }  
  25. 00411403  pop         edi    
  26. 00411404  pop         esi    
  27. 00411405  pop         ebx    
  28. 00411406  mov         esp,ebp   
  29. 00411408  pop         ebp                   /* 默认调用是_stdcall 被调用函数负责清栈 */  
  30. 00411409  ret         8      
  31. --- No source file -------------------------------------------------------------  
  32.   
  33. int TestCallType::__cdecl_call(int a, int b)  
  34. {  
  35. 00411420  push        ebp    
  36. 00411421  mov         ebp,esp   
  37. 00411423  sub         esp,0C0h   
  38. 00411429  push        ebx    
  39. 0041142A  push        esi    
  40. 0041142B  push        edi    
  41. 0041142C  lea         edi,[ebp-0C0h]   
  42. 00411432  mov         ecx,30h   
  43. 00411437  mov         eax,0CCCCCCCCh   
  44. 0041143C  rep stos    dword ptr es:[edi]   
  45.     this->x = a + b;  
  46. 0041143E  mov         eax,dword ptr [a]   
  47. 00411441  add         eax,dword ptr [b]   
  48. 00411444  mov         ecx,dword ptr [this]   
  49. 00411447  mov         dword ptr [ecx],eax   
  50.     return this->x;  
  51. 00411449  mov         eax,dword ptr [this]   
  52. 0041144C  mov         eax,dword ptr [eax]   
  53. }  
  54. 0041144E  pop         edi    
  55. 0041144F  pop         esi    
  56. 00411450  pop         ebx    
  57. 00411451  mov         esp,ebp   
  58. 00411453  pop         ebp    
  59. 00411454  ret                            /* __cdecl 不用负责栈清除 */  
  60. --- No source file -------------------------------------------------------------  
  61.   
  62. int TestCallType::_stdcall_call(int a, int b)  
  63. {  
  64. 00411470  push        ebp    
  65. 00411471  mov         ebp,esp   
  66. 00411473  sub         esp,0C0h   
  67. 00411479  push        ebx    
  68. 0041147A  push        esi    
  69. 0041147B  push        edi    
  70. 0041147C  lea         edi,[ebp-0C0h]   
  71. 00411482  mov         ecx,30h   
  72. 00411487  mov         eax,0CCCCCCCCh   
  73. 0041148C  rep stos    dword ptr es:[edi]   
  74.     this->x = a + b;  
  75. 0041148E  mov         eax,dword ptr [a]   
  76. 00411491  add         eax,dword ptr [b]   
  77. 00411494  mov         ecx,dword ptr [this]   
  78. 00411497  mov         dword ptr [ecx],eax   
  79.     return this->x;  
  80. 00411499  mov         eax,dword ptr [this]   
  81. 0041149C  mov         eax,dword ptr [eax]   
  82. }  
  83. 0041149E  pop         edi    
  84. 0041149F  pop         esi    
  85. 004114A0  pop         ebx    
  86. 004114A1  mov         esp,ebp   
  87. 004114A3  pop         ebp    
  88. 004114A4  ret         0Ch                  //清除栈,字节数和参数入栈对应  
  89. --- No source file -------------------------------------------------------------  
  90.   
  91. int TestCallType::_fastcall_call(int a, int b)  
  92. {  
  93. 004114C0  push        ebp    
  94. 004114C1  mov         ebp,esp   
  95. 004114C3  sub         esp,0D8h   
  96. 004114C9  push        ebx    
  97. 004114CA  push        esi    
  98. 004114CB  push        edi    
  99. 004114CC  push        ecx    
  100. 004114CD  lea         edi,[ebp-0D8h]   
  101. 004114D3  mov         ecx,36h   
  102. 004114D8  mov         eax,0CCCCCCCCh   
  103. 004114DD  rep stos    dword ptr es:[edi]   
  104. 004114DF  pop         ecx    
  105. 004114E0  mov         dword ptr [ebp-8],edx   
  106. 004114E3  mov         dword ptr [ebp-14h],ecx   
  107.     this->x = a + b;  
  108. 004114E6  mov         eax,dword ptr [a]   
  109. 004114E9  add         eax,dword ptr [b]   
  110. 004114EC  mov         ecx,dword ptr [this]   
  111. 004114EF  mov         dword ptr [ecx],eax   
  112.     return this->x;  
  113. 004114F1  mov         eax,dword ptr [this]   
  114. 004114F4  mov         eax,dword ptr [eax]   
  115. }  
  116. 004114F6  pop         edi    
  117. 004114F7  pop         esi    
  118. 004114F8  pop         ebx    
  119. 004114F9  mov         esp,ebp   
  120. 004114FB  pop         ebp    
  121. 004114FC  ret         4                    //清除栈,字节数和参数入栈对应  
  122. --- No source file -------------------------------------------------------------  
  123.   
  124. int TestCallType::_thiscall_call(int a, int b)  
  125. {  
  126. 00411510  push        ebp    
  127. 00411511  mov         ebp,esp   
  128. 00411513  sub         esp,0CCh   
  129. 00411519  push        ebx    
  130. 0041151A  push        esi    
  131. 0041151B  push        edi    
  132. 0041151C  push        ecx    
  133. 0041151D  lea         edi,[ebp-0CCh]   
  134. 00411523  mov         ecx,33h   
  135. 00411528  mov         eax,0CCCCCCCCh   
  136. 0041152D  rep stos    dword ptr es:[edi]   
  137. 0041152F  pop         ecx    
  138. 00411530  mov         dword ptr [ebp-8],ecx   
  139.     this->x = a + b;  
  140. 00411533  mov         eax,dword ptr [a]   
  141. 00411536  add         eax,dword ptr [b]   
  142. 00411539  mov         ecx,dword ptr [this]   
  143. 0041153C  mov         dword ptr [ecx],eax   
  144.     return this->x;  
  145. 0041153E  mov         eax,dword ptr [this]   
  146. 00411541  mov         eax,dword ptr [eax]   
  147. }  
  148. 00411543  pop         edi    
  149. 00411544  pop         esi    
  150. 00411545  pop         ebx    
  151. 00411546  mov         esp,ebp   
  152. 00411548  pop         ebp    
  153. 00411549  ret         8                   //清除栈,字节数和参数入栈对应  
  154. --- No source file -------------------------------------------------------------  
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值