- 1、本文档共5页,可阅读全部内容。
- 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
- 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
C的优化汇编代码
C++的优化汇编代码
对于一个资深程序员来说,了解我们的程序的最底层的运行机制是很重要的,特别对于C/C++程序员来说,这点显得尤为突出。
在很多情况下,知道其底层运行机制对我们理解更深层次的东西是非常有帮助的。比如说,如果你对这些底层的运行记住比较熟悉,那么可能在COM编程中,你会更容易理解他的虚表(vtbl)技术,或者windows编程中经常涉及的TRUNK机制。
其实在不同的C/C++编译器中,由同样的C/C++代码编译成的汇编(机器)代码是不同的。主要讨论Microsoft Visual C++.Net编译器生成的机器代码。Visual C++不同版本的编译器生成的代码没有什么大的区别,这些在讨论后面的实现中会有详细的论述。
C++代码与汇编码
下面我要给出一个全局函数代码,为了简单起见,代码比较简单。
Void InitFun(Function* pFun)
{
pFun-SetAge(34);
PFun-SetName(brucewang);
}
Function是我们定义的一个类,这个函数的功能是接受一个Function类型对象的指针以对该对象进行初始化。SetAge和SetName是Function中定义的两个函数,分别设置Function中定义的age和name属性。下面给出Visual C++编译之后的汇编代码:
;前期工作:设置基址指针,为局部变量分配内存
push ebp
Mov ebp,esp
Sub esp,0C0h
;保存三个常用辅助寄存器原始信息
Push ebx
Push esi
Push edi
;以0CCCCCCCCh值初始化局部变量内存空间
Lea edi,[ebp-0C0h]
Mov ecx,30h
Rep stos dword ptr [edi]
;函数主体,执行函数逻辑
Push 22h
Mov ecx,dword prt [pFun]
Call Function::SetAge
Push offset string brucewang
Mov ecx,dword ptr[pFun]
Call Function::SetName
Pop edi
Pop esi
Pop ebx
Add esp 0C0h
Cmp ebp,esp
Call @ILT+3240(_RTC_CheckEsp)
Mov esp,ebp
Pop ebp
解析C++Debug版本汇编代码
首先,我们进入函数体,就要执行三条初始化指令:
push ebp
Mov ebp,esp
Sub esp,0C0h
我们知道,ebp寄存器在Visual C++中是被默认用来做基址指针的。因此,在刚进入函数执行阶段,都要对ebp进行相应的操作。
第一步,先保存当前ebp中的值,然后将他用在本函数中。
第二步,获取当前堆栈指针,获得的堆栈指针将作为局部变量的基址指针使用。最要引起我们注意的是第三条语句,在C++中,程序局部变量是在堆栈中分配的,可是并没有在每个函数中发现诸如AllocMem等申请内存的函数或指令。实际上,函数中的局部变量空间的分配就是由这条指令完成的。在本例中,程序分配了0C0h字节的空间供该子函数使用。至于为什么要分配多少字节,我们在后面再讨论。
其次,是辅助寄存器ebx,edi,esi的状态保存。作为通用寄存器,他们经常被用在一些常见的操作中,特别是在字符串、数组等的操作中,edi、esi通常作为存储目的、源数据的地址指针来使用。因此这里先保存这三个寄存器的值。虽然在本例中,并没有用到ebx和esi,但是还是按照惯例保存了。
第四步,就是函数调用了。早前面给出的C++源代码中,我们有两个调用类成员函数的语句:
pFun-SetAge(34);
PFun-SetName(brucewang);
在谈到对象的方法的调用上,我们有必要讨论它的具体存储方式,在C++中,对象的成员数据和方法是分开存储的。这样,对同一个类的多个对象,可以共享相同的代码。
这就为我们引入了一个新的问题:当我们调用某个方法是,类方法代码如何知道应该对那个对象数据进行操作呢?在C++代码级别,这个问题是不存在的,因为C++调用对象方法时是加上对象限定符的。但是在汇编码级别是怎样处理的呢?在Visual C++中,对象数据指针是用ecx寄存器来传递的,也就是说在方法中对对象数据的访问,是使用ecx寄存器中的数值来作为对象基址指针对对象数据进行存取等操作的。实际上,这个ecx就是你在实现类成员方法是在其中使用的this指针。所以你看到的汇编代码是这样的:
Push 22h
Mov ecx,dword prt [pFun]
Call Function::SetAge
第五步,退出函数是的恢复工作,受限是恢复前面提到的3个常用的辅助寄存器:ebx、ed
您可能关注的文档
最近下载
- 部编版八年级上册历史基础知识填空.docx
- 小学五年级上全册人自然社会教案可打印.doc
- DB11∕T 1598.3-2019 居家养老服务规范 第3部分:助医服务.docx VIP
- 人教版高中物理电学实验要点总结.pdf VIP
- 普通高中课程标准2023.pdf
- 幼儿园幼儿出游安全应急预案.docx VIP
- 2024浙江省执业药师继续教育答案-中医虚症辨证用药.docx VIP
- DB11_T 1598.2-2019 居家养老服务规范 第2部分:助餐服务.PDF VIP
- 简谱 爱永在 沂蒙山 王传亮.pdf
- 小学一年级音乐下(第三单元 音乐中的动物: 唱歌 咏鹅):C1跨学科学习活动设计-教学方案设计+学生学习成果+学习成果点评[2.0微能力获奖优秀作品].docx
文档评论(0)