编译原理
  • 编译原理
  • 一些简答题
  • 绪论
    • 编译器简介
    • 程序设计语言
    • 静态与动态
    • 参数传递机制
  • 词法分析
    • 词法单元、模式、词素
    • 串和语言
    • 正则表达式
    • 状态转换图
    • 不确定有穷自动机NFA
    • 确定有穷自动机DFA
    • 算法:正则表达式转NFA
    • 自动机到词法分析器
  • 语法分析
    • 语法分析器
    • 上下文无关文法
    • 二义性和左递归
    • 递归下降语法分析
    • 算法:求解FIRST集和FOLLOW集
    • 算法:LL(1)
    • 自底向上语法分析
    • 移入-归约语法分析
    • 算法:LR(0)
    • 算法:SLR(1)
    • 算法:LR(1)
    • 算法:LALR
    • LR分析器和LALR分析器
  • 语法制导
    • 语法制导定义(SDD)
    • 综合属性和继承属性
    • 语法树上的SDD求值
    • 依赖图
    • L属性的SDD
    • 类型
    • SDD的应用
  • 中间代码生成
    • 三地址代码
    • SSA(静态单赋值)
    • 类型和声明
    • 表达式的翻译
    • 类型检查
    • 控制流
    • 回填
  • 运行时刻环境
    • 存储组织
    • 栈式分配
    • 栈中非局部数据的访问
    • 堆管理
    • 垃圾回收
  • 代码生成
    • 代码生成器的设计
    • 目标语言
    • 目标代码中的地址
    • 基本块和流图
    • 基本块的优化
Powered by GitBook
On this page
  • 非局部数据的访问(无嵌套过程)
  • 非局部数据的访问(有嵌套过程)
  • 嵌套深度
  • 访问链
  • 访问链的维护
  • 显示表
  1. 运行时刻环境

栈中非局部数据的访问

Previous栈式分配Next堆管理

Last updated 4 months ago

非局部数据的访问(无嵌套过程)

C语言中每个函数能访问的变量:

  • 函数的局部变量:相对位置已知,且存放在当前活动记录内,top_sp指针加上相对地址即可访问

  • 全局变量:在静态区,地址在编译时刻可知

很容易将C语言的函数作为参数进行传递,参数中只需包含函数代码的开始地址,在函数中访问非局部变量的模式很简单,不需要考虑过程是如何激活的。

非局部数据的访问(有嵌套过程)

PASCAL中,如果过程A的声明中包含了过程B的声明,那么B可以使用在A中声明的变量。当B的代码运行时,如果它使用的是A中的变量,必须通过访问链访问。

嵌套深度

嵌套深度可以根据源程序静态确定,不内嵌于任何其他过程的过程,深度为1;嵌套于深度为i的过程的深度是i+1。

访问链

访问链被用于访问非局部的数据:

  • 如果过程p在声明时(直接)嵌套在过程q中,那么p活动记录中的访问链指向上层最近的q的活动记录

  • 从栈顶活动记录开始,访问链形成了一个链路,嵌套深度沿着链路逐一递减

设深度为np的过程p访问变量x,而变量x在深度为nq的过程q中声明:

  • np-nq在编译时刻已知,从当前活动记录出发,沿访问链前进np-nq次找到活动记录

  • x相对于这个活动记录的偏移量在编译时刻已知

访问链的维护

当过程q调用过程p时:

  • p的深度大于q:根据作用域规则,p必然在q中直接定义;那么p的访问链指向当前活动记录(即q)

  • 递归调用p=q:新活动记录的访问链等于当前记录的访问链(即和前一个q指向同一目标)

  • p的深度小于q:必然有过程r,p直接在r中定义,而q嵌套在r中;p的访问链指向栈中r的活动记录。

在传递过程指针参数时,过程型指针参数中不仅包含过程的代码指针(开始地址),还包括正确的访问链。

显示表

用访问链访问数据,访问开销与嵌套深度差有关。使用显示表可以提高效率,访问开销为常量。显示表使用数组d为每个嵌套深度保留一个指针,指针d[i]指向栈中最近的、嵌套深度为i的活动记录。如果过程p访问嵌套深度为i的过程q中声明的变量x,那么d[i]直接指向相应的活动记录(i在编译阶段已知)。

调用过程p时,在p的活动记录中保存d[np]的值,并将d[np]设置为当前活动记录(即p),从p返回时,恢复d[np]的值。