想必大家在学完C语言函数章节之后,是否有这样的困惑:
- 局部变量是怎么创建的 ?
- 为什么局部变量的值是随机值 ?
- 函数是怎么传参的?传参的顺序又是什么样的 ?
- 形参和实参是什么关系 ?
- 函数调用是怎么做的 ?
- 函数调用结束后是怎么返回的 ?
今天我们来学习函数栈帧的创建与销毁,让我们一起了解更多的底层原理,看完之后这些问题都迎刃而解了!!!
注:在不同编译器下,函数调用过程中栈帧的创建是略有差异的,具体细节诎诘语编译器的实现
演示环境:Win10+x86+Vs2013
一 .函数栈帧的创建与销毁过程
在介绍函数栈帧的创建之前,我们首先要了解一个东西--------------------寄存器
寄存器的种类有很多种,今天主要介绍两种:
ebp和esp 这两个寄存器存放的是地址,用来维护函数栈帧的,简单来说就是维护函数开辟的那一块空间
每一个函数的调用,都要在栈区开辟一块空间,而ebp和esp就是维护这块空间的,如下图:
为了方便演示,我们编写一个加法程序:
intAdd(intx, inty) { intz=0; z=x+y; returnz; } intmain() { inta=10; intb=20; intc=0; c=Add(a, b); printf("%d", c); return0; }
接下来就是函数栈帧的创建和销毁,这里我们需要打开反汇编代码,逐条分析:
操作步骤:F10----->光标停留在代码块处右击鼠标----->转到反汇编
main函数汇编代码:
1.intmain() { 002718A0pushebp002718A1movebp,esp002718A3subesp,0E4h002718A9pushebx002718AApushesi002718ABpushedi002718ACleaedi,[ebp-24h] 002718AFmovecx,9002718B4moveax,0CCCCCCCCh002718B9repstosdwordptres:[edi] 002718BBmovecx,27C003h002718C0call0027131Binta=10; 002718C5movdwordptr [ebp-8],0Ahintb=20; 002718CCmovdwordptr [ebp-14h],14hintc=0; 002718D3movdwordptr [ebp-20h],0c=Add(a, b); 002718DAmoveax,dwordptr [ebp-14h] 002718DDpusheax002718DEmovecx,dwordptr [ebp-8] 002718E1pushecx002718E2call002710B4002718E7addesp,8002718EAmovdwordptr [ebp-20h],eaxprintf("%d", c); 002718EDmoveax,dwordptr [ebp-20h] 002718F0pusheax002718F1push277B30h002718F6call002710D2002718FBaddesp,8return0; 002718FExoreax,eax} 00271900popedi00271901popesi00271902popebx00271903addesp,0E4h00271909cmpebp,esp0027190Bcall0027124400271910movesp,ebp00271912popebp00271913ret
首先我们要知道,main函数也是被其他函数所调用的,它是被_tmainCRTStartup这个函数所调用,我们这里主要说明函数栈帧的创建和销毁,所以这里就不带大家介绍这个函数的由来了,如果感兴趣可以自己去翻阅一下资料------