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等的可变参数个数功能,因为子函数不知道具体有多少要参数进入了,只有调用处才知道)