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