例:
#include<stdio.h>
int sum(int a,int b)
{
int tmp = 0;
tmp = a + b;
return tmp;
}
int main()
{
int x = 10;
int y = 20;
int ret = 0;
ret = sum(x,y);
printf("%d\n",ret);
return 0;
}
//汇编代码:
/*--- f:\c代码\函数调用堆栈\函数调用堆栈\0403.cpp ----------------------------------------------
#include<stdio.h>
int sum(int a,int b)
{
008813B0 push ebp //栈底指针
008813B1 mov ebp,esp //esp 栈顶指针
008813B3 sub esp,0CCh //esp -= 0CCh
008813B9 push ebx
008813BA push esi
008813BB push edi
008813BC lea edi,[ebp-0CCh] //lea 将后面的 地址赋给edi
008813C2 mov ecx,33h //mov 将33h赋给ecx
008813C7 mov eax,0CCCCCCCCh
008813CC rep stos dword ptr es:[edi] //rep stos 相当于for循环,循环拷贝
int tmp = 0;
008813CE mov dword ptr [tmp],0
tmp = a + b;
008813D5 mov eax,dword ptr [a]
008813D8 add eax,dword ptr [b]
008813DB mov dword ptr [tmp],eax
return tmp;
008813DE mov eax,dword ptr [tmp]
}
008813E1 pop edi
008813E2 pop esi
008813E3 pop ebx
008813E4 mov esp,ebp
008813E6 pop ebp
008813E7 ret
/*--- f:\c代码\函数调用堆栈\函数调用堆栈\0403.cpp ----------------------------------------------
int main()
{
00881400 push ebp
00881401 mov ebp,esp
00881403 sub esp,0E4h
00881409 push ebx
0088140A push esi
0088140B push edi
0088140C lea edi,[ebp-0E4h]
00881412 mov ecx,39h
00881417 mov eax,0CCCCCCCCh
0088141C rep stos dword ptr es:[edi]
int x = 10;
0088141E mov dword ptr [x],0Ah
int y = 20;
00881425 mov dword ptr [y],14h
int ret = 0;
0088142C mov dword ptr [ret],0
ret = sum(x,y);
00881433 mov eax,dword ptr [y]
00881436 push eax
00881437 mov ecx,dword ptr [x]
0088143A push ecx
0088143B call sum (88105Fh) //**在call sum之前需要将下一行指令的地址入栈,这样sum函数回退就知道下一步该执行哪一行指令了**
00881440 add esp,8
00881443 mov dword ptr [ret],eax
printf("%d\n",ret);
00881446 mov esi,esp
00881448 mov eax,dword ptr [ret]
0088144B push eax
0088144C push offset string "%d\n" (88573Ch)
00881451 call dword ptr [__imp__printf (8882BCh)]
00881457 add esp,8
0088145A cmp esi,esp
0088145C call @ILT+315(__RTC_CheckEsp) (881140h)
return 0;
00881461 xor eax,eax
}
00881463 pop edi
00881464 pop esi
00881465 pop ebx
00881466 add esp,0E4h
0088146C cmp ebp,esp
0088146E call @ILT+315(__RTC_CheckEsp) (881140h)
00881473 mov esp,ebp
00881475 pop ebp
00881476 ret */
局部变量int x = 0; int y = 0;等属于指令,不属于数据,在可重定位目标文件中在.text段存放,并且都是通过ebp指针的偏移量来表示其地址。
由汇编代码可以看出函数入栈和回退的过程:
1、main函数调用完sum,需要回到main
2、回来后,继续从调用sum的下一句指令开始执行
3、形参内存的开辟是在主调函数中开辟,形参内存的回退也是在主调函数中回退。
4、实参是从右至左的顺序入栈
5、函数的返回值是通过一个4字节的寄存器带出来的
思考:函数的返回值是怎么带出来的?
见下次博客。。。。