【C语言】函数栈帧的创建与销毁

简介: 【C语言】函数栈帧的创建与销毁

  在学习函数栈帧的创建与销毁前,我们应该理解寄存器的概念作为铺垫:esp ebp  eax ebx ecx(本质是一个计数器) edx等寄存器,其中esp ebp尤为重要,这是因为这两个寄存器中存放的是地址,而这两个地址是用来维护栈帧的  


0.ebp和esp是如何来维护栈帧的呢?

       当我们调用Main函数时

a870334ffded4707bebbd001db202965.png

  注:通常我们成ebp为栈底指针,esp为栈顶指针,此外在32位环境下是ebp和esp而到了64位环境下栈底指针和栈顶指针变为rbp和rsp

       当我们弄懂了寄存器的概念,此时我们就正式开始学习函数的栈帧和创建,在学习前,带着疑问,进入学习:


1.为什么局部变量的值不初始化是随机的?

2.局部变量是怎么创建的?

3.函数是如何传参的?传参的顺序是怎样的?

4..函数是如何调用的?

5.形参和实参的关系?

6.函数调用结束后如何返回?


1.为什么局部变量的值不初始化是随机的?


       其他编辑器调用过程过于繁琐,不利于我们观察堆栈的调用过程,为了方便观察和学习,我们以VS2013为例,查看函数在堆栈中的调用情况


023e97dc8a624cecb2fbae53b54a9bce.png


我们使用ebp(rbp)和esp(rsp)来维护main函数的栈帧空间,首先进行压栈,此时esp栈顶指针的位置上移,而后将esp的地址赋给ebp,使得ebp指向了esp


adfadea9ec70422fa998f3193f028354.png而后我们开辟出了一块大为0E4h大小的栈帧空间,该空间即为main函数的栈帧空间,esp随着栈帧空间的开辟也随之发生了改变


1e58875b8b1c4a589a97d58b91351a76.png


而后我们再对其进行压栈,esp(栈顶指针)依旧随之发生改变



a218203448fc4f77847380bd2afd0377.png



 通过这步操作,我们将ebp-24h的空间地址存储到edi中,也就是main函数的栈帧空间地址,往下看发现,其实该步真正起作用的地方为rep,它的意思就是,从edi开始,ecx次将eax的内容初始化为CCCCCCCC


53e221cdafbf4de8a1a69096ab54faed.png


3 .函数是如何传参的?传参的顺序是怎样的


       传参时我们将ebp-14h和ebp-8的地址分别传给eax和ecx寄存器,并进行压栈,esp的地址也随之发生改变


720d910958454937b2c654002437519f.png



 我们通过该步骤调用了call命令,并将该地址保存在栈帧空间内部,esp再次发生改变,维护函数空间


1eba8b8ff34c4ca784b4013a1a35dac9.png



4.函数是如何调用的


通过该步骤,我们进行操作,将main函数的栈底进行压栈,esp的随栈帧空间发生改变,将esp的地址赋给ebp,我们开辟一块0CCh大小的空间,用来维护add函数的栈帧,对ebx,esi,edi等寄存器进行压栈,将epb-0Ch处的地址加载到edi中,同时初始化add函数栈帧空间的内容为0CCCCCCCCCh


4878a882dfee4f3a82a3d3797a1e2287.png




5.形参和实参的关系

      我们常说形参其实是实参的临时拷贝,改变形参其实是无法改变实参的,具体原因是怎样的?


该步骤,寻找到ebp-8的位置开辟变量Z的栈帧,将其初始化为0,将ebp+8和ebp+12的内容相加得出了x+y的和,其实我们这一步不难发现,我们在main函数中调用add函数进行传参,其实仅仅只是将实参的值放到两个寄存器内,进行压栈,我们在add函数中调用形参时,访问的其实是寄存器中的内容,这也是为什么,我们常说,形参是实参的临时拷贝,修改形参无法对实参造成任何影响


efaa5d05c9974302bea19c1b51a3439d.png



6.函数调用结束后如何返回?


当调用结束后,将ebp-8的内容存储到eax寄存器中,同时将edi esi ebx出栈,此时esp维护空间也发生了变化,esp+00Ch,此时销毁了add函数的栈帧空间,将ebp的地址赋给esp,但是我们在main函数中留有call函数的地址,将其弹出,回头main函数中,同时esp+8,栈顶指针再次发生改变,同时将eax中add函数的返回值放到ebp-20中,此时才是真正意义的返回


084d5603f7f0497f9a4402ae456a7fe7.png


目录
相关文章
|
2月前
|
存储 安全 C语言
深度剖析c语言程序 -- 函数栈帧的创建和销毁(纯肝货)-2
深度剖析c语言程序 -- 函数栈帧的创建和销毁(纯肝货)-2
|
2月前
|
存储 编译器 C语言
深度剖析c语言程序 -- 函数栈帧的创建和销毁(纯肝货)-1
深度剖析c语言程序 -- 函数栈帧的创建和销毁(纯肝货)-1
|
4月前
|
存储 编译器 程序员
C语言之反汇编查看函数栈帧的创建与销毁(一)
C语言之反汇编查看函数栈帧的创建与销毁(一)
C语言之反汇编查看函数栈帧的创建与销毁(一)
|
5月前
|
编译器 Linux C语言
函数栈帧的创建和销毁(以C语言代码为例,汇编代码的角度分析)(上)
函数栈帧的创建和销毁(以C语言代码为例,汇编代码的角度分析)
|
5月前
|
存储 C语言
打通你学习C语言的任督二脉-函数栈帧的创建和销毁(上)
打通你学习C语言的任督二脉-函数栈帧的创建和销毁(上)
45 0
|
3月前
|
存储 编译器 C语言
C语言:底层剖析——函数栈帧的创建和销毁
C语言:底层剖析——函数栈帧的创建和销毁
|
3月前
|
存储 编译器 C语言
C 语言函数栈帧的概念讲解
C 语言函数栈帧的概念讲解
30 0
|
4月前
|
存储 编译器 程序员
C语言之反汇编查看函数栈帧的创建与销毁(二)
C语言之反汇编查看函数栈帧的创建与销毁(二)
|
5月前
|
编译器 C语言
函数栈帧的创建和销毁(以C语言代码为例,汇编代码的角度分析)(下)
函数栈帧的创建和销毁(以C语言代码为例,汇编代码的角度分析)
|
6月前
|
存储 编译器 C语言
【C语言】函数栈帧的创建和毁销
【C语言】函数栈帧的创建和毁销
35 0