从汇编层面深度剖析C++基本对象布局
作者:网络转载 发布时间:[ 2014/7/2 11:24:38 ] 推荐标签:Net 软件开发
为了让大家更清楚构造函数到底作了什么事情,我对上面的汇编语句逐行分析:
7 this->x = x;
0x080484fd <point+3>: mov eax,DWORD PTR [ebp+0x8]
0x08048500 <point+6>: mov edx,DWORD PTR [ebp+0xc]
0x08048503 <point+9>: mov DWORD PTR [eax],edx
mov eax,DWORD PTR [ebp+0x8] 将函数第一个参数的值存放到寄存器eax中
mov edx,DWORD PTR [ebp+0xc] 将函数第二个参数的值存放到寄存器edx中
mov DWORD PTR [eax],edx 将edx寄存器的值写到eax所指向的内存中
结合this->x = x;这个C++代码,我们可以大胆推测,point构造函数生成汇编后,它对应的函数名(或者符号名)为
_ZN5pointC1Eii。该函数的第一个参数为this,类型为point类内存布局的表示类型,我们姑且称为struct point *类型;第二参数为int类型的x。
接下来的this->y = y;语句的反汇编,与上面this->x = x; 语句如同一辙,唯有x和y在point对象的内存偏移量不同。
从而得出,x成员在point对象内存的偏移量为0,而y的为4。
比较迷惑的是后这句:
9 ins_cnt++;
0x0804850e <point+20>: mov eax,ds:0x804a01c
0x08048513 <point+25>: add eax,0x1
0x08048516 <point+28>: mov ds:0x804a01c,eax
第一个mov是将内存0x804a01c的值读到eax中,add指令是将eax加1,后一个mov是将eax后的值写回到内存中。还记得0x804a01c是哪个符号的地址吗?没错,它是point类静态变量ins_cnt的地址。
由此,我们可以使用point类的对象在内存的布局如下:
struct point {
int x;
int y;
};
// point::ins_cnt 变量,在汇编层面上,它是一个全局变量
int point_ins_cnt = 0;
它的构造函数翻译成如下:
void point::point(struct point *this, int x, int y)
{
this->x = x;
this->y = y;
point_ins_cnt++;
}
正如你早已知道的秘密,C++编译器悄悄地将你写的非静态 函数 成员(当然包括构造函数的析构函数)加上this指针作为第一个参数,这是C++资料上所说的this隐藏参数。在汇编的曝光下,这一切都真相大白了。
下面是move成员函数反汇编的结果,如有不明白,可以对比分析一下:
(gdb) disassemble /m _ZN5point4moveEii
Dump of assembler code for function _ZN5point4moveEii:
22 point & move(int addx, int addy)
0x0804853a <_ZN5point4moveEii+0>: push ebp
0x0804853b <_ZN5point4moveEii+1>: mov ebp,esp
23 {
24 this->x += addx;
0x0804853d <_ZN5point4moveEii+3>: mov eax,DWORD PTR [ebp+0x8]
0x08048540 <_ZN5point4moveEii+6>: mov eax,DWORD PTR [eax]
0x08048542 <_ZN5point4moveEii+8>: mov edx,eax
0x08048544 <_ZN5point4moveEii+10>: add edx,DWORD PTR [ebp+0xc]
0x08048547 <_ZN5point4moveEii+13>: mov eax,DWORD PTR [ebp+0x8]
0x0804854a <_ZN5point4moveEii+16>: mov DWORD PTR [eax],edx
25 this->y += addy;
0x0804854c <_ZN5point4moveEii+18>: mov eax,DWORD PTR [ebp+0x8]
0x0804854f <_ZN5point4moveEii+21>: mov eax,DWORD PTR [eax+0x4]
0x08048552 <_ZN5point4moveEii+24>: mov edx,eax
0x08048554 <_ZN5point4moveEii+26>: add edx,DWORD PTR [ebp+0x10]
0x08048557 <_ZN5point4moveEii+29>: mov eax,DWORD PTR [ebp+0x8]
0x0804855a <_ZN5point4moveEii+32>: mov DWORD PTR [eax+0x4],edx
26
27 return *this;
0x0804855d <_ZN5point4moveEii+35>: mov eax,DWORD PTR [ebp+0x8]
28 }
0x08048560 <_ZN5point4moveEii+38>: pop ebp
0x08048561 <_ZN5point4moveEii+39>: ret
End of assembler dump.
|
相关推荐
更新发布
功能测试和接口测试的区别
2023/3/23 14:23:39如何写好测试用例文档
2023/3/22 16:17:39常用的选择回归测试的方式有哪些?
2022/6/14 16:14:27测试流程中需要重点把关几个过程?
2021/10/18 15:37:44性能测试的七种方法
2021/9/17 15:19:29全链路压测优化思路
2021/9/14 15:42:25性能测试流程浅谈
2021/5/28 17:25:47常见的APP性能测试指标
2021/5/8 17:01:11