__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 plaincopyprint?
  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 plaincopyprint?
  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 plaincopyprint?
  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. int TestCallType::__cdecl_call(int a, int b)
  33. {
  34. 00411420  push        ebp
  35. 00411421  mov         ebp,esp
  36. 00411423  sub         esp,0C0h
  37. 00411429  push        ebx
  38. 0041142A  push        esi
  39. 0041142B  push        edi
  40. 0041142C  lea         edi,[ebp-0C0h]
  41. 00411432  mov         ecx,30h
  42. 00411437  mov         eax,0CCCCCCCCh
  43. 0041143C  rep stos    dword ptr es:[edi]
  44. this->x = a + b;
  45. 0041143E  mov         eax,dword ptr [a]
  46. 00411441  add         eax,dword ptr [b]
  47. 00411444  mov         ecx,dword ptr [this]
  48. 00411447  mov         dword ptr [ecx],eax
  49. return this->x;
  50. 00411449  mov         eax,dword ptr [this]
  51. 0041144C  mov         eax,dword ptr [eax]
  52. }
  53. 0041144E  pop         edi
  54. 0041144F  pop         esi
  55. 00411450  pop         ebx
  56. 00411451  mov         esp,ebp
  57. 00411453  pop         ebp
  58. 00411454  ret                            /* __cdecl 不用负责栈清除 */
  59. --- No source file -------------------------------------------------------------
  60. int TestCallType::_stdcall_call(int a, int b)
  61. {
  62. 00411470  push        ebp
  63. 00411471  mov         ebp,esp
  64. 00411473  sub         esp,0C0h
  65. 00411479  push        ebx
  66. 0041147A  push        esi
  67. 0041147B  push        edi
  68. 0041147C  lea         edi,[ebp-0C0h]
  69. 00411482  mov         ecx,30h
  70. 00411487  mov         eax,0CCCCCCCCh
  71. 0041148C  rep stos    dword ptr es:[edi]
  72. this->x = a + b;
  73. 0041148E  mov         eax,dword ptr [a]
  74. 00411491  add         eax,dword ptr [b]
  75. 00411494  mov         ecx,dword ptr [this]
  76. 00411497  mov         dword ptr [ecx],eax
  77. return this->x;
  78. 00411499  mov         eax,dword ptr [this]
  79. 0041149C  mov         eax,dword ptr [eax]
  80. }
  81. 0041149E  pop         edi
  82. 0041149F  pop         esi
  83. 004114A0  pop         ebx
  84. 004114A1  mov         esp,ebp
  85. 004114A3  pop         ebp
  86. 004114A4  ret         0Ch                  //清除栈,字节数和参数入栈对应
  87. --- No source file -------------------------------------------------------------
  88. int TestCallType::_fastcall_call(int a, int b)
  89. {
  90. 004114C0  push        ebp
  91. 004114C1  mov         ebp,esp
  92. 004114C3  sub         esp,0D8h
  93. 004114C9  push        ebx
  94. 004114CA  push        esi
  95. 004114CB  push        edi
  96. 004114CC  push        ecx
  97. 004114CD  lea         edi,[ebp-0D8h]
  98. 004114D3  mov         ecx,36h
  99. 004114D8  mov         eax,0CCCCCCCCh
  100. 004114DD  rep stos    dword ptr es:[edi]
  101. 004114DF  pop         ecx
  102. 004114E0  mov         dword ptr [ebp-8],edx
  103. 004114E3  mov         dword ptr [ebp-14h],ecx
  104. this->x = a + b;
  105. 004114E6  mov         eax,dword ptr [a]
  106. 004114E9  add         eax,dword ptr [b]
  107. 004114EC  mov         ecx,dword ptr [this]
  108. 004114EF  mov         dword ptr [ecx],eax
  109. return this->x;
  110. 004114F1  mov         eax,dword ptr [this]
  111. 004114F4  mov         eax,dword ptr [eax]
  112. }
  113. 004114F6  pop         edi
  114. 004114F7  pop         esi
  115. 004114F8  pop         ebx
  116. 004114F9  mov         esp,ebp
  117. 004114FB  pop         ebp
  118. 004114FC  ret         4                    //清除栈,字节数和参数入栈对应
  119. --- No source file -------------------------------------------------------------
  120. int TestCallType::_thiscall_call(int a, int b)
  121. {
  122. 00411510  push        ebp
  123. 00411511  mov         ebp,esp
  124. 00411513  sub         esp,0CCh
  125. 00411519  push        ebx
  126. 0041151A  push        esi
  127. 0041151B  push        edi
  128. 0041151C  push        ecx
  129. 0041151D  lea         edi,[ebp-0CCh]
  130. 00411523  mov         ecx,33h
  131. 00411528  mov         eax,0CCCCCCCCh
  132. 0041152D  rep stos    dword ptr es:[edi]
  133. 0041152F  pop         ecx
  134. 00411530  mov         dword ptr [ebp-8],ecx
  135. this->x = a + b;
  136. 00411533  mov         eax,dword ptr [a]
  137. 00411536  add         eax,dword ptr [b]
  138. 00411539  mov         ecx,dword ptr [this]
  139. 0041153C  mov         dword ptr [ecx],eax
  140. return this->x;
  141. 0041153E  mov         eax,dword ptr [this]
  142. 00411541  mov         eax,dword ptr [eax]
  143. }
  144. 00411543  pop         edi
  145. 00411544  pop         esi
  146. 00411545  pop         ebx
  147. 00411546  mov         esp,ebp
  148. 00411548  pop         ebp
  149. 00411549  ret         8                   //清除栈,字节数和参数入栈对应
  150. --- No source file -------------------------------------------------------------

函数调用方式__stdecl _stdcall _fastcall __thiscall介绍相关推荐

  1. _cdecl、_stdcall 、_fastcall、_thiscall 函数调用方式与区别

    几种函数调用方式 __cdecl 是C DECLaration的缩写(declaration,声明),表示C语言默认的函数调用方法:所有参数从右到左依次入栈,这些参数由调用者清除,称为手动清栈.被调用 ...

  2. C++函数调用方式(_stdcall, _pascal, _cdecl...)总结 收藏

    C++函数调用方式(_stdcall, _pascal, _cdecl...)总结 收藏 __stdcall: _stdcall 调用约定相当于16位动态库中经常使用的PASCAL调用约定.在32位的 ...

  3. c语言程序中函数调用本身叫什么,在C语言中函数调用方式有什么区别

    在使用VC进行函数定义时,通常会指定该函数调用方式,那么在C语言中函数调用方式有什么区别呢?下面小编找到了一下教程,分享给大家,希望可以帮助到大家. 通常在使用VC进行函数定义时会指定该函数调用方式, ...

  4. Process Explorer函数调用方式

    Process Explorer Process Explorer是Windows操作系统下最优秀的进程管理工具,画面左上侧Parent/Child树结构显示当前运行的进程,右侧显示个进程的PID.C ...

  5. JavaScript中七种函数调用方式及对应 this 的含义

    http://blog.sina.com.cn/s/blog_621f1e120100rj21.html this 在 JavaScript 开发中占有相当重要的地位,不过很多人对this这个东西都感 ...

  6. php回调函数如何执行顺序,PHP回调函数调用方式

    //PHP回调函数调用方式 // 类MyClass class MyClass { //静态方法 public static function myCallbackMethod() { echo &q ...

  7. 字节对齐和C/C++函数调用方式学习总结(多篇节选)

    字节对齐和C/C++函数调用方式学习总结 created: 04-06-17 last saved: author: ayixidelu 前言: <***软件编程规范>中提到:" ...

  8. 静态成员函数调用方式--收藏帖子

    原帖子地址:https://bbs.csdn.net/topics/390750229 静态成员函数调用方式  A:: s_fun();//不需要额外传递一个参数,作为this 指针:因为静态函数,属 ...

  9. C语言试题八十一之利用递归函数调用方式,将所输入的5个字符,相反顺序打印

    1.题目 利用递归函数调用方式,将所输入的5个字符,相反顺序打印 2 .温馨提示 C语言试题汇总里可用于计算机二级C语言笔试.机试.研究生复试中C程序设计科目.帮助C语言学者打好程序基础.C语言基础, ...

最新文章

  1. 记录JVM垃圾回收算法
  2. IOS内置safari浏览器日期字符串转Date对象失败
  3. 计算机组成原理,P函数,深入浅出计算机组成原理学习笔记:第五讲
  4. mysql数据类型优化
  5. shiro框架的UsernamePasswordToken与对应Realm中的AuthenticationToken的一点比较
  6. jQuery的$.ajax()与php后台交互,进行文件上传并保存在指定目录
  7. 前端加密js库--CryptoJs
  8. git与gitlab使用教程
  9. Adobe Illustrator CS6 出现错误报告16
  10. 魔兽、星际和红警的比较
  11. win10 1909是微软的第几个版本 win10各版本区别
  12. 使用ArcMap 生成TPK和geodatabase包
  13. 防范于未“燃”|涂鸦智慧社区推出“黑科技”,电瓶车禁入电梯智慧方案
  14. 云呐|固定资产采购管理系统(资产采购管理有哪些功能)
  15. 正定矩阵的相关性质,凸锥
  16. 实时渲染大赛太卷了,来看提前交卷的优秀参赛作品
  17. DOSBOX运行程序
  18. Kubernetes服务发现:Service、Kube-Proxy(Netfilter)
  19. android 传输助手 mac,MacDroid for mac(安卓手机数据传输助手)
  20. 不愧是阿里巴巴公布Java10W字面经,在Github标星32K

热门文章

  1. File类的构造方法
  2. MySQL8.0允许外部访问
  3. 数字型变量可以直接计算
  4. zsh配置其显示当前文件路径
  5. Linux查询系统信息
  6. Puppet exec资源介绍(二十六)
  7. [译] 原生 JavaScript 值得学习吗?答案是肯定的
  8. [Bootstrap]全局样式(四)
  9. Alpha版会议总结
  10. Model层视频播放关闭问题及手机视频播放的适配问题解决方案