函数调用堆栈的过程

例:

#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字节的寄存器带出来的
思考:函数的返回值是怎么带出来的?
见下次博客。。。。

猜你喜欢

转载自blog.csdn.net/wjh814/article/details/79799490