• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >C语言 > __stdcall 和 __cdecl 的区别浅析

__stdcall 和 __cdecl 的区别浅析

作者: 字体:[增加 减小] 来源:互联网 时间:2017-05-28

通过本文主要向大家介绍了stdcall cdecl, stdcall,delphi stdcall,c stdcall,int stdcall等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

1. __cdecl
__cdecl 是C Declaration的缩写(declaration,声明),表示C语言默认的函数调用方法:所有参数从右到左依次入栈,由调用者负责把参数压入栈,最后也是由调用者负责清除栈的内容,一般来说,这是 C/C++ 的默认调用函数的规则,MS VC 编译器采用的规则则是这种规则2. __stdcall
_stdcall 是StandardCall的缩写,是C++的标准调用方式:所有参数从右到左依次入栈,由调用者负责把参数压入栈,最后由被调用者负责清除栈的内容,Windows API 所采用的函数调用规则则是这种规则

另外,采用 __cdecl 和 __stdcall 不同规则的函数所生成的修饰名也各为不同,相同点则是生成的函数修饰名前缀都带有下划线,不同的则是后缀部分,当然,这两者最大的不同点就在于恢复栈的方式不同,而且这点亦是最为重要的。


__cdecl 规则要求调用者本身负责栈的恢复工作,在汇编的角度上说,恢复堆栈的位置是在调用函数内,考虑这样一段 C++ 代码(在 VC 下 Debug)

void __cdecl func(int param1, int param2, int param3) {
  int var1 = param1;
  int var2 = param2;
  int var3 = param3;

  printf("%ld\n", long(¶m1));
  printf("%ld\n", long(¶m2));
  printf("%ld\n", long(¶m3));
  printf("----------------\n");
  printf("%ld\n", long(&var1));
  printf("%ld\n", long(&var2));
  printf("%ld\n", long(&var3));
  return ;
}

int main() {
  func(1, 2, 3);
  return 0;
}
</div>
注意到 func 函数使用了 __cdecl 进行修饰(其实不需要,因为 VC 下默认的是 __cdecl 规则, 这里是为了更为清晰),生成汇编代码如下:

...............................................        ; 省略了printf的代码

15:     return ;
16:   }
004010BD   pop         edi
004010BE   pop         esi
004010BF   pop         ebx
004010C0   add         esp,4Ch
004010C3   cmp         ebp,esp
004010C5   call        __chkesp (004011d0)
004010CA   mov         esp,ebp
004010CC   pop         ebp
004010CD   ret                                         ; 这里是 ret,由调用者(main)恢复堆栈,但如果是 __stdcall 的话,
                                                       ; 恢复堆栈就在这里进行

*******************************************************************************************************************

18:   int main() {

...............................................       ; 省略了建立堆栈的代码

19:     func(1, 2, 3);
00401118   push        3                              ; 将 param3 压入栈
0040111A   push        2                              ; 将 param2 压入栈
0040111C   push        1                              ; 将 param1 压入栈
0040111E   call        @ILT+5(func) (0040100a)        ; @ILT+5(func) 是函数func的修饰名,而0040100a则是他的地址
00401123   add         esp,0Ch                        ; 恢复堆栈,__cdecl 规则由调用者(这里是main)恢复堆栈
20:     return 0;
00401126   xor         eax,eax
21:   }
00401128   pop         edi
00401129   pop         esi
0040112A   pop         ebx
0040112B   add         esp,40h
0040112E   cmp         ebp,esp
00401130   call        __chkesp (004011d0)
00401135   mov         esp,ebp
00401137   pop         ebp
00401138   ret
</div>

结果截图


程序中的栈结构如下图示:

__stdcall 规则由被调用者本身去调整堆栈,在汇编的角度上说,恢复堆栈的行为发生在调用者函数内,考虑这样一段代码(VC 下Debug):

分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • 关于函数调用方式__stdcall和__cdecl详解
  • __stdcall 和 __cdecl 的区别浅析

相关文章

  • 2017-05-28C++的静态联编和动态联编详解
  • 2017-05-28c++显式类型转换示例详解
  • 2017-05-28C++设计模式之观察者模式
  • 2017-05-28VC++中HTControl控件类的CHTSlider控制杆控件类简介
  • 2017-05-28C++中getline()和get()的方法浅析
  • 2017-05-28C++实现将简单密码译回原文的方法
  • 2017-05-28使用C语言编写基于TCP协议的Socket通讯程序实例分享
  • 2017-05-28C++设置超时时间的简单实现方法
  • 2017-05-28C语言中查询进程信号是否被遮罩或搁置的简单方法
  • 2017-05-28C语言求两个字符串的最长公共子串

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • C++编程中指针的声明与基本使用讲解
    • C++求阶乘的两种方法
    • C++ 中使用lambda代替 unique_ptr 的Deleter的方法
    • 如何使用递归和非递归方式反转单向链表
    • c++实现十进制转换成16进制示例
    • 利用简洁的C语言代码解决跳台阶问题与约瑟夫环问题
    • 英语和数学不好,能学编程吗?
    • 双缓冲解决VC++绘图时屏幕闪烁
    • MFC命名规则汇总
    • 详解约瑟夫环问题及其相关的C语言算法实现

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有