您的位置:首页 > 其它

函数调用堆栈的过程

2018-04-03 10:21 204 查看
例:

#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 
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字节的寄存器带出来的

[b]思考:函数的返回值是怎么带出来的?


见下次博客。。。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: