空间的栈式分配

摘要:有些语言使用过程、函数或方法作为用户自定义的单元,几乎所有针对这些语言的编译器都把他们的(至少一部分)运行时刻存储按照一个栈进行管理,每当一个过程被调用时,用于存放该过程的局部变量的空间被压入栈,当这个过程结束时,该空间被弹出这个栈,这些安排不仅允许活跃时段不交叠的多个过程调用之间共享空间,而且允许我们以以下方式为一个过程编译代码:它的局部变量的相对地址总是固定的,和过程调用的序列无关。

1.活动树(过程调用的嵌套模型)

例子:快排伪代码如下:

在活动树和程序行为之间存在下列多种有用的对应关系,正是这种对应关系使我们能够使用运行时刻栈:

1)过程调用的序列和活动树的前序遍历相对应;

2)过程返回的序列和活动树的后序遍历相对应;

3)假定控制流位于某个过程的特定活动中,且该活动对应于活动树上的某个结点N。那么当前尚未结束的(即活跃的)活动就是结点N及其祖先结点对应的活动。这些活动被调用的顺序就是他们从根节点到N的路径上的出现顺序。这些活动将按照这个顺序的反序返回。

树中每个结点对应一个活动,根结点是启动程序执行的main过程的活动,在表示过程p的某个活动结点上,其子节点对应于被p的这次活动调用的各个过程的活动。我们按照这些活动被调用的顺序,自左向右的显示他们。注意:一个子结点必须在其右兄弟结点活动开始之前结束。

2.活动记录(frame帧)

过程调用和返回通常由一个称为控制栈(control stack)的运行时刻栈进行管理。每个活跃的活动都有一个位于控制栈中的活动记录(frame),活动树的根位于栈底,栈中全部活动记录的序列对应于活动树中到达当前控制所在的活动结点的路径。程序控制所在的活动的记录位于栈顶。

例:假设当前控制位于活动树中q(2,3)上,那么q(2,3)对应的活动记录在控制栈的顶端。紧跟在下面的是q(1,3)的活动记录,即树中q(2,3)的父节点。再下面是q(1,9)的活动记录。栈的底端是函数m的活动记录,也就是树的根。

活动记录结构图:

3.调用代码序列关系图

几点说明:

1)在调用者和被调用者之间传递的值一般放在被调用者的活动记录的开始位置,它们尽可能的靠近调用者的活动记录,这样做的动机是,调用者能够计算该次调用的实在参数的值并将它放在自身活动记录的顶部(被调用者的底部),这样一来,由于参数及返回值长度确定,(即使是变参函数:如printf(), 也能够根据第一个参数,判断其他参数,因此长度也能确定下来),使得被调用者返回时,主调函数自己去被调函数的参数和返回值字段顺序取值,而不必关心被调用者活动记录的空间布局及工作方式;

2)固定长度的项被放在中间位置,包括控制链、访问链和机器状态字段,如果每次调用中保存的机器状态的成分相同,那么可以使用同一代码来保存和恢复每次调用的结果,不仅如此,如果将机器状态信息标准化,那么当错误发生时,诸如调试工具这样的程序将可以更容易的将栈中的内容解码。

3)大部分局部变量具有固定的长度,编译器通过检查其类型就可以确定,然而还是存在有些局部变量的大小只有在程序运行时才能确定下来,比如动态数组,数组大小可能要根据调用者的某个参数才能决定。另外,临时变量所需要的空间大小通常依赖于代码生成阶段能够将多少临时变量放在寄存器中。所以编译器最终会知道临时变量做需要的空间大小,但在刚开始生成代码的时候并不知道该空间的大小。

4)调用者和被调用者合作管理调用栈的例子:当寄存器top_sp指向当前顶层活动记录中机器状态字段的末端,调用者知道这个位于被调用者的活动记录中的位置。因此调用者可以负责在控制权转向被调用者之前设定top_sp的值。这个调用代码序列以及与被调用者之间的划分描述如下:

           <1>调用者计算实在参数的值;

           <2>调用者将返回地址和原来的top_sp值存放到被调用者的活动记录中。然后。调用者增加top_sp的值。也就是说top_sp越过了调用者的局部数据和临时变量以及被调用者的参数、返回值和机器状态字段

           <3>被调用者保存寄存器的值和其他状态信息;

           <4>被调用者初始化其局部数据并开始执行, 并将返回值放到与参数相邻的位置;

           <5>使用机器状态字段中的信息,被调用者恢复top_sp和其他寄存器,然后跳转到由调用者放在机器状态字段中的返回地址(控制链);

            <6>尽管top_sp值已经被减小,但调用者仍然知道返回值相对于当前top_sp值的位置,因此调用者可以找到并使用那个返回值。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值