c++虚函数表汇编及内存布局分析(基于visual studio 2019)(四)

#include <iostream>

class Base
{
public:
    virtual int ShowFunc(int param)
    {
        std::cout << "Base ShowFunc: " << param << std::endl;
        return param;
    }
    int b;
};

class Derive: public Base
{
public:
    int ShowFunc(int param)
    {
        std::cout << "Derive ShowFunc: " << param << std::endl;
        return param;
    }
    int d;
};

int main()
{
    Base b1;  变量地址008bf88c
    b1.ShowFunc(1);
    Base* b2 = new Derive();  b2变量地址0086f880,保存内容(指针指向)00e51f90
    b2->ShowFunc(2);
    Derive d1;
    d1.ShowFunc(3);
    std::cout << sizeof(Base) << " " << sizeof(Derive) << std::endl;  // 1个int和1个虚函数表  2个int和1个虚函数表

}

/*
class Derive    size(12):
        +---
 0      | +--- (base class Base)
 0      | | {vfptr}  虚函数表,地址为
 4      | | b
        | +---
 8      | d
        +---

Derive::$vftable@:
        | &Derive_meta
        |  0
 0      | &Derive::ShowFunc  虚函数表中保存的是子类函数
*/

 

Base b1;
009E281F  lea         ecx,[b1]  
009E2822  call        Base::Base (09E1307h)  
    b1.ShowFunc(1);
009E2827  push        1  
009E2829  lea         ecx,[b1]  
009E282C  call        Base::ShowFunc (09E14F1h)  直接调用函数地址
    Base* b2 = new Derive();
009E2831  push        0Ch  
009E2833  call        operator new (09E1140h)  
009E2838  add         esp,4  
009E283B  mov         dword ptr [ebp-0FCh],eax  
009E2841  cmp         dword ptr [ebp-0FCh],0  
009E2848  je          __$EncStackInitStart+71h (09E286Dh)  
009E284A  xor         eax,eax  
009E284C  mov         ecx,dword ptr [ebp-0FCh]  
009E2852  mov         dword ptr [ecx],eax  
009E2854  mov         dword ptr [ecx+4],eax  
009E2857  mov         dword ptr [ecx+8],eax  
009E285A  mov         ecx,dword ptr [ebp-0FCh]  
009E2860  call        Derive::Derive (09E1221h)  
009E2865  mov         dword ptr [ebp-104h],eax  
009E286B  jmp         __$EncStackInitStart+7Bh (09E2877h)  
009E286D  mov         dword ptr [ebp-104h],0  
009E2877  mov         edx,dword ptr [ebp-104h]  
009E287D  mov         dword ptr [b2],edx  
    b2->ShowFunc(2);
009E2880  mov         esi,esp  
009E2882  push        2  
009E2884  mov         eax,dword ptr [b2]   eax变为00e51f90,b2变量内容(指针值)
009E2887  mov         edx,dword ptr [eax]  edx变为009e9c70(虚函数表存储地址),即eax指向内容的第一个字节(00e51f90指向内容第一个字节)
009E2889  mov         ecx,dword ptr [b2]  
009E288C  mov         eax,dword ptr [edx]  edx(虚函数表存储地址)指向内容的第一个字节,即子类函数showFunc
009E288E  call        eax   调用虚函数showFunc
009E2890  cmp         esi,esp  
009E2892  call        __RTC_CheckEsp (09E12F3h)  
    Derive d1;
009E2897  lea         ecx,[d1]  
009E289A  call        Derive::Derive (09E1221h)  
    d1.ShowFunc(3);
009E289F  push        3  
009E28A1  lea         ecx,[d1]  
009E28A4  call        Derive::ShowFunc (09E14E7h)  直接调用函数地址

 


 

 

 

posted @ 2021-10-14 10:20  AdamTang  阅读(114)  评论(0编辑  收藏  举报