先分析一个例子。
#include<stdio.h> class CBase { public: CBase() { printf("CBase\n"); } ~CBase() { printf("~CBase\n"); } void SetNumber(int nInt) { this->m_nNumber = nInt; } int GetNumber() { return this->m_nNumber; } private: int m_nNumber; }; class CDerive : public CBase { public: void ShowNumber(int nNumber) { SetNumber(nNumber); m_nDerive = nNumber + 1; printf("%d\n" , GetNumber()); printf("%d\n" , m_nDerive); } public: int m_nDerive; }; int main1(int argc , char *argv[]) { CDerive derive; derive.ShowNumber(argc); return 0; } int main3() { int nTest = 0x87654321; CBase base; CDerive *pDerive = (CDerive *)(&base); printf("%x\n" , pDerive->m_nDerive); return 0; }
下面是反汇编分析
此处是函数跳转表 @ILT+0([email protected]@@[email protected]): 00401005 jmp CBase::SetNumber (00401190) @ILT+5([email protected]@[email protected]): 0040100A jmp CBase::~CBase (00401300) @ILT+10([email protected]@@[email protected]): 0040100F jmp CDerive::ShowNumber (00401100) @ILT+15([email protected]@@QAEHXZ): 00401014 jmp CBase::GetNumber (004011d0) @ILT+20([email protected]@[email protected]): 00401019 jmp CDerive::CDerive (00401210) @ILT+25([email protected]@[email protected]): 0040101E jmp CDerive::~CDerive (004012b0) @ILT+30(_main): 00401023 jmp main (00401060) @ILT+35([email protected]@[email protected]): 00401028 jmp CBase::CBase (00401260) CDerive::CDerive: 00401210 push ebp 00401211 mov ebp,esp 00401213 sub esp,44h 00401216 push ebx 00401217 push esi 00401218 push edi 00401219 push ecx 0040121A lea edi,[ebp-44h] 0040121D mov ecx,11h 00401222 mov eax,0CCCCCCCCh 00401227 rep stos dword ptr [edi] 00401229 pop ecx 0040122A mov dword ptr [ebp-4],ecx ecx即为this指针 0040122D mov ecx,dword ptr [ebp-4] 00401230 call @ILT+35(CBase::CBase) (00401028) 00401235 mov eax,dword ptr [ebp-4] 00401238 pop edi 00401239 pop esi 0040123A pop ebx 0040123B add esp,44h 0040123E cmp ebp,esp 00401240 call __chkesp (00401730) 00401245 mov esp,ebp 00401247 pop ebp 00401248 ret CDerive::~CDerive: 004012B0 push ebp 004012B1 mov ebp,esp 004012B3 sub esp,44h 004012B6 push ebx 004012B7 push esi 004012B8 push edi 004012B9 push ecx 004012BA lea edi,[ebp-44h] 004012BD mov ecx,11h 004012C2 mov eax,0CCCCCCCCh 004012C7 rep stos dword ptr [edi] 004012C9 pop ecx 004012CA mov dword ptr [ebp-4],ecx 004012CD mov ecx,dword ptr [ebp-4] 004012D0 call @ILT+5(CBase::~CBase) (0040100a) 004012D5 pop edi 004012D6 pop esi 004012D7 pop ebx 004012D8 add esp,44h 004012DB cmp ebp,esp 004012DD call __chkesp (00401730) 004012E2 mov esp,ebp 004012E4 pop ebp 004012E5 ret 1: #include<stdio.h> 2: 3: class CBase 4: { 5: public: 6: CBase() 00401260 push ebp 00401261 mov ebp,esp 00401263 sub esp,44h 00401266 push ebx 00401267 push esi 00401268 push edi 00401269 push ecx 0040126A lea edi,[ebp-44h] 0040126D mov ecx,11h 00401272 mov eax,0CCCCCCCCh 00401277 rep stos dword ptr [edi] 00401279 pop ecx 0040127A mov dword ptr [ebp-4],ecx 7: { 8: printf("CBase\n"); 0040127D push offset string "CBase\n" (00425020) 00401282 call printf (00401860) 00401287 add esp,4 9: } 0040128A mov eax,dword ptr [ebp-4] 0040128D pop edi 0040128E pop esi 0040128F pop ebx 00401290 add esp,44h 00401293 cmp ebp,esp 00401295 call __chkesp (00401730) 0040129A mov esp,ebp 0040129C pop ebp 0040129D ret 10: ~CBase() 11: { 00401300 push ebp 00401301 mov ebp,esp 00401303 sub esp,44h 00401306 push ebx 00401307 push esi 00401308 push edi 00401309 push ecx 0040130A lea edi,[ebp-44h] 0040130D mov ecx,11h 00401312 mov eax,0CCCCCCCCh 00401317 rep stos dword ptr [edi] 00401319 pop ecx 还原ecx指针 0040131A mov dword ptr [ebp-4],ecx 12: printf("~CBase\n"); 0040131D push offset string "~CBase\n" (00425028) 00401322 call printf (00401860) 00401327 add esp,4 13: } 0040132A pop edi 0040132B pop esi 0040132C pop ebx 0040132D add esp,44h 00401330 cmp ebp,esp 00401332 call __chkesp (00401730) 00401337 mov esp,ebp 00401339 pop ebp 0040133A ret 14: void SetNumber(int nInt) 15: { 00401190 push ebp 00401191 mov ebp,esp 00401193 sub esp,44h 00401196 push ebx 00401197 push esi 00401198 push edi 00401199 push ecx 0040119A lea edi,[ebp-44h] 0040119D mov ecx,11h 004011A2 mov eax,0CCCCCCCCh 004011A7 rep stos dword ptr [edi] 004011A9 pop ecx 004011AA mov dword ptr [ebp-4],ecx 16: this->m_nNumber = nInt; 004011AD mov eax,dword ptr [ebp-4] 004011B0 mov ecx,dword ptr [ebp+8] 004011B3 mov dword ptr [eax],ecx 17: } 004011B5 pop edi 004011B6 pop esi 004011B7 pop ebx 004011B8 mov esp,ebp 004011BA pop ebp 004011BB ret 4 18: int GetNumber() 19: { 004011D0 push ebp 004011D1 mov ebp,esp 004011D3 sub esp,44h 004011D6 push ebx 004011D7 push esi 004011D8 push edi 004011D9 push ecx 004011DA lea edi,[ebp-44h] 004011DD mov ecx,11h 004011E2 mov eax,0CCCCCCCCh 004011E7 rep stos dword ptr [edi] 004011E9 pop ecx 004011EA mov dword ptr [ebp-4],ecx 20: return this->m_nNumber; 004011ED mov eax,dword ptr [ebp-4] 004011F0 mov eax,dword ptr [eax] 21: } 004011F2 pop edi 004011F3 pop esi 004011F4 pop ebx 004011F5 mov esp,ebp 004011F7 pop ebp 004011F8 ret 22: private: 23: int m_nNumber; 24: }; 25: 26: class CDerive : public CBase 27: { 28: public: 29: void ShowNumber(int nNumber) 30: { 00401100 push ebp 00401101 mov ebp,esp 00401103 sub esp,44h 00401106 push ebx 00401107 push esi 00401108 push edi 00401109 push ecx 0040110A lea edi,[ebp-44h] 0040110D mov ecx,11h 00401112 mov eax,0CCCCCCCCh 00401117 rep stos dword ptr [edi] 00401119 pop ecx 0040111A mov dword ptr [ebp-4],ecx 31: SetNumber(nNumber); 0040111D mov eax,dword ptr [ebp+8] 00401120 push eax 00401121 mov ecx,dword ptr [ebp-4] 00401124 call @ILT+0(CBase::SetNumber) (00401005) 32: m_nDerive = nNumber + 1; 00401129 mov ecx,dword ptr [ebp+8] 0040112C add ecx,1 0040112F mov edx,dword ptr [ebp-4] 00401132 mov dword ptr [edx+4],ecx 33: printf("%d\n" , GetNumber()); 00401135 mov ecx,dword ptr [ebp-4] 00401138 call @ILT+15(CBase::GetNumber) (00401014) 0040113D push eax 0040113E push offset string "%d\n" (0042501c) 00401143 call printf (00401860) 00401148 add esp,8 34: printf("%d\n" , m_nDerive); 0040114B mov eax,dword ptr [ebp-4] 0040114E mov ecx,dword ptr [eax+4] 00401151 push ecx 00401152 push offset string "%d\n" (0042501c) 00401157 call printf (00401860) 0040115C add esp,8 35: } 0040115F pop edi 00401160 pop esi 00401161 pop ebx 00401162 add esp,44h 00401165 cmp ebp,esp 00401167 call __chkesp (00401730) 0040116C mov esp,ebp 0040116E pop ebp 0040116F ret 4 36: private: 37: int m_nDerive; 38: }; 39: 40: int main(int argc , char *argv[]) 41: { 00401060 push ebp 00401061 mov ebp,esp 00401063 push 0FFh 00401065 push offset __ehhandler$_main (00413429) 0040106A mov eax,fs:[00000000] 00401070 push eax 00401071 mov dword ptr fs:[0],esp 00401078 sub esp,4Ch 0040107B push ebx 0040107C push esi 0040107D push edi 0040107E lea edi,[ebp-58h] 00401081 mov ecx,13h 00401086 mov eax,0CCCCCCCCh 0040108B rep stos dword ptr [edi] 42: CDerive derive; 0040108D lea ecx,[ebp-14h] 00401090 call @ILT+20(CDerive::CDerive) (00401019) 00401095 mov dword ptr [ebp-4],0 43: derive.ShowNumber(argc); 0040109C mov eax,dword ptr [ebp+8] 0040109F push eax 004010A0 lea ecx,[ebp-14h] 004010A3 call @ILT+10(CDerive::ShowNumber) (0040100f) 44: return 0; 004010A8 mov dword ptr [ebp-18h],0 004010AF mov dword ptr [ebp-4],0FFFFFFFFh 004010B6 lea ecx,[ebp-14h] 004010B9 call @ILT+25(CDerive::~CDerive) (0040101e) 004010BE mov eax,dword ptr [ebp-18h] 45: } 004010C1 mov ecx,dword ptr [ebp-0Ch] 004010C4 mov dword ptr fs:[0],ecx 004010CB pop edi 004010CC pop esi 004010CD pop ebx 004010CE add esp,58h 004010D1 cmp ebp,esp 004010D3 call __chkesp (00401730) 004010D8 mov esp,ebp 004010DA pop ebp 004010DB ret 父类有构造函数子类没有则编译器提供一个默认的。子类有父类没有则不一定提供。除非有虚函数等。 46: int main() 47: { 00401360 push ebp 00401361 mov ebp,esp 00401363 sub esp,50h 00401366 push ebx 00401367 push esi 00401368 push edi 00401369 lea edi,[ebp-50h] 0040136C mov ecx,14h 00401371 mov eax,0CCCCCCCCh 00401376 rep stos dword ptr [edi] 48: int nTest = 0x87654321; 00401378 mov dword ptr [ebp-4],87654321h 49: CBase base; 0040137F lea ecx,[ebp-8] 00401382 call @ILT+40(CBase::CBase) (0040102d) 50: CDerive *pDerive = (CDerive *)(&base); 00401387 lea eax,[ebp-8] 0040138A mov dword ptr [ebp-0Ch],eax 51: printf("%x\n" , pDerive->m_nDerive); 0040138D mov ecx,dword ptr [ebp-0Ch] 00401390 mov edx,dword ptr [ecx+4] //指针偏移,注意此处是指针偏移,指针可以为NULL NULL + 4不是NULL,不会出现空指针异常 00401393 push edx 00401394 push offset string "%x\n" (00425034) 00401399 call printf (00401930) 0040139E add esp,8 52: return 0; 004013A1 mov dword ptr [ebp-10h],0 004013A8 lea ecx,[ebp-8] 004013AB call @ILT+5(CBase::~CBase) (0040100a) 004013B0 mov eax,dword ptr [ebp-10h] 53: } 004013B3 pop edi 004013B4 pop esi 004013B5 pop ebx 004013B6 add esp,50h 004013B9 cmp ebp,esp 004013BB call __chkesp (00401800) 004013C0 mov esp,ebp 004013C2 pop ebp 004013C3 ret
时间: 2024-10-21 10:28:07