前几天一直是用的CFree和DEV,装好VS2015以后今天试着用了一下,发现生成的反汇编代码可读性更强,以后就用它进行反汇编学习了。
C++源代码:
#include<iostream> using namespace std; class Test { public: int m; void setNumber(int nNumber) { m = nNumber; } }; int main() { Test test; test.setNumber(5); printf("%d", test.m); return 0; }生成的汇编代码:
#include<iostream> using namespace std; class Test { public: int m; void setNumber(int nNumber) { 002D1760 push ebp 002D1761 mov ebp,esp 002D1763 sub esp,0CCh 002D1769 push ebx 002D176A push esi 002D176B push edi 002D176C push ecx 002D176D lea edi,[ebp-0CCh] 002D1773 mov ecx,33h 002D1778 mov eax,0CCCCCCCCh 002D177D rep stos dword ptr es:[edi] 002D177F pop ecx 还原ecx 002D1780 mov dword ptr [this],ecx 将ecx处的数据存入this指针 m = nNumber; 002D1783 mov eax,dword ptr [this] 取出对象的首地址并存入eax 002D1786 mov ecx,dword ptr [nNumber] 取出参数中的数据并保存到ecx中 002D1789 mov dword ptr [eax],ecx 给成员赋值 } 002D178B pop edi 002D178C pop esi 002D178D pop ebx 002D178E mov esp,ebp 002D1790 pop ebp 002D1791 ret 4
int main() { 00D41870 push ebp 00D41871 mov ebp,esp 00D41873 sub esp,0D0h 00D41879 push ebx 00D4187A push esi 00D4187B push edi 00D4187C lea edi,[ebp-0D0h] 00D41882 mov ecx,34h 00D41887 mov eax,0CCCCCCCCh 00D4188C rep stos dword ptr es:[edi] 00D4188E mov eax,dword ptr ds:[00D48004h] 00D41893 xor eax,ebp 00D41895 mov dword ptr [ebp-4],eax Test test; test.setNumber(5); 00D41898 push 5 压入参数5 00D4189A lea ecx,[test] 取出对象的首地址存入ecx中 00D4189D call Test::setNumber (0D4120Dh) printf("%d", test.m); 00D418A2 mov eax,dword ptr [test] 取出对象首地址处4字节的数据m放入eax中 00D418A5 push eax 将eax中保存的数据成员m向成员函数传参 00D418A6 push 0D46B30h 00D418AB call _printf (0D4132Fh) 00D418B0 add esp,8 return 0; 00D418B3 xor eax,eax }在调用成员函数的过程中,编译器利用寄存器ecx保存了对象的首地址并以寄存器传参的的形式传递到成员函数中。这就是this指针的由来,由此可见,所有非静态成员函数都有一个隐藏参数,即自身类型的指针,这就是this指针,将这样的默认调用约定称为thiscall。在成员函数中访问数据成员也是通过this指针间接访问的,这便是为什么在成员函数内可以直接使用数据成员的原因。