debug版本
esp 栈顶指针
ebp 存放堆栈指针
空程序:
int main(){ 00411360 push ebp ;压入ebp00411361 mov ebp,esp ;ebp = esp,保留esp,待函数调用完再恢复,因为函数调用中肯定会用到esp.00411363 sub esp,0C0h ;esp-=0C0h(192);为该函数留出临时存储区;将其他指针或寄存器中的值入栈,以便在函数中使用这些寄存器。00411369 push ebx ;压入ebx0041136A push esi ;压入esi0041136B push edi ;压入edi0041136C lea edi,[ebp-0C0h] ;读入[ebp-0C0h]有效地址,即原esp-0C0h,正好是为该函数留出的临时存储区的最低位00411372 mov ecx,30h ;ecx = 30h(48),30h*4 = 0C0h00411377 mov eax,0CCCCCCCCh ;eax = 0CCCCCCCCh;0041137C rep stos dword ptr es:[edi] ;重复在es:[edi]存入30个;0CCCCCCCCh? Debug模式下把Stack上的变量初始化为0xcc,检查未初始化的问题return 0;0041137E xor eax,eax ;将eax清零,作为返回值};各指针出栈00411380 pop edi ;弹出edi00411381 pop esi ;弹出esi00411382 pop ebx ;弹出ebx00411383 mov esp,ebp ;esp复原00411385 pop ebp ;弹出ebp,也复原00411386 ret ;返回 函数调用:int _tmain(int argc, _TCHAR* argv[]){ 同上理解, 保存现场004113D0 push ebp 004113D1 mov ebp,esp 004113D3 sub esp,0F0h ;一共留了0F0h(240)空间004113D9 push ebx 004113DA push esi 004113DB push edi 004113DC lea edi,[ebp-0F0h] 004113E2 mov ecx,3Ch ; ecx = 3C(60),3C*4 = 0F0h,004113E7 mov eax,0CCCCCCCCh 004113EC rep stos dword ptr es:[edi] 同上理解. int a = 1, b = 2, c = 3;定义a,b,c并存储在为函数留出的临时存储空间中.004113EE mov dword ptr [a],1 004113F5 mov dword ptr [b],2 004113FC mov dword ptr [c],3 int d = Fun1(a, b, c);参数反向入栈
00411403 mov eax,dword ptr [c] 00411406 push eax 00411407 mov ecx,dword ptr [b] 0041140A push ecx 0041140B mov edx,dword ptr [a] 0041140E push edx 调用Fun10041140F call Fun1 (4111DBh) ;Call调用时将下一行命令的EIP压入堆栈恢复因为Fun1参数入栈改变的栈指针,因为Fun1有3个参数,一个整数4个字节,共0Ch(12)个字节00411414 add esp,0Ch 00411417 mov dword ptr [d],eax 将返回值保存在d中. return 0;返回值为0,让eax清零0041141A xor eax,eax}
恢复现场0041141C pop edi 0041141D pop esi 0041141E pop ebx 以下全为运行时ESP检查:先恢复因为为main预留空间而改变的栈指针0041141F add esp,0F0h 00411425 cmp ebp,esp 00411427 call @ILT+320(__RTC_CheckEsp) (411145h) 正常时只需要以下两句就可以正常恢复esp,再出栈,又可以恢复ebp.0041142C mov esp,ebp 0041142E pop ebp 0041142F ret ;main返回
release版本
void fun1(int na, int na2,int na3,int na4)
{ sub esp,0E4h ;预留出空间栈 mov eax,dword ptr [___security_cookie (11D3000h)] xor eax,esp mov dword ptr [esp+0E0h],eax ;堆栈平衡检查xxxxxxxx
}
mov ecx,dword ptr [esp+0E0h] xor ecx,esp call __security_check_cookie (11D1056h) ;堆栈平衡检查 add esp,0E4h ;还原esp ret
release版本编译器对函数内的汇编代码做了一定的简化,少了ebp