C++运行原理的汇编代码分析 一

ILT:Incremental Link Table 增量链接表,(函数地址跳转表) @ILT+100 相当于跳转到弟21个函数 JMP 0xXXXXXXXX (5字节在32位机器)跳转到某个具体函数地址, 所有的call会先到表里,再JMP到具体函数地址
1、普通成员函数
    int add_1(int a, int b){return a+b;};
00361810  push        ebp 
00361811  mov         ebp,esp      #保存ebp
00361813  sub         esp,0CCh     #申请栈空间
00361819  push        ebx          #保存非易失寄存器
0036181A  push        esi         
0036181B  push        edi 
0036181C  push        ecx          #保存类指针
0036181D  lea         edi,[ebp-0CCh]    #初始化申请到的栈空间 
00361823  mov         ecx,33h      
00361828  mov         eax,0CCCCCCCCh 
0036182D  rep stos    dword ptr es:[edi] 
0036182F  pop         ecx          #把类指针拿出来
00361830  mov         dword ptr [ebp-8],ecx  #把类指针放在ebp-8的位置
00361833  mov         eax,dword ptr [a]  #拿第一参数ebp+8
00361836  add         eax,dword ptr [b]  #拿第二参数ebp+12,结果放在eax 返回类地址
00361839  pop         edi          #恢复寄存器
0036183A  pop         esi 
0036183B  pop         ebx 
0036183C  mov         esp,ebp      #恢复esp,ebp
0036183E  pop         ebp 
0036183F  ret         8            #返回,stdcall
2、构造函数
class son : public father
{
public:
    son(){m_val = 12;}
...
...
003615B3  mov         ecx,dword ptr [this]          #this指针就是ebp-8
003615B6  call        father::father (361073h)      #先调用父类的构造
003615BB  mov         eax,dword ptr [this]         
                      #把虚函数表地址放在类的首地址中
003615BE  mov         dword ptr [eax],offset son::`vftable' (366740h) 
003615C4  mov         eax,dword ptr [this] 
003615C7  mov         dword ptr [eax+4],0Ch  #eax+4就是成员变量m_val的位置
003615CE  mov         eax,dword ptr [this]   #构造函数的返回值是this指针
003615D1  pop         edi 
003615D2  pop         esi 
003615D3  pop         ebx 
003615D4  add         esp,0CCh      #释放栈空间
003615DA  cmp         ebp,esp       #比较栈是否平衡
                      #调用__RTC_CheckEsp函数 第74个函数,仅仅是为了检查
003615DC  call        @ILT+365(__RTC_CheckEsp) (361172h)  
003615E1  mov         esp,ebp      #函数返回
003615E3  pop         ebp 
003615E4  ret 
3、析构函数
~son(){m_val = 0;}
......
...... #省略初始化工作
00A01783  mov         eax,dword ptr [this] 
00A01786  mov         dword ptr [eax],offset son::`vftable' (0A06740h) #设置虚函数表
00A0178C  mov         eax,dword ptr [this]         
00A0178F  mov         dword ptr [eax+4],0          #m_val清零
00A01796  mov         ecx,dword ptr [this] 
00A01799  call        father::~father (0A010C8h)   #调用基类的析构
00A0179E  pop         edi                          #返回,代码跟构造函数一样,析构函数没有返回值
......
4、类的静态函数
static int add_1(int a, int b){return a+b;};
00F51810  push        ebp 
00F51811  mov         ebp,esp 
00F51813  sub         esp,0C0h 
00F51819  push        ebx 
00F5181A  push        esi 
00F5181B  push        edi 
00F5181C  lea         edi,[ebp-0C0h] 
00F51822  mov         ecx,30h 
00F51827  mov         eax,0CCCCCCCCh 
00F5182C  rep stos    dword ptr es:[edi]  #以上都初始化,发现没有使用类指针,与普通函数无差别
00F5182E  mov         eax,dword ptr [a] 
00F51831  add         eax,dword ptr [b] 
00F51834  pop         edi 
00F51835  pop         esi 
00F51836  pop         ebx 
00F51837  mov         esp,ebp 
00F51839  pop         ebp 
00F5183A  ret                      #返回的时候没有使用ret 8,说明是c标准调用,call后面跟add esp,8
5、静态成员变量
void set_val(int n){m_privete = n;} // m_privete 是静态成员
......
......#仅列出最重要的2句
013C2043  mov         eax,dword ptr [n]  #获取n的值
013C2046  mov         dword ptr [son::m_privete (13C81ACh)],eax  #放到一个静态地址里
6、虚函数
    father *pfather = newson;  #父类指针new一个子类对象,调用父类虚函数
    pfather->add_0(2,4);        #看调用过程
00FF155E  mov         esi,esp   #先保存esp到esi
00FF1560  push        4         #参数入栈
00FF1562  push        2 
                      #注意这里用mov不是lea,取指针的值,eax放的就是new的类对象的地址
00FF1564  mov         eax,dword ptr [ebp-14h]
        #类对象地址的首地址的值放的是虚函数表的地址,记下edx的值0x000F6740(看下面虚函数表)
00FF1567  mov         edx,dword ptr [eax]
00FF1569  mov         ecx,dword ptr [ebp-14h] #ecx一如既往地保存类对象地址
00FF156C  mov         eax,dword ptr [edx+4]   #取到实际函数的地址
00FF156F  call        eax          #调用函数,call一个寄存器,就是运行时多态
00FF1571  cmp         esi,esp      #检查栈平衡
00FF1573  call        @ILT+355(__RTC_CheckEsp) (0FF1168h) 
7、虚函数表,以NULL结尾
#虚函数表2个函数,一个地址是0xF110E,另一个0xF120D
0x000F6740 0e 11 0f 00 0d 12 0f 00 00 00 00 00
son::`vector deleting destructor':    #父类虚析构,子类的析构函数在虚函数表里
000F110E  jmp         son::`scalar deleting destructor' (0F1510h)
son::add_0:        #父类的add_0是虚函数
000F120D  jmp         son::add_0 (0F1850h)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值