_stdcall 函数 debug/release汇编代码区别

Posted 菜b

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了_stdcall 函数 debug/release汇编代码区别相关的知识,希望对你有一定的参考价值。

debug版本

 

esp 栈顶指针

ebp 存放堆栈指针

 

空程序:
int main()
{
00411360 push ebp ;压入ebp
00411361 mov ebp,esp ;ebp = esp,保留esp,待函数调用完再恢复,因为函数调用中肯定会用到esp.
00411363 sub esp,0C0h ;esp-=0C0h(192);为该函数留出临时存储区
;将其他指针或寄存器中的值入栈,以便在函数中使用这些寄存器。
00411369 push ebx ;压入ebx
0041136A push esi ;压入esi
0041136B push edi ;压入edi
0041136C lea edi,[ebp-0C0h] ;读入[ebp-0C0h]有效地址,即原esp-0C0h,正好是为该函数留出的临时存储区的最低位
00411372 mov ecx,30h ;ecx = 30h(48),30h*4 = 0C0h
00411377 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 ;弹出edi
00411381 pop esi ;弹出esi
00411382 pop ebx ;弹出ebx
00411383 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
调用Fun1
0041140F 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

 

以上是关于_stdcall 函数 debug/release汇编代码区别的主要内容,如果未能解决你的问题,请参考以下文章

为 __stdcall 函数指针提供比预期更多的参数

如何运用c++里的“__stdcall”?

函数调用方法之__cdecl与_stdcall

__stdcall__cdcel和__fastcall三者的区别

_stdcall 与 _cdecl 区别

_stdcall 与 _cdecl 区别