函数调用堆栈(1)

函数调用:我们先来看看底下的这一段代码:

int sum(int a,int b)
{
        int tmp=0;
    tmp=a+b;
    return  tmp;
}
int main()
{
    int a=10;
    int b=20;
    int ret=0;
    ret=sum(a,b);
    printf("%d\n",ret);
        return 0;
}

那么我们考虑几个问题:
1、额,我们都知道函数运行从主函数开始,那么运行到 ret=sum(a,b) 是怎么跳到sum函数的?
2、执行sum函数的时候,是怎么把tmp 的值带回来到主函数并赋值给 ret 的呢?
3、从sum函数返回怎么知道返回到 ret=sum(a,b) 并执行下一条语句,而不是返回到主函数的开始呢?

带着这几个问题,我们一起来探究到底是怎么回事?
程序执行的时候需要用到虚拟地址空间里的栈,把一些进程运行的参数保存到栈中。

我们看看上面程序的汇编代码:注意啊,看不懂下面的代码没关系,会有图解哟,耐心看图解吧。
主函数的反汇编:

int main()
{
012D1880  push        ebp  
012D1881  mov         ebp,esp  
012D1883  sub         esp,0E4h  
012D1889  push        ebx  
012D188A  push        esi  
012D188B  push        edi  
012D188C  lea         edi,[ebp-0E4h]  
012D1892  mov         ecx,39h  
012D1897  mov         eax,0CCCCCCCCh  
012D189C  rep stos    dword ptr es:[edi]  
    int a=10;
012D189E  mov         dword ptr [ebp-4],0Ah  
    int b=20;
012D18A5  mov         dword ptr [ebp-8],14h  
    int ret=0;
012D18AC  mov         dword ptr [ebp-0ch],0  
    ret=sum(a,b);
012D18B3  mov         eax,dword ptr [b]  //其实就是变量b所在的地址
012D18B6  push        eax  
012D18B7  mov         ecx,dword ptr [a]  
012D18BA  push        ecx  
012D18BB  call        sum (012D1082h)  
012D18C0  add         esp,8  
012D18C3  mov         dword ptr [ret],eax  
    printf("%d\n",ret);

sum函数的反汇编:

int sum(int a,int b)
{
00E91830  push        ebp  
00E91831  mov         ebp,esp  
00E91833  sub         esp,0CCh  
00E91839  push        ebx  
00E9183A  push        esi  
00E9183B  push        edi  
00E9183C  lea         edi,[ebp-0CCh]  
00E91842  mov         ecx,33h  
00E91847  mov         eax,0CCCCCCCCh  
00E9184C  rep stos    dword ptr es:[edi]  
    int tmp=0;
00E9184E  mov         dword ptr [tmp],0  
    tmp=a+b;
00E91855  mov         eax,dword ptr [a]  
00E91858  add         eax,dword ptr [b]  
00E9185B  mov         dword ptr [tmp],eax  
    return  tmp;
00E9185E  mov         eax,dword ptr [tmp]  
}
00E91861  pop         edi  
00E91862  pop         esi  
00E91863  pop         ebx  
00E91864  mov         esp,ebp  
00E91866  pop         ebp  
00E91867  ret  

我们一点一点分析:
图一:
这里写图片描述
图二:
这里写图片描述
图三:
这里写图片描述
图四:
这里写图片描述
图五:
这里写图片描述
调用堆栈就是这样啦!
总结一下函数调用的过程:
这里写图片描述

猜你喜欢

转载自blog.csdn.net/lyt15829797751/article/details/78379053