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) 直接调用函数地址