调用函数后的堆栈平衡

对于__stdcall调用方式,调用函数的逻辑一般如下

//Caller

;prolog
push xx
push ...
call callee
add esp x ; 恢复堆栈
;epilog

一般情况下,指令add esp x会恢复调用函数之前的栈顶指针。但并不是所有的情况都这样,例如,调用这个函数后,可能接着调用另外一个函数,这时候栈顶指针可能被修改为符合调用下个函数的esp值。例如主调函数会调用被调函数1及被调函数2,被调函数1的参数长度为8,被调函数2的参数长度为4,被调函数1执行完后,主调函数不会将esp的值加8(add esp 8),而是将esp值加4,使之成为适合调用被调函数2的栈结构。

以上我是通过自己写的某个测试代码发现的,其符合以下条件才会这样编译(未开启优化)

1. 两个被调用函数必须紧密连续被调用,之间没有其它的逻辑。

2. 存在浮点数参数。

例如以下代码

void loadfloat(int a,float f)
{
	f+=a;
}

void loaddouble(int b, double d)
{
	d-=b;
}

int _tmain(int argc, _TCHAR* argv[])
{
	int a=3;
	float f = 1.2f;
	double de = 3.4;
<pre class="cpp" name="code">	loaddouble(a,de);
              
	loadfloat(a,f);

return 0;}
 


反编译为

int _tmain(int argc, _TCHAR* argv[])
{
00211020  push        ebp  
00211021  mov         ebp,esp  
00211023  sub         esp,10h  
	int a=3;
00211026  mov         dword ptr [a],3  
	float f = 1.2f;
0021102D  fld         dword ptr [__real@3f99999a (21A818h)]  
00211033  fstp        dword ptr [f]  
	double de = 3.4;
00211036  fld         qword ptr [__real@400b333333333333 (21A810h)]  
0021103C  fstp        qword ptr [de]  
	loaddouble(a,de);
0021103F  sub         esp,8  
00211042  fld         qword ptr [de]  
00211045  fstp        qword ptr [esp]  
00211048  mov         eax,dword ptr [a]  
0021104B  push        eax  
0021104C  call        loaddouble (211010h)  
	loadfloat(a,f);
00211051  add         esp,8  
00211054  fld         dword ptr [f]  
00211057  fstp        dword ptr [esp]  
0021105A  mov         ecx,dword ptr [a]  
0021105D  push        ecx  
0021105E  call        loadfloat (211000h)  
00211063  add         esp,8  
	return 0;
00211066  xor         eax,eax  
}


请大家注意,loaddouble的参数总长度为12,但是调用完毕后确实是add esp 8,已满足下个被调函数的堆栈布局。若是在两个子函数之间随意插入一个逻辑,例如


 

loaddouble(a,de);
a++;               
loadfloat(a,f);

则编译器不会执行这种优化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值