函数调用堆栈变化情况

int goo(int a, int b)
{
	return a + b;
}

void foo()
{
	int a[] = {1, 2, 3};
	int result = goo(a[1], a[2]);
	printf("result: %d", result);
}

VS2010下编译


foo函数部分汇编:

00EB3890  push        ebp  
00EB3891  mov         ebp,esp  
00EB3893  sub         esp,0E4h  
00EB3899  push        ebx  
00EB389A  push        esi  
00EB389B  push        edi  
00EB389C  lea         edi,[ebp-0E4h]  
00EB38A2  mov         ecx,39h  
00EB38A7  mov         eax,0CCCCCCCCh  
00EB38AC  rep stos    dword ptr es:[edi]  
00EB38AE  mov         eax,dword ptr [___security_cookie (0EB7000h)]  
00EB38B3  xor         eax,ebp  
00EB38B5  mov         dword ptr [ebp-4],eax  
	int a[] = {1, 2, 3};
00EB38B8  mov         dword ptr [ebp-14h],1  
00EB38BF  mov         dword ptr [ebp-10h],2  
00EB38C6  mov         dword ptr [ebp-0Ch],3  
	int result = goo(a[1], a[2]);
00EB38CD  mov         eax,dword ptr [ebp-0Ch]  
00EB38D0  push        eax  
00EB38D1  mov         ecx,dword ptr [ebp-10h]  
00EB38D4  push        ecx  
00EB38D5  call        goo (0EB11E5h)  
00EB38DA  add         esp,8  

goo函数完整汇编:

00EB1580  push        ebp  
00EB1581  mov         ebp,esp  
00EB1583  sub         esp,0C0h  
00EB1589  push        ebx  
00EB158A  push        esi  
00EB158B  push        edi  
00EB158C  lea         edi,[ebp-0C0h]  
00EB1592  mov         ecx,30h  
00EB1597  mov         eax,0CCCCCCCCh  
00EB159C  rep stos    dword ptr es:[edi]  
	return a + b;
00EB159E  mov         eax,dword ptr [a]  
00EB15A1  add         eax,dword ptr [b]  
}
00EB15A4  pop         edi  
00EB15A5  pop         esi  
00EB15A6  pop         ebx  
00EB15A7  mov         esp,ebp  
00EB15A9  pop         ebp  
00EB15AA  ret  


foo函数push ebp, mov ebp, esp后

保存原ebp,设定新的ebp为当前esp位置



sub esp, 0E4h

给局部变量分配足够大的栈空间


保存原先的一些寄存器值,每次push,esp继续向下移



为局部变量a数组赋值


调用goo前Push两个参数,esp继续下移


call goo函数时,cpu自动push下一条指令地址,esp继续下移

在goo函数中,同样保存foo函数中的ebp值,设定新的ebp,esp等


在执行玩goo函数最后几句指令时,edi, esi, ebx恢复,esp同时也编程goo中ebp的位置,ebp恢复至foo函数原来的位置(pop ebp)

下一条指令也装入IP(ret指令),esp继续向上一步



foo函数中的add esp, 8将esp值继续往上(清除函数参数)

清除函数参数的工作也可通过ret X在goo函数返回时设定(这样的话不必在每次调用点上加上add esp, X指令缩短了编译出来的文件大小,但在子函数中清除将不能做到printf等的可变参数个数功能,因为子函数不知道具体有多少要参数进入了,只有调用处才知道)


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值