程序内存模型和栈帧结构

程序内存模型

在这里插入图片描述

在这里插入图片描述

  • 在x86体系中,栈顶由ESP寄存器,也被称为栈指针来标记,它是一个32位寄存器,里面存放着最后一个压入栈顶的项的内存地址,栈顶是朝着内存低地址方向增长的
  • 对于每一个进程,内核维护这一个变量brk(读作"break"),它指向堆的起始位置;

程序栈的结构

其中栈的结构是由栈帧组成,如下图所示:
在这里插入图片描述
C/C++语言中的函数,对应汇编中的过程。一个过程调用包括将数据(以过程参数和返回值的形式)和控制从代码的一部分传递到另一部分。另外,它还必须在进入时为过程的局部变量分配空间,并在退出时释放这些空间。上述的数据传递,局部变量的分配和释放通过操纵程序栈来实现。

程序通过栈来传递过程参数,存储返回信息,保存寄存器用于以后恢复,以及本地存储(临时/局部变量)。为单个过程分配的那部分称为栈帧(stack frame)

帧栈可以认为是程序栈的一段,它有两个端点,一个标识着起始地址,一个标识着结束地址,而这两个地址,则分别存储在固定的寄存器当中,即起始地址存在%ebp寄存器当中,结束地址存在%esp寄存器当中。也就是说寄存器 %ebp 为帧指针,寄存器 %esp 为栈指针。当程序执行时,栈指针可以移动(入栈出栈),因此大多数信息访问都是相对于帧指针的。(注:%esp与ESP是同一个寄存器的不同说法而已,%ebp同理)

假设过程P(调用者)调用过程Q(被调用者),则Q的参数放在P的栈帧中(这个比较好理解,P需要向Q传递参数)。另外,当P调用Q时,P中的返回地址被压入栈中,形成P的栈帧的末尾。返回地址就是当P从Q返回时应该继续执行的地方

正如前文所讲,栈向低地址方向增长。栈指针%esp指向栈顶元素,可以用push存入数据,用pop取出数据。将栈指针的值减小适当的大小可以分配没有指定初始值的数据的空间(加入数据时栈顶向低地址方向移动)。类似地,可以通过增加栈指针来释放空间(取出数据时栈顶向高地址方向移动)。

函数调用的实现

过程的实现主要就是在于数据如何在调用者和被调用者之间传递,以及在被调用者当中局部变量内存的分配以及释放。

而过程实现当中,参数传递以及局部变量内存的分配和释放都是通过以上介绍的栈帧来实现的,大部分情况下,我们认为过程调用当中做了以下几个操作。

①、备份原来的帧指针,调整当前的帧指针到栈指针的位置,这个过程就是我们经常看到的如下两句汇编代码做的事情。

pushl   %ebp
movl    %esp, %ebp 

②、建立起来的栈帧就是为被调用者准备的,当被调用者使用栈帧时,需要给临时变量分配预留内存,这一步一般是经过下面这样的汇编代码处理的。

subl    $16,%esp 

③、备份被调用者保存的寄存器当中的值,如果有值的话,备份的方式就是压入栈顶。因此会采用如下的汇编代码处理。

pushl    %ebx

④、使用建立好的栈帧,比如读取和写入,一般使用mov,push以及pop指令等等。

⑤、恢复被调用者寄存器当中的值,这一过程其实是从栈帧中将备份的值再恢复到寄存器,不过此时这些值可能已经不在栈顶了。因此在恢复时,大多数会使用pop指令,但也并非一定如此。

⑥、释放被调用者的栈帧,释放就意味着将栈指针加大,而具体的做法一般是直接将栈指针指向帧指针,因此会采用类似下面的汇编代码处理(也可能是addl)。

movl    %ebp,%esp 

⑦、恢复调用者的栈帧,恢复其实就是调整栈帧两端,使得当前栈帧的区域又回到了原始的位置。因为栈指针已经在第六步调整好了,因此此时只需要将备份的原帧指针弹出到%ebp即可。类似的汇编代码如下。

popl    %ebp 

⑧、弹出返回地址,跳出当前过程,继续执行调用者的代码。此时会将栈顶的返回地址弹出到PC,然后程序将按照弹出的返回地址继续执行。这个过程一般使用ret指令完成。

过程的实现大概就是以上八个步骤组成的,不过这些步骤并不都是必须的(大部分时候,开启编译器的优化会优化掉很多步骤)。

参考

内存中的堆和栈到底是什么
深入理解计算机系统(十九):过程(函数的调用原理)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值