


免费预览已结束,剩余1页可下载查看
下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
callstack(调用栈)(二)调用约定调用约定在计算机界不是什么新鲜的概念,已经有许多相关的文献给予详细的介绍。比较全面的介绍可以参见wikipedia上的相关页面。然而,如果你和我一样,在第一次接触调用约定的时候,觉得这个概念是个高深神秘的冬冬,那么就请跟随我一起,在这篇博客中看看他的由来,他的范畴以及他的用途。为什么需要调用约定?在具体介绍调用约定的定义之前,我们先来看看为什么我们需要一个称之为调用约定的冬冬。如果各位了解汇编语言(不了解的话,看下面的这段会稍微有些费力,不过我尽可能把汇编的相关知识解释的清楚一些),那么回忆一下我们是怎么来做一个函数调用的。汇编语言提供了一条指令,call ptr,其功能是把CS:IP (指令段:指令指针,决定着下一条执行指令的地址)压栈,并且修改CPU的指令指针,作一个跳转。在函数结束的地方,我们使用另一条指令,ret,其功能是把栈中的返回地址取出,并且跳转到那条指令。在这里汇编语言只提供了指令跳转的命令,作为函数调用另一个重要组成部分的参数传递,其方式就很灵活,你可以通过寄存器传值,可以通过调用栈传值,可以通过某一块具体的内存传值(类似全局变量)。然后在被调用函数中,从寄存器,栈或者是内存中读取这些信息。想象一下如果被调用函数是某一个程序员所编写的,调用者是另一个程序员,那么他俩之间对于参数的传递方式就有了一个约定。高级语言的出现,把这个问题隐藏了起来。我们在编写一般的c+程序的时候,通常不需要顾虑参数传递的底层实现,但是,这并不意味着这一问题不再出现我们只是把责任推给了编译器。编译器作为一个计算机程序,总是遵照一定的规则工作,每一个规则对应了一种调用约定。久而久之,那些经典的规则所产生的调用约定,就成了耳熟能详的冬冬:耳熟能详的调用约定在介绍这些调用规范之前,我想先说明的是,下面所涉及的调用规范是在32位x86处理器windows平台上的。把范畴限定在32位处理器的原因是:位处理器已经退出CPU的历史舞台,64微处理器无论是IA64还是AMD64都只有一个调用规范只有32位处理器呈现百家成名,百花齐放的景象。(对了,你当然明白调用规范是绑定在处理器架构上的概念,因为它涉及太多的诸如寄存器之类的处理器架构细节。)聚焦于windows则是因为我现在的工作只涉及这一平台。下表的出处来自于The Old New Thing以及张羿的csdn专栏,并作了适当修改。首先来看所有的调用规范都遵循的规定:返回值存储在EDX:EAX中,EDI,ESI,EBP,EBX是保留的存储器。(即函数可以任意使用这些寄存器,无需担心破坏了调用者的寄存器状态) 调用约定名称 清理堆栈 参数压栈顺序 备注 cdecl 调用者 (Caller) 从右往左 因为是调用者清理Stack,因此允许变参 (如printf) stdcall 被调用者 (Callee) 从右往左 一般在Windows API和COM中使用,也是.NET和Native代码调用的缺省Calling Convention。 顺便提一下,Windows中API的Calling Convention所使用到的WINAPI宏在PC机上是_stdcall,而在WinCE上则是_cdecl,并非一成不变。 Thiscall (Microsoft) 被调用者 (Callee) 从右往左 基本上等价stdcall, 除了this指针用ECX传递 Fastcall (Microsoft) 被调用者 (Callee) 从右往左 和Stdcall类似,但是会选择两个从左往右数最先可以放在寄存器里面的参数放在ECX和EDX中 大家可能对清理堆栈,参数压栈顺序这些概念不是很清楚,在这里我会通过一个具体的例子来说明。下面列出了一小段程序和它的汇编代码:#include int _stdcall Test(int a, char b, short c)printf(%d %c %d, a, b, c);return a+c;void main()int a = Test(5, a, );#include int _stdcall Test(int a, char b, short c)printf(%d %c %d, a, b, c);return a+c;void main()int a = Test(5, a, );在main中对Test的调用对应了如下的汇编代码:01 6a0a push 0Ah01 6a61 push 61h01 6a push 5000a e800f0feff call test!ILT+(?TestYGHHDFZ) (000f)000f 8945fc mov dword ptr ebp-4,eax ss:0b:001 6a0a push 0Ah01 6a61 push 61h01 6a push 5000a e800f0feff call test!ILT+(?TestYGHHDFZ) (000f)000f 8945fc mov dword ptr ebp-4,eax ss:0b:0在这个例子中,我们可以观察到如下信息:1. 压栈顺序:栈中首先压入的是0A(十进制中的),是最后一个参数,其次是a,最后是5,所以说_stdcall的压栈顺序是从右向左。2. 返回值存放在eax中:在call指令之后,把eax的值存入到ebp-4中,对应了c+代码中对a的赋值,可见eax是返回值的存放之所。3. 被调用函数清理栈:在call指令和mov指令没有额外的其他指令,可见之前放到栈里的参数,都已经被函数Test清理了(Test的最后一条指令是ret 0c),把栈的指针调整了三个变量的位置。4. 函数更名:细心的读者会发现call指令后面跟的是如同乱码般的test!ILT+(?TestYGHHDFZ),这是编译器做的手脚(name mangling),不同的调用规范下,编译器会按照不同的规则对函数进行更名。我不想细究的原因在于:一方便,函数更名的规则本身就在变化,我目前使用的编译器,会按照以前_thiscall的规则来更名_stdcall的函数。另一方面,许多debuger比如windbg,会自动的把命名调整回来。如何指定调用约定通常,我们真正需要考虑到调用约定的场景,是对一些外部类库的使用。举例来说,如果我们要调用的函数由另外一个类库提供,那么,我们需要根据这个函数所声明的调用约定来使用这个函数。也就是说,我们要告诉编译器,请按照这个调用约定,生成相关的代码,来使用那个来自于类库的函数。对于MSVC的编译器来说,有下面的这些开关: 编译器开关 调用规范 /Gd _cdecl /Gr _fastcall /Gz _stdcall 其中/Gz是c+的默认选项。另外一个例子是,提供给别人的回调函数,需要根据调用者的要求,声明调用约定,举一个例子来说,在windows中开始一个新的线程。这时候,可以在函数声明的语句中,在返回值类型后面插入相关的调用规范,如前面的例子中所示。int _stdcall Test(int a, char b, short c)int _stdcall Test(int a, char b, short c)如果你是一个.NET用户(终于,我可以谈及一些我们的产品了),那么你在P/Invoke的时候仍然需要调用约定。DllImportAttibute中,有一个字段CallingConvention,就是对应这个需求生成的。DllImport(ole32.dll, EntryPoint=CoCreateInstance, CallingConvention=CallingConvention.StdCall)public static extern int CoCreateInstance(ref Guid rclsid, IntPtr pUnkOuter, uint dwClsContext, ref Guid riid, ref System.IntPtr ppv) ;调用约定的用武之地看了上面的介绍之后,你可能会想,我们只需要根据文档上声明的调用约定,在自己的代码中指定相应的调用约定就可以了。那么,了解清楚每一个调用约定的具体内容
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025江苏盐城市第七人民医院招录政府购买服务用工14人模拟试卷完整答案详解
- 2025河南三联科技工程有限公司招聘模拟试卷及完整答案详解1套
- 2025广东江门新会区会城街道今古洲社区公益性岗位招聘1人考前自测高频考点模拟试题及答案详解(名校卷)
- 2025安徽宣城市中心医院第一批次招聘22人模拟试卷及答案详解(历年真题)
- 书店图书订购协议5篇
- 2025辽宁沈阳市浑南区森工林业集团有限公司招聘56人模拟试卷及1套参考答案详解
- 班组建设与安全培训课件
- 班组年后复岗安全培训课件
- 2025黑龙江绥化海伦市民政服务站招聘46人考前自测高频考点模拟试题附答案详解(典型题)
- 2025辽宁鞍山立山区教育局招聘2人考前自测高频考点模拟试题及1套参考答案详解
- 存款代持协议书范文模板
- 建筑施工企业施工项目安全生产标准化考评表
- 电梯使用单位电梯安全总监职责和电梯安全员守则
- 足太阳膀胱经(经络腧穴课件)
- 沟通的艺术智慧树知到期末考试答案章节答案2024年湖南师范大学
- 2024年四川省广安市中考数学试题(含答案逐题解析)
- 员工上下班交通安全知识培训课件
- 产品质量法-企业培训讲座
- 塑胶模具报价表范例
- 三阶魔方七步还原图文教程
- 肌肉注射评分标准
评论
0/150
提交评论