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
![](http://hi.csdn.net/attachment/201107/9/0_1310229023Ttta.gif)
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等的可变参数个数功能,因为子函数不知道具体有多少要参数进入了,只有调用处才知道)