《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指针;
  • 没有返回值

构造函数和析构函数的充分条件:

有虚表指针初始化的操作和写入虚表指针的操作。

posted @ 2020-05-04 08:34  坚持,每天进步一点点  阅读(321)  评论(0编辑  收藏  举报