收藏 分享(赏)

从汇编的角度理解C++.doc

上传人:mcady 文档编号:6334403 上传时间:2019-04-07 格式:DOC 页数:8 大小:228.50KB
下载 相关 举报
从汇编的角度理解C++.doc_第1页
第1页 / 共8页
从汇编的角度理解C++.doc_第2页
第2页 / 共8页
从汇编的角度理解C++.doc_第3页
第3页 / 共8页
从汇编的角度理解C++.doc_第4页
第4页 / 共8页
从汇编的角度理解C++.doc_第5页
第5页 / 共8页
点击查看更多>>
资源描述

1、从汇编的角度理解 C+(一) 2007-11-26 14:32 362 人阅读 评论(0) 收藏 举报 汇编 c+initializationclassstringiostreamC 的优美在于其清澈,一眼见底,看着 C 代码甚至可以想像到其构成的汇编,而 C+的优美在于其优雅,结合面向对象和泛型的方法,可以写出赏心悦目的代码。对于既喜欢优雅又喜欢清澈的人来说(比如我),只好阅读 C+生成的汇编代码来理解 C+了。下面就将从几个侧面,来看看 VC8.0 是怎么实现 C+的众多技术的吧。(顺便汇总我在 C+/C 版面上回答此类问题所发表的文章)今天要写的是 this 指针,虚函数和构造函数初始化

2、的顺序(1)this 指针总是将 this 指针 lea ecx, this,然后再调用成员函数。就是 thiscall 的函数调用方式。例程:#include using namespace std;class Baseprotected:int val;public:int GetVal()return val;int main()Base test;test.GetVal();return 0;相应的汇编指令:test.GetVal();lea ecx,test call Base:GetVal (42BFCDh) (2) 虚函数的实现。对于单继承的类,虚函数表的指针存放在类的开始 4

3、个字节,访问虚函数的时候,就是首先取得虚函数表的头指针,然后加一个偏移的量(此偏移量的计算是根据声明虚函数的顺序来定的,也就是说第一个声明的虚函数,偏移量就是 0,以此类推),取得函数指针,再进行访问。虚函数损失的效率就是在于比普通函数多了两次访问内存的过程。例程:class Baseprotected:int val;int val2;public:virtual int GetVal()return val;virtual int GetVal2()return val2;class Child:public Basepublic:virtual int GetVal2()return 0

4、;int main()Child test;Base *p=(Base*)p-GetVal2();return 0;生成的汇编p-GetVal2();mov edx,dword ptrpmov ecx,dword ptr p mov eax,dword ptr edx+4 call eax 对于多继承的类,则稍稍复杂了点。比如从 BaseA, BaseB 继承而来类,其头四个字节存放跟 BaseA 相关的虚函数表头指针,接下来存放 BaseA 的成员变量,再接下来的四个字节,存放 BaseB 相关的虚函数头指针,接下去是 BaseB 的成员变量。这样一来造成指向对象自己的 BaseB*的基类指

5、针实际指向的是对象地址+sizeof(BaseA),因此如果 delete 该指针就会出错。例程#include using namespace std;class Baseprotected:int val;int val2;public:virtual int GetVal()return val;virtual int GetVal2()return val2;class Base2protected:int val;public:virtual int GetVal()return val;class Child:public Base, Base2public:virtual int

6、 GetVal2()return 0;int main()Child *test= new Child;Base *p=(Base*)test;Base2 *p2 =(Base2*)test;/指向 test+sizeof(Base)cout,std:allocator :basic_string,std:allocator (42E30Bh) ;初始化 m10042FD33 mov dword ptr ebp-4,0 0042FD3A mov ecx,dword ptr ebp-14h 0042FD3D add ecx,28h 0042FD40 call std:basic_string,s

7、td:allocator :basic_string,std:allocator (42D302h) ;初始化 m2val2=0;0042FD45 mov eax,dword ptr ebp-14h 0042FD48 mov dword ptr eax+48h,0 ;val2 被赋值0042FD4F mov dword ptr ebp-4,0FFFFFFFFh 0042FD56 mov eax,dword ptr ebp-14h 0042FD59 mov ecx,dword ptr ebp-0Ch 0042FD5C mov dword ptr fs:0,ecx 0042FD63 pop ecx

8、 0042FD64 pop edi 0042FD65 pop esi 0042FD66 pop ebx 0042FD67 add esp,0D8h 0042FD6D cmp ebp,esp 0042FD6F call ILT+3860(_RTC_CheckEsp) (42DF19h) 0042FD74 mov esp,ebp 0042FD76 pop ebp 0042FD77 ret 可见,先是基类的构造函数被调用,然后虚函数表的指针被确定,接着是初始化类中成员变量的初始化(包括member initialization list),最后才调用子类的构造函数。从汇编的角度理解 C+(二) 20

9、07-12-02 00:21 233 人阅读 评论(0) 收藏 举报 汇编 c+c今天要写的内容是: ?:表达式,switch 结构和常量。其实这些内容是跟 C 相关的,而且估计以 C 和 C+方式编译产生的汇编码应该大致相同,在此就不去细分了。(4) ?:表达式?:表达式是个相当高效的表达式,而且可以使代码显得短小精悍,所以在 C+里面,我依旧偏爱这种表达式。下面就其产生的汇编码来一探究竟。如下面的例子,此时在 release 下,生成的汇编代码与 if else 结构是一样的。int a,b, c;c= (ab)?a:b);coutb)?a:b);0040104A mov eax,dwor

10、d ptr esp 0040104D mov ecx,dword ptr esp+4 00401051 cmp eax,ecx 00401053 jg main+57h (401057h) 00401055 mov eax,ecx 例 2:int a,b, c;cinab;c= (ab)?3:4);fprintf(stdout, “%d“, c);生成的汇编代码是:00401021 mov edx,dword ptr esp 00401024 xor eax,eax 00401026 cmp edx,dword ptr esp+4 0040102A setle al 0040102D add eax,3 对于此类是常量的情形,直接加上两者之间的差值。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 生活休闲 > 社会民生

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报