《C++反汇编与逆向分析技术揭秘》--构造函数 读书笔记
问题:
当对象生成时, 编译器会自动产生调用其类构造函数代码,在编码过程中可以为类中的数据成员赋予恰当的初始值,在某些情况下,编译器会提供默认的构造函数和析构函数
1)在何种情况下编译器会提供默认的构造函数和析构函数?
2)编译器如何调用??
构造函数时机
对象生成时会自动调用构造函数。只要找到了定义对象的地方,就找到了构造函数调用的时机
不同作用域的对象的生命周期不同,如局部对象、全局对象、静态对象等的生命周期各不相同,只要知道了对象的生命周期,便可以推断出构造函数的调用时机
学习的对象:
- 局部对象
- 堆对象
- 参数对象
- 返回对象
- 全局对象
- 静态对象
局部对象
源码:
反汇编分析:
主函数分析
分析汇编源码:
lea ecx,[ebp-8h];ebp-8h是变量test的首地址,即是该对象的this指针
ecx保存的值相当于就是this指针,也就是说调用构造函数也要传递this指针了
在栈帧的建立过程中,需要遵守x86的函数调用约定,将call保存的寄存器压入栈内。
call保存的寄存器值:ebx、esi、edi.可以发现这个函数调用将call需要保存的寄存器全部保存起来。
在创建对象的时候,下面的代码即是调用构造函数的代码:
push 6
push 3
lea ecx,[ebp-8h]
call 0040100f 构造函数
类对象分析
0040109A mov dword ptr [ebp -4], ecx ;将this指针保存到地址为ebp-4的内存 0040109D mov eax,dword ptr [ ebp+8 ] ;将this指针传递到eax 004010A0 mov ecx, dword ptr [ ebp+0Ch ] mov dword ptr [ ebp+0Ch ] ,ecx;对this指针所指对象的第一个变量进行赋值 004010A9 mov eax,dword ptr [ ebp-4 ];eax保存了this指针,
注意此代码中ecx在函数最前面要使用一堆数据填充栈时需要用到ecx,所有先保存起来,后来再使用,所以有压栈和弹栈的过程。通过上面的代码我们可以知道,对成员变量的赋值,其实都是通过this指针进行索引,间接寻址方式找到成员变量,也可以看出隐含着的this指针作用多么重要。另外,虽然我们写构造函数时没有返回值,但在汇编代码中还体现了构造函数“拥有”返回值这一现象,即通过eax构造函数返回了this指针,这些隐藏于代码之下的细节,也只有通过汇编的形式才能看到。
构造函数的必要条件:
- 这个函数的调用,是这个对象在作用域内的第一次成员函数调用,看this指针即可以区分对象,是哪个对象的this指针就是哪个对象的成员函数。
- 使用thiscall调用方式,使用ecx传递this指针;
- 返回值为this指针
析构函数的必要条件:
- 这个函数的调用,是这个对象在作用域内的最后一次成员函数调用,看this指针即可以区分对象,是哪个对象的this指针就是哪个对象的成员函数;
- 使用thiscall调用方式,使用ecx传递this指针;
- 没有返回值
构造函数和析构函数的充分条件:
有虚表指针初始化的操作和写入虚表指针的操作。