编译原理第10章目标程序运行时的组织
编译原理模拟试卷和答案

北京语言大学网络教育学院《编译原理》模拟试卷一注意:1.试卷保密,考生不得将试卷带出考场或撕页,否则成绩作废。
请监考老师负责监督。
2.请各位考生注意考试纪律,考试作弊全部成绩以零分计算。
3.本试卷满分100分,答题时间为90分钟。
4.本试卷分为试题卷和答题卷,所有答案必须答在答题卷上,答在试题卷上不给分。
一、【单项选择题】(本大题共10小题,每小题2分,共20分)在每小题列出的四个选项中只有一个选项是符合题目要求的,请将正确选项前的字母填在答题卷相应题号处。
1、一个编译程序中,包含词法分析、()、中间代码生成、代码优化、目标代码生成等五个部分。
[A] 语法分析[B] 文法分析[C] 语言分析[D] 解释分析2、词法分析器用于识别()。
[A] 字符串[B] 语句[C] 单词[D] 标识符3、语法分析器则可以发现源程序中的()。
[A] 语义错误[B] 语法和语义错误[C] 错误并校正[D] 语法错误4、下面关于解释程序的描述正确的是()。
(1) 解释程序的特点是处理程序时不产生目标代码。
(2) 解释程序适用于COBOL 和FORTRAN 语言。
(3) 解释程序是为打开编译程序技术的僵局而开发的。
[A] (1)(2)[B] (1)[C] (1)(2)(3)[D] (2)(3)5、解释程序处理语言时, 大多数采用的是()方法。
[A] 源程序命令被逐个直接解释执行[B] 先将源程序转化为中间代码, 再解释执行[C] 先将源程序解释转化为目标程序, 再执行[D] 以上方法都可以6、编译过程中, 语法分析器的任务就是()。
(1) 分析单词是怎样构成的(2) 分析单词串是如何构成语句和说明的(3) 分析语句和说明是如何构成程序的(4) 分析程序的结构[A] (2)(3)[B] (2)(3)(4)[C] (1)(2)(3)[D] (1)(2)(3)(4)7、编译程序是一种()。
[A] 汇编程序[B] 翻译程序[C] 解释程序[D] 目标程序8、文法G 所描述的语言是()的集合。
编译原理第10章运行时的存储组织与分配

10.2 静态存储分配
在编译阶段由编译程序实现对存储空间的管理,为 源程序中的变量分配存储单元。
条件
➢在编译时能够确定变量在运行时的数据空间大小 ➢运行时不改变
编译原理第10章运行时的存储组织与 分配
FORTRAN程序的静态分配
编译原理第10章运行时的存储组织与 分配
动态存储分配 在目标程序运行阶段由目标程序实现对存
再见,see you again
2020/12/13
编译原理第10章运行时的存储组织与 分配
编译原理第10章运行时的存储组织与 分配
练习 下面程序的运行结果是什么?如果把第6行的(i+1)*fact( )改 成fact( )*(i+1)的话,则程序的运行结果是有什么变化?试分析 为什么会有这两种不同的结果。 int fact( ) { static int i=5; if(i==0) return 1; else { i--; return((i+1)*fact( )); //第6行 }} main( ) { printf("factor of 5!=%d\n",fact());}
为运行阶段实现存储奠定基础
编译原理第10章运行时的存储组织与 分配
教学内容
• 10.1 存储组织概述 • 10.2 静态存储分配 • 10.3 栈式动态存储分配 • 10.4 堆式动态存储分配
编译原理第10章运行时的存储组织与 分配
10.1 存储组织概述
运行时存储空间的划分
代码空间
目标代码空间 静态数据空间
储空间的组织与管理,为源程序中的变量分 配存储单元 特点 • 在目标程序运行时进行分配 • 编译时为运行阶段设计好存储组织形式,即为每个 数据项安排好它在数据区中的相对位置
编译原理目标程序运行时的存储组织

编译原理目标程序运行时的存储组织引言在编译原理中,目标程序是指通过编译器将高级源代码转换为机器可执行的程序。
在目标程序运行时,需要一定的存储空间来存储程序的指令和数据。
本文将介绍编译原理中目标程序运行时的存储组织的基本概念和原理。
程序的内存模型目标程序在运行时的存储组织是通过内存模型来描述的。
内存模型定义了目标程序在内存中的存储方式和访问机制。
常见的内存模型有栈式模型、堆式模型和段式模型等。
栈式模型栈式模型将程序的内存划分为栈和堆两部分。
栈用于存储程序的局部变量、函数调用和返回地址等信息,而堆用于动态存储分配,如动态创建的对象以及通过malloc等函数分配的内存。
栈式模型的存储空间是连续分配的,栈的大小是固定的,而堆的大小可以根据需要进行动态调整。
堆式模型堆式模型将程序的内存划分为堆和栈两部分。
堆是动态分配的内存空间,用于存储程序运行时动态创建的对象和变量。
栈则用于存储函数调用的临时变量、函数参数和返回地址等信息。
堆式模型的存储空间可以动态调整,但需要手动管理内存的分配和释放,以避免内存泄漏和内存碎片的产生。
段式模型段式模型将程序的内存划分为若干个段,每个段用于存储特定类型的数据。
常见的段包括代码段、数据段、堆段和栈段等。
代码段用于存储程序的指令,数据段用于存储常量、全局变量和静态变量等数据,堆段和栈段与堆式模型和栈式模型类似。
段式模型可以更灵活地管理不同类型的数据,提高了内存的利用率。
存储器分配在目标程序运行时,编译器负责将程序的指令和数据分配到合适的存储器中。
存储器分配的主要目标是提高程序的执行效率和优化存储空间的利用率。
静态存储器分配静态存储器分配是在编译时确定存储器的分配方式。
静态存储器分配将程序的指令和数据分配到固定的内存地址上,程序运行时不会改变存储器分配。
静态存储器分配适用于程序结构稳定、数据量较小的场景,但难以适应动态创建和销毁对象的情况。
栈式存储器分配栈式存储器分配将程序的局部变量、函数调用和返回地址等信息存储在栈中。
编译原理目标程序运行时的组织

编译原理目标程序运行时的组织简介在编译原理中,目标程序是由程序设计语言的源代码通过编译器转换而成的可执行文件。
目标程序的运行是通过操作系统的支持以及相关的硬件来完成的。
在目标程序运行时,需要对内存的组织进行有效的管理,以保证程序能够正确地执行。
程序的存储结构目标程序在运行时的组织首先涉及到程序的存储结构。
一般来说,目标程序在存储器中被组织为多个段或者区块。
这些段或者区块包括代码段、数据段、堆栈段等。
每个段都有不同的权限,比如代码段通常是只读的,数据段和堆栈段都是读写的。
代码段代码段是存储目标程序的机器指令的区域。
代码段在目标程序运行时是只读的,因为在运行时不能更改源代码。
代码段通常是按照顺序组织的,每条指令都有一个地址。
当程序执行时,计算机会从代码段中读取指令并逐条执行。
数据段数据段是存储目标程序的静态数据、全局变量以及常量的区域。
数据段在目标程序运行时是读写的,因为数据段中的数据可能会发生变化。
数据段通常是按照数据的类型和大小进行组织的,每个数据都有一个地址。
堆栈段堆栈段是存储目标程序的局部变量、函数的参数和返回值等临时数据的区域。
堆栈段在目标程序运行时是读写的,因为堆栈中的数据会被不断压入和弹出。
堆栈段通过栈的数据结构进行组织,数据的压入和弹出都是通过栈指针来实现的。
内存管理目标程序在运行时需要使用内存进行存储和计算。
内存管理是指程序如何分配、使用和释放内存资源的过程。
在目标程序运行时,操作系统负责管理内存的分配和释放,并对内存进行保护,以防止程序的错误操作导致系统崩溃或安全风险。
内存管理的主要任务包括内存分配、内存回收和内存保护。
内存分配是指为程序分配所需的内存空间。
常见的内存分配方式有静态分配和动态分配。
静态分配是在程序加载到内存时预先分配一定的内存空间,而动态分配是根据程序的需要,在运行时临时分配内存空间。
内存回收是指当某个内存空间不再被程序使用时,将其释放回系统。
常见的内存回收方式有手动回收和自动回收。
程序设计语言编译原理第三版第10章

§10.2 局部优化
举例:考察下面的三地址代码程序
(1)Read X
(2)Read Y
B1
(3)R:=X mod Y (4)if R=0 goto (8) B2
(5)X:=Y
(6)Y:=R
B3
(7)goto(3)
(8)write Y B4
(9)halt
B1
B2
B3
B4
§10.2 局部优化
3.流图及其生成
标识符(包括常数)-结点 NODE(A)-描述上述对应关系的函数,其值或者是一个结点的编号,
或者无定义
(2)中间代码的三种形式:A:=B A:=op B A:=B op C 或 A:=B[C]
(3)构造算法: ①开始,DAG为空 ②对基本块中每一条中间代码式,依次执行以下步骤:
§10.2 局部优化
步骤: 1.如果NODE(B)无定义,则构造一标记为B的叶结点并定义
NODE(B)为这个结点 如果当前代码是0型,则记NODE(B)的值为n,转4 如果当前代码是1型,则转2(1) 如果当前代码是2型,则(ⅰ)如果NODE(C)无定义,则构造一标 记
为C的叶结点并定义NODE(C)为这个结点;(ⅱ)转2(2)
(1)T0:=3.14 (2)T1:=2*T0 (3)T2:=R+r (4)A:=T1*T2 (5)B:=A (6)T3:=2*T0 (7)T4:=R+r (8)T5:=T3*T4 (9)T6:=R-r (10)B:=T5*T6
(4)代数变换
§10.2 局部优化
二、基本块的DAG表示及其应用
1.基本块的DAG:
一种结点带有下述标记或附加信息的DAG
(1)图的叶结点以一标识符(变量名)或常数作为标记,表示该 结点代表该变量或常数的值。
第10章目标程序运行时的组织

2、堆式动态存储分配 如果一个程序语言提供用户自由地申请数据空间和
退还数据空间的机制,通常使用一种称为堆式的动态存 储分配方案。
术语: 过程活动记录: AR
为说明方便,假定程序是由过程组成,过程运行时称作过 程的激活。
一个过程的一次执行所需要的信息使用一个连续的存储区来 管理,这个区 (块)叫做一个活动记录
1、栈式动态存储分配 这种分配策略是将整个程序的数据空间设计为一个栈。 例:在具有递归结构的语言程序中,每当调用一个过程时, 它所需的数据空间就分配在栈顶,每当过程工作结束时就释 放这部分空间。
过程所需的数据空间包括两部分: 一部分是生存期在本过程这次活动中的数据对象,如局部变 量、参数单元、临时变量等等; 另一部分则是用以管理过程活动的记录信息(连接数据)。即 当一次过程调用出现时,调用该过程的那个过程的活动即被 中断,当前机器的状态信息,诸如返回地址、寄存器的值等 等,也都必须保留在栈中。当控制从调用返回时,便根据栈 中记录的信息恢复机器状态,使该过程的活动继续进n 中的数据说明
} Void R( ) { R 中的数据说明 } Void Q
{Q中的数据说明
这种情况可以直接采用栈式 存储分配策略。
在运行时,每个过程开始时 就把它的活动记录压入栈, 直到该活动结束,它的活动 记录弹出栈。
}
Main
QR
嵌套过程语言的栈式分配方案
前面我们讲的过程不允许语言嵌套定义,现在 我们取消这个限制,即允许过程嵌套定义,一 个过程可以引用包围它的任一外层过程所定义 的标识(如变量,数组或过程等)。如:我们 所熟悉的PASCAL语言程序结构就是这样一种 语言。
编译原理程序运行时的存储组织

编译原理程序运行时的存储组织一、程序的应该存储区域1.代码区:也称为文本区或者只读区,用于存放程序的目标代码。
代码区是只读的,不允许修改。
在程序运行过程中,代码区的内容不会发生变化。
2.全局数据区:用于存放全局变量和静态数据。
全局数据区在程序开始运行时就被分配好空间,在程序的整个运行过程中都存在,直到程序结束。
3.堆区:用于存放动态分配的内存空间,也称为动态内存分配区。
堆区的内存空间是在程序运行时动态分配和释放的,可以根据程序的需要进行扩大或者缩小。
4.栈区:用于存放函数的局部变量和函数调用信息。
栈区的空间是在程序运行时自动分配和释放的,由编译器负责管理。
在函数调用时,会为函数分配一块栈区空间,函数返回后,该空间被自动释放。
二、内存管理方式1.静态内存管理:静态内存管理是指在程序编译阶段,由编译器根据程序的静态内存需求,在编译过程中为程序分配好固定大小的内存空间,静态内存管理的特点是内存空间的分配和释放都是在编译时确定的,程序运行时不需要进行内存管理。
2.动态内存管理:动态内存管理是指在程序运行时根据需要动态地分配和释放内存空间,动态内存管理的特点是内存空间的分配和释放是在程序运行过程中动态确定的。
动态内存管理可以通过堆区进行。
三、内存分配和释放编译原理程序在运行时的存储组织中,对于静态内存区域的分配和释放是由编译器在编译时确定的,程序在运行时无法进行修改。
对于动态内存区域的分配和释放,可以通过堆区进行,可以使用以下几个函数进行动态内存的分配和释放:1. 分配内存:程序可以使用malloc函数、calloc函数或者realloc函数来分配内存空间。
malloc函数用于分配指定字节数的内存空间,calloc函数用于分配指定数量和大小的内存空间,realloc函数用于调整已经分配的内存空间的大小。
2. 释放内存:程序在使用完动态分配的内存空间后,需要使用free函数来释放内存空间。
free函数会将之前分配的内存空间标记为可用状态,可以供其他程序使用。
编译原理课件第十章目标程序运行时的存储组织

PART 01
目标程序运行时的存储器 组织
存储器分类
主存储器
用于存储程序运行时所需的数 据和指令,具有较快的访问速
度。
辅助存储器
如硬盘、光盘等,用于存储大 量数据和程序,访问速度较慢 。
高速缓存存储器
位于CPU和主存储器之间,用 于缓存常用数据和指令,提高 访问速度。
寄存器
位于CPU内部,用于临时存储 数据和指令,访问速度最快。
01
数据段用于存储程序中定义的全 局变量、静态变量等数据。
03
数据段的大小在编译时确定,并 在程序运行时被加载到内存中。
02
数据段分为初始化数据段和未初 始化数据段,分别用于存储初始
化和未初始化的数据。
201 4
04
数据段的保护机制可以防止其他 程序或用户随意修改其中的数据。Fra bibliotek堆栈段
01
堆栈段用于存储函数调用的参数、局部变量以及函数调用的返回地址 等信息。
02
堆栈段的特点是后进先出(LIFO),即最后进入堆栈的元素最先被弹 出。
03
当函数被调用时,其参数和局部变量等信息被压入堆栈中;当函数返 回时,这些信息被从堆栈中弹出。
04
堆栈段的增长和缩小是通过堆栈指针来实现的,堆栈指针指向堆栈的 顶部元素。
PART 02
程序的内存布局
静态内存分配
全局变量存储
代码段
01
代码段用于存储程序的指令代码 ,是程序运行时必须加载到内存 中的部分。
02
代码段通常被划分为多个区段, 每个区段对应程序中的一个模块
或函数。
在程序运行时,代码段中的指令 被加载到CPU的指令寄存器中, 并由CPU执行。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
编译原理第10章目标程序运行时的组 织
编译原理第10章目标程序运行时的组 织
用Display表的方案
(1)主程序--->(2)P--->(3)Q--->(4)R
top
P的
display sp 活动记录
d[1]
主程序的
d[0]
活动记录
编译原理第10章目标程序运行时的组 织
概述
代码生成前如何安排目标机资源 运行时组织的几个问题 • 数据表示-如何在目标机中表示每个源语言类型的值 • 表达式求值-如何组织表达式的计算 • 存储分配-如何组织不同作用域变量的存储 • 过程实现-如何以例程实现过程,函数,参数传递
编译原理第10章目标程序运行时的组 织
• 关键技术:解决对非局部量的引用(存 取)。
• 设法跟踪每个外层过程的最新活动记录 AR的位置。
• 跟踪办法: 1. 用静态链(如PL/0的SL)。 2. 用DISPLAY表。
编译原理第10章目标程序运行时的组 织
const a=10; var b,c; procedure p; begin c:=b+a; end; begin read(b); while b#0 do begin call p; write(2*c); read(b); end end.
数组内情向量:编译将数组的有关信息记录在一些单元中,称为数 组的“内情向量”。
A[l 1:u 1,l 2:u 2, … ,ln : un]
l1
u1
l2
u2
: :
type
a(首地址)
n
C
编译原理第10章目标程序运行时的组
织
目标程序运行时的存储组织
存储分配策略:
静态存储分配 动态存储分配——栈式
堆式
简单的栈式分配方案 嵌套过程的栈式分配方案 分程序结构的存储分配方案
. . . d DISPLAY . 简单变量 . 数组内情向量 . 临时变量
• 当过程的层次为n, 它的 display为n+1个 值。 • 一个过程被调用时, 从调用过程的 DISPLAY表中自下向 上抄录n个SP值,再加 上本层的SP值。 •全局DISPLAY地址
编译原理第10章目标程序运行时的组 织
在语义学中,使用术语environment函数表示
env: N→S
(N到S的映射) 编译原理第10章目标程序运行时的组
织
编译原理第10章目标程序运行时的组 织
决定运行管理复杂程度的因素——源语言本身 1. 允许的数据类型的多少 2.语言中允许的数据项是 静态确定
动态确定 3.程序结构 决定名字的作用域的规则和结构 A.段结构 B.过程定义不嵌套,只允许过程递归调用 C.分程序结构
编译原理第10章目标程序运行时的组 织
为了解决上述问题,可采取两种措施。第 一,对每个过程或分程序都建立有自己 的栈顶指示器TOP,代替原来仅有过程 的栈顶指示器, 每个TOP的值保存在各自 活动记录中。这样,上述的第二个问题 便可解决。第二,不把分程序看作“无 参过程”,每个分程序享用包围它的那 个最近过程的DISPLAY。每个分程序都 隶属于某个确定的过程,分程序的层次 是相对于它所属的那个过程进行编号的。
但方法(成员函数)不存在该对象里 指令:
编译原理第10章目标程序运行时的组 织
编译原理第10章目标程序运行时的组 织
编译原理第10章目标程序运行时的组 织
编译原理第10章目标程序运行时的组 织
可变 (动态)数组: 若一个数组所需的存储空间的大小在
编译时就已知道,则称它为确定数组,否则称为可变(动态)数组。
分程序嵌套 过程定义嵌套
4存储类别的多少
Global Static Local dynamic
编译原理第10章目标程序运行时的组 织
术语
• 静态:如果一个名字的性质通过说明语句 或隐或显规则而定义,则称这种性质是 “静态”确定的。
• 动态:如果名字的性质只有在程序运行时 才能知道,则称这种性质为“动态”确定 的。
局部变量 中间结果
编译原理第10章目标程序运行时的组 织
目标代码的解释执行 运行栈
S
• M调用过程P t.
.
RA DL
b SL t
b
P
M
编译原理第10章目标程序运行时的组 织
解决对非局部量的引用(存取) 用Display表
Display表---嵌套层次显示表 当前激活过程的层次为K,它的Display表含有K+1个单元,依次存
分程序结构
Procedure A(m,n); integer m,n;
B1:begin real z; array B[m:n];
B2:begin real d, e;
L3:
2
end;
B4:begin array C[1:m];
1
B5:begin real e;
L6:
54
end;
end;
L8:end;
编译原理第10章目标程序运行时的组
织
目标代码解释执行时数据栈的布 局(运行栈的存储分配)
每个过程的AR有 3个联系单元:
–SL: 静态链,指向定义该过程的直接外过程 (或主程序)运行时最新数据段的基地址。
–DL: 动态链,指向调用该过程前正在运行过 程的数据段基地址。
–RA: 返回地址,记录调用该过程时目标程序 的断点,即调用过程指令的下一条指令的地址。
编译原理第10章目标程序运行时的组 织
每个过程被当作是0层分程序。而过程体 分程序(假定是一个分程序)当作是它 所管辖的第1层分程:序。
这样,每个过程的活动记录所含的内容有:
1.过程的TOP值,它指向过程活动记录的 栈顶位置。
2.连接数据,共四项:
(1)老SP值;
(18) opr 0 4 次栈顶与栈顶相乘(2*c)
(19) opr 0 14 栈顶值输出至屏幕 (20) opr 0 15 换行 (21) opr 0 16 从命令行读取值到栈顶 (22) sto 0 3 栈顶值送变量b中 (23) jmp 0 11 无条件转到循环入口(11) (24) opr 0 0 结束退栈
编译原理第10章目标程序运行时的组 织
分程序结构的存储 分配方案
处理分程序结构存储分配方案的一种 简单办法是,把分程序看成 “无名无参过 程”,它在哪里定义就在哪里被调用。因 此,可以把处理过程的存储办法应用到处 理分程序中。但这种做法是极为低效的。
一则,每逢进入 一个分程序,就照样建立 连接数据和DISPLAY表,这是不必要的。 二则 ,当从内层分程序向外层转移时,可 能同时要结束若干个分程序。
编译原理第10章目标程序运行时的组 织
简单的栈式分配方案
• 程序结构特点:过程定义不嵌套,过程可 递归调用,含可变数组;
• 例: main
• 全局变量的说明
• proc R
• ……
• end R;
• proc Q
• ……
• end Q; • 主程序执行语句
• end main
编译原理第10章目标程序运行时的组 织
编译原理第时的组 织
嵌套过程语言的栈式 分配方案
l 主要特点:
• (语言)一个过程可以引用包围它的任 一外层过程所定义的标识符(如变量, 数组或过程等)。
• (实现)一个过程可以引用它的任一外 层过程的最新活动记录中的某些数据。
编译原理第10章目标程序运行时的组 织
编译原理第10章目标程序运行时的组 织
按照过程处理办法,意味着必须一层 一层地通过“返回” 来恢复所要到达的 那个分程序的数据区,但不能直接到达。
例如:如果有一个从第5层分程序转出到达 第1层分程序的标号L,虽然在第5层分程 序工作时知道L所属的层数,我们极易从 DISPLAY中获得第1层分程序的活动记 录基址(SP),但是怎么知道第1层分程 序进入时的TOP呢?唯一的办法是从 5,4,3和2各层顺序退出。但这种办法是很 浪费时间的。
编译原理第10章目标程 序运行时的组织
2020/12/13
编译原理第10章目标程序运行时的组 织
概述-代码生成解决语义gap
高级语言支持的概念 Type value expression Variable procedure Function parameters
目标机支持的概念 bits bytes words Registers Stack address Routine(sub routine)
top display
主程序的
d[0]
sp 活动记录
(2)
(1) 编译原理第10章目标程序运行时的组 织
用Display表的方案
• 主程序--->P--->Q--->R
d[2]displatyopsp
Q的 活动记录
d[1]
P的
d[0]
活动记录
主程序的
活动记录
(3)
top R 的 display sp 活动记录
( 0) jmp 0 8 转向主程序入口 ( 1) jmp 0 2 转向过程p入口 ( 2) int 0 3 过程p入口,为过程p开辟空间 ( 3) lod 1 3 取变量b的值到栈顶 ( 4) lit 0 10 取常数10到栈顶 ( 5) opr 0 2 次栈顶与栈顶相加 ( 6) sto 1 4 栈顶值送变量c中 ( 7) opr 0 0 退栈并返回调用点(16) ( 8) int 0 5 主程序入口开辟5个栈空间 ( 9) opr 0 16 从命令行读入值置于栈顶 (10) sto 0 3 将栈顶值存入变量b中 (11) lod 0 3 将变量b的值取至栈顶 (12) lit 0 0 将常数值0进栈 (13) opr 0 9 次栈顶与栈顶是否不等 (14) jpc 0 24 等时转(24)(条件不满足转) (15) cal 0 2 调用过程p (16) lit 0 2 常数值2进栈 (17) lod 0 4 将变量c的值取至栈顶