先貼出自己寫的測試代碼:
int* M2(int* p) { return p+1; } int M(int a, char b) { int* pp = M2(&a); return *pp; } int _tmain(int argc, _TCHAR* argv[]) { int e=0; int d = M(3,'c'); getchar(); return 0; }
然后來一層一層的分析:
調用函數Main
008B1030 push ebp // 將ebp的值壓入棧 008B1031 mov ebp,esp // 將esp的值賦值給ebp 008B1033 sub esp,8 // esp-8,為了空出變量e,d的空間 int e=0; 008B1036 mov dword ptr [e],0 // 將e的值設置為0 int d = M(3,'c'); 008B103D push 63h // 將'c'壓入棧 008B103F push 3 // 將整數3壓入棧 008B1041 call M (8B1010h) // 調用函數M
此時函數堆棧的情況大致如下:
調用函數M
int M(int a, char b) { 01391010 push ebp // 將ebp的值壓入棧 01391011 mov ebp,esp // 將esp的值賦值給ebp 01391013 push ecx // ecx壓入棧 int* pp = M2(&a); 01391014 lea eax,[a] // 將變量a的地址賦給eax 01391017 push eax // 將eax壓入棧 01391018 call M2 (1391000h) // 調用函數M2()
調用函數M2
int* M2(int* p) { 01391000 push ebp // ebp入棧 01391001 mov ebp,esp // ebp = esp return p+1; 01391003 mov eax,dword ptr [p] // eax = p; 01391006 add eax,4 // eax+=4; } 01391009 pop ebp // 將棧頂的值彈出給ebp 0139100A ret // 返回
01391018 call M2 (1391000h) // 調用函數M2() 0139101D add esp,4 // esp+=4 01391020 mov dword ptr [pp],eax // eax的值賦給pp return *pp; 01391023 mov ecx,dword ptr [pp] // 將pp指向的地址賦值給ecx 01391026 mov eax,dword ptr [ecx] // 將ecs指向的地址賦值為eax } 01391028 mov esp,ebp 0139102A pop ebp 0139102B ret