编译原理实践

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

运行时存储空间的划分
目标代码区 静态数据区 栈 自由空间

存储分配策略
静态存储分配 在运行前就能确定数据空间的大小,因 而在编译时就能分配各种数据项的空间, 如FORTRAN语言 动态存储分配 不能在编译时完全确定所有数据项的存 储空间,只能在编译时产生各种必要的 信息,而在运行时,再动态地分配数据 项的存储空间。包括栈式动态存储分配 和堆式动态存储分配
编译原理实践 --运行时的存储组 织与分配
在程序的执行过程中,程序中数据的存取是通过对应 的存储单元进行的。在早期的计算机上,这个存储管 理工作是由程序员自己来完成。在程序执行以前,首 先要将用机器语言或汇编语言编写的程序输送到内存 的某个指定区域中,并预先给变量和数据分配相应的 内存地址。而有了高级语言之后,程序员不必直接和 内存地址打交道,程序中使用的存储单元都由逻辑变 量(标识符)来表示,它们对应的内存地址都是由编译 程序在编译时分配或由其生成的目标程序运行时进行 分配。所以,对编译程序来说,存储的组织及管理是 一个复杂而又十分重要的问题。另外,有些程序设计 语言允许有递归过程,有的允许有可变长度的串,有 的允许有动态数组,而有些语言则不允许有这些,为 什么呢?这都是因为采用了不同的存储分配方式。
如赋值语句X := Y op Z(op为某个运算 符),将被翻译成下面的目标代码序列: (设指令计数从第100号开始)
100 101 102 103 LOD LOD OPR STO Level_diff_Y ,Addr_Y Level_diff_Z,Addr_Z 0,op Level_diff_X,Addr_X
1. 编译时为每一变量名、过程名和程序段确定 一个反映静态嵌套深度的级别level 2. 采用数据栈的管理方式,先进后出。在解释 执行前,数据栈是空栈,栈顶地址t=0 3. 调用一个过程时,先在栈顶为过程分配确定 的存储单元,包括:
1.
2. 3. 4.
ຫໍສະໝຸດ Baidu
静态链接SL单元 动态链接DL单元 返回地址RA单元 为过程局部变量预留的存储单元
1)栈式动态存储分配: 运行时,每当进入一个分程序或过程,其中各 项数据项所需的存储空间就动态地分配于栈顶, 退出时,则释放所占用的空间 特点:效率很高,但是分配的内存容量有限 2)堆式动态存储分配: 允许用户动态申请存储空间,每当需要时可从 堆中分得一块,用完之后再退还给堆 特点:动态内存的生存期由我们决定,使用非常 灵活,但问题也最多 注意:我们接下来只讨论栈式动态存储分配
1、存储组织概述
程序运行时,系统将为程序分配一块存储空间。 这块空间用来存储程序的目标代码以及目标代 码运行时需要或产生的各种数据: 1) 目标程序区:用来存放目标代码。 2) 静态数据区:用来存放编译时就能确定存 储空间的数据。 3) 运行栈区:用来存放运行时才能确定存储 空间的数据。 4) 运行堆区:用来存放运行时用户动态申请 存储空间的数据。
main p Q SP call Q
Q’s AR (2) Q’s AR (1) p’s AR main’s AR 栈 增 长 方 向
call Q
call p
过程的一次执行对应一个AR
1)简单语言的栈式存储分配
简单语言:无分程序结构,过程定义不 嵌套,但允许过程的递归调用。如C语言。 C语言不允许过程嵌套定义,即不允许在 一个过程内定义另一个过程。C语言的全 局变量只能出现在源程序的开头,可采 用静态存储分配,编译时候就确定它们 的地址 计算局部变量或形参绝对地址的公式为: 绝对地址=SP+相对地址 比较简单,具体不再讨论
3. 所有运算操作都从栈顶找到它的操作数,并以计算结 果代之
编译原理实践 --目标计算机及其 解释程序
当前任务:将PL/0源程序翻译成为目 标代码程序 通常先将源程序翻译成一种中间代码程 序,然后再对中间代码程序进行处理
1.
2.
将中间代码程序翻译成某一种计算机的汇 编指令程序,由该计算机的汇编程序对生 成的汇编指令程序汇编,获得可以在该计 算机上执行的目标程序 编写一个独立的解释程序,解释执行生成 的中间代码程序
注意:这里的假设与我们的编译概念并 不矛盾,在本课程中我们写的只是一个 示范性的编译程序,它的后端无法完整 地实现,因而只能在一个解释性的环境 下予以模拟。从另一个角度上讲,把解 释程序就看成是PL/0机硬件,把解释执 行看成是PL/0的硬件执行,那么我们所 做的工作:由PL/0源语言程序到PL/0机 器指令的变换,就是一个完整的编译程 序。
PL/0编译程序不仅完成通常的词法分析、 语法分析,而且还产生中间代码和“目 标”代码。最终我们要“运行”该目标 码。为了不致陷入与本课程无关的实际 机器的特有性质的考虑中去,我们假想 有台适合PL/0程序运行的计算机,我们 称之为PL/0处理机。PL/0处理机顺序解 释生成的目标代码,我们称之为解释程 序。
2)嵌套过程语言的栈式存储分配
嵌套过程语言:允许过程嵌套,如 pascal,PL/0。AR中必须有一些内容,用于解 决对非局部变量的引用问题 “嵌套层次”,或称层数。主程序为0,过程S 在层数为i的过程R定义,则S层数为i+1 一个过程可以引用包围它的任一外层过程所定 义的变量,解决方法很多,常见的方法:双指 针方法和Display表方法 双指针方法简单直接,但当嵌套层次较多时, 对非局部量的访问效率较低! Display表方法效率较高,实现略复杂 对于PL/0的编译程序,采用的是双指针方法
返回指针 returned pointer 动态链 dynamic link 静态链 static link 机器状态 machine states 参数单元 parameters 局部变量 local variables 临时变量 temporaries
低地址
高地址
i. 被调用过程非局部变 量存储区的首地址 (静态链、Display表) ii. 调用过程的AR首址 (动态链,oldSP) iii. 调用点的机器状态 iv. 形实参数通讯区 v. 返回值 vi. 被调用过程的局部量 和临时变量存储区
PL/0数据动态存储采用的技术措施
1. 编译时为每一变量名、过程名和程序段确定一个反映 静态嵌套深度的级别level 2. 调用一个过程时,把他的活动记录压入运行时的栈顶, 返回时弹出相应的活动记录。活动记录包括:
1. 2. 3. 4.
静态链接SL:指向定义该过程的直接外层过程的活动记录的 基地址,以确保变量的正确存取 动态链接DL:指向调用该过程前正在运行的那个过程的活动 纪录的基地址,以确保能返回到调用过程段 返回地址RA:保存该被调用过程返回后的地址,也就是调用 过程指令的下一条指令的地址 为过程局部变量预留的存储单元
目标计算机的组织结构和指令格式 数据存储器的动态存储器管理 目标计算机指令系统及其解释 解释程序interpret及其执行
1.目标计算机的组织结构和指令格式
目标计算机的组织结构
程序存储器code 数据存储器s 程序地址寄存器p 地址寄存器t 指令寄存器i 基本地址寄存器b
目标计算机的指令结构
LIT指令,把一个常数放入栈顶 LOD指令,把一个变量放入栈顶 STO指令,从栈顶把数放入一个变量单元里 CAL指令,调用一个过程 INT指令,预留数据存储位置 JMP指令,无条件转移 JPC指令,有条件转移 OPR 一组算术和关系运算指令
数据动态存储分析
在调用一个过程时,先在栈顶为过程及其变量分配 一些位置,叫做过程段 每个过程在过程段里存放一些自己的数据,至少有 被调用时的程序地址RA(返回地址)以及调用过程的 段地址DL(动态链接) 还需要有第二个链,能正确反映变量存取的路线, 称为SL(静态链接) 地址于是由编译程序表示为数据对l和a的形式。第 一个数l表示调用者(调用程序段)与被调用变量之间 的静态级差,它等于找到变量所在段须通过的SL链 的个数。第二个数a是位移,即变量在所在段的相 对地址
PL/0计算机的指令格式 F INT LIT LOD STO CAL JMP JPC OPR L ——— ——— 层次差 层次差 层次差 ——— ——— ——— A 常 量 常 量 数据地址 数据地址 程序地址 程序地址 程序地址 运算类别
层次差为变量名或过程名引用和声明之 间的静态层次差别,程序地址为目标数 组code的下标,数据地址为变量在局部 存贮中的相对地址 PL/0的编译程序为每一条PL/0源程序的 可执行语句生成后缀式目标代码。这种 代码生成方式对于表达式、赋值语句、 过程调用等的翻译较简单
4. 所有运算操作都从栈顶找到它的操作数,并 以计算结果代之
3.目标计算机指令系统及其解释
表10-1 P137
4.解释程序interpret及其执行
Program6.pas 解释程序interpret
程序静态级别和动态存储分配
编译程序在编译过程中能为程序的每一个变 量名、过程名以及程序段分配一个静态嵌套 深度,或者说静态级别 调用语句被翻译成cal l,a,其中a是被调用 代码程序在程序存储器的开始地址,l是调 用程序段的级与被调用过程的级之差 函数base(l)
数据动态存储采用的技术措施
栈式动态存储分配
在允许递归调用的语言中,每次递归调用都要 重新分配局部变量。对于这种语言应该采用 “栈式动态存储分配”,其分配策略是将整个 程序的数据空间设计为一个栈,每当调用一个 过程时就将其活动记录压入栈,在栈顶形成该 过程工作时的数据区,而当过程结束时再将其 活动记录弹出栈。在这种分配方式下,过程的 调用关系是先进后出的栈模型,每个过程都可 能有若干个不同的活动记录,每个活动记录代 表了一次不同的调用。当前的AR首地址由栈 指针SP指出。AR中通常应包含如下内容:
2.数据存储器的动态存储器管理
每一个PL/0过程可能含有局部变量。过程可以 递归调用,每次递归调用,被调用过程又要求 有自己的局部变量,因此不可能在编译时就为 局部变量确定好固定的存储位置。只能在每次 执行过程调用时才为过程的一组局部变量确定 相应的存储位置。过程一结束,存储位置又被 释放。 后进先出—last in first out 按照栈的原理来管理数据存储器
相关文档
最新文档