编译原理第19讲(第十章)

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

目标代码区 静态数据区
Stack
heap
概述
代码生成前如何安排目标机资源 运行时组织的几个问题 数据表示-如何在目标机中表示每个源语言类型的值 表达式求值-如何组织表达式的计算 存储分配-如何组织不同作用域变量的存储 过程实现-如何以例程实现过程,函数,参数传递
决定运行管理复杂程度的因素—源语言本身
静态存储分配举例
FORTRAN语言由主程序段和若干子程序段组成。各程序 段中定义的名字一般是彼此独立的,也即各段的数据对象 名的作用域在各段中,同一个名字在不同的程序段表示不 同的存储单元,不会在不同段间互相引用、赋值。另外它 的每个数据名所需的存储空间大小都是常量(即不许含可 变体积的数据,如可变数组)。这样,整个程序所需数据 空间的总量在编译时完全确定,从而每个数据名的地址就 可静态进行分配。
1. 允许的数据类型的多少 2.语言中允许的数据项是
静态确定 动态确定 3.程序结构 (决定名字的作用域的规则和结构) A.段结构(Fortran) B. 过程定义不嵌套,只允许过程递归调用 C.分程序结构 分程序嵌套 过程定义嵌套 静态:如果一个名字的性质
4.存储类别的多少
Global Static Local dynamic
通过说明语句或隐或显规则 而定义,则称这种性质是 “静态”确定的。 动态:如果名字的性质只有 在程序运行时才能知道,则 称这种性质为“动态”确定 的。
10.2 数据表示各种数据对象的存储分配
简单变量: char: 1 byte integers: 2 or 4 bytes floats: 4 to 16 bytes booleans: 1 bit (but usually 1 byte)
存储分配
动态存储分配
如果一个程序设计语言允许递归过程、可变 数组或允许用户自由申请和释放空间,那么,就 需要采用动态存储管理技术。因为对于这种程序 在编译时无法知道它在运行时需要多大的存储空 间,它所需要的数据空间的大小需待程序运行时 动态地确定。
动态存储分配举例
•若一个数组所需的存储空间的大小在编译时就已知 道,则称它为确定数组,否则称为可变数组。 procedure A(m,n:integer); begin real z; array B[m:n]; begin ··· end; end; B[m:n] 为可变数组,B的上下界是过程A的实参, A被调用时才能确定。 •使用malloc
例子1
(1) program sort(input, output); //sort的过程头 (2) var a: array [0..10] of integer; (3) x: integer; (4) procedure readarray; //sort内嵌套定义的readarray的过程头 (5) var i: integer; (6) begin…a…end{readarray}; //readarray的过程体 (7) procedure exchange(i,j: integer); //sort内嵌套定义的exchange的过程头 (8) begin (9) x∶=a[i]; a[i]∶=a[j]; a[j]∶=x; //exchange的过程体 (10) end{exchange}; (11) procedure quicksort(m,n: integer); //sort内嵌套定义的quicksort的过程头 (12) var k,v: integer; (13) function partition(y,z:integer):integer; //quicksort内嵌套定义的partition的函数头 (14) var i.j:integer; (15) begin //partition的函数体 (16) …a… (17) …v… (18) exchange(i,j); (19) end{partition}; (20) begin…end{quicksort}; //quicksort的过程体 (21) begin…end{sort} //sort的例程体
演示函数调用退出时sp和top的变化
Main---->Q----> R
TOP-----> R的数组区
Main--->Q---->Q
Q的数组区 Q的活动记录 Q的数组区 Q的活动记录 主程序全局 数据区
SP------>
R的活动记录 Q的数组区 Q的活动记录 主程序全局 数据区
TOP----> 临时工作单元 局部简单变量 局部数组的内情向量 保存运 行过程前的状态 (返回地址,寄存器值……) 实参(形式单元)和参数个数 SP-----> 控制链(老 SP)
10.3.2嵌套过程语言的栈式分配方案
主要特点: (语言)一个过程可以引用包围它的任一外层过程所 定义的标识符(如变量,数组或过程等)。 (实现)一个过程执行时可以引用它的任一外层过程 的最新活动记录中的某些数据。 我们所熟悉的PASCAL语言程序结构的特点是允许 过程嵌套定义,一个过程可以引用包围它的任一外层过 程所定义的标识(如变量,数组或过程等)。它的存储 分配也看成是采用栈式动态分配策略,只是它的过程活 动记录中应增设一些内容,用以解决对非局部变量的引 用问题。 (回忆简单栈式存储分配:局部量+全局量)
目标机支持的概念 bits bytes words Registers Stack address Routine(sub routine)
概述
在代码生成前,编译程序必须进行目标程序运行环 境的配置和数据空间的分配。 一般来讲,假如从操作系统中得到一块存储区以使 目标程序在其上运行,该存储区需容纳生成的目标代码 和目标代码运行时的数据空间。 数据空间应包括:用户定义的各种类型的数据对象(变 量和常数)所需的存储空间,作为保留中间结果和传递 参数的临时工作单元,调用过程时所需的连接单元,以 及组织输入/输出所需的缓冲区。 目标代码所占用空间的大小在编译时能确定。有些数据 对象所占用的空间也能在编译时确定,其地址可以编译 进目标代码中。而有些数据对象具有可变体积和待分配 性质,无法在编译时确定存储空间的位置。
术语--过程活动记录AR
为说明方便,假定源程序是由过程组成,运行时称 作过程的激活。 一个过程的一次执行所需要的信息,使用一个连续 的存储区来管理这个区(块),叫做一个活动记录AR或 frame帧
一般这个区AR要记录: (运行栈的存储分配) l 临时值(如计算表达式时的中间工作单元。) l 局部变量(数据) l 保存运行过程前的状态 (返回地址,寄存器值……) l 形参 (形式单元) l 返回值(RA 对函数,有时可使用寄存器存放返回值) l 存取链(SL 可选,对于非局部量的引用。) l 控制链(DL 可选,指向调用者的活动记录,释放栈。)
目标代码的解释执行(运行栈S)
M调用过程P
t
. . P
RA DL SL
b t
b
M
10.3.1简单的栈式分配方案
程序结构特点:过程定义不嵌套,过程可递归调用,含
可变数组; 例: main 全局变量的说明 • proc R • …… • end R; • proc Q • …… • end Q; • 主程序执行语句 end main
readarray
{ var i: integer; …对a的访问…
}
exchange
{ } …对a的访问…
quicksort
{ var k,v: integer;
partition
{ } } end var i.j:integer; …对a的访问…
例子1(问题)
过程readarray,exchange和partition中引用的a均不是它们的 局部变量,而是过程sort的局部变量。假如过程sort激活(调用)了 过程quicksort,这时存储栈中的情形示意如图,其中在quicksort过 程活动记录中有一(或一些)存储单元(用斜线描绘)用以记录过程 quicksort可以引用sort中定义的变量a和x。也就是说,为了解决对 非局部量的存取问题,必须设法跟踪每个外层过程的最新活动记录 的位置。
概述
运行时的存储区常常划分成:目标区、静态数据区、栈区和堆 区,如下图就是一种典型划分,代码(code)区用以存放目标代码, 这是固定长度的,即编译时能确定的;静态数据区(static data)用以 存放编译时能确定所占用空间的数据;堆栈区(stack and heap)用于 可变数据以及管理过程活动的控制信息。
数据对象的属性 name 名字/名称 type 类型 location 内存地址 value 值 component 成分
指针:unsigned integers 一维数组:一块连续的存储区 多维数组:一块连续的存储区,按行存放 结构(记录):把所有域(field)存放在一块连续的存储区 对象:类的实例变量象结构的域一样存放在一块连续的存 储区,但方法(成员函数)不存在该对象里 指令:
第十章 目标程序运行时的组织 10.1 10.2 10.3 10.4 10.5 概述 数据表示ቤተ መጻሕፍቲ ባይዱ目标程序运行时的栈式存储组织 参数传递 堆式存储概述
10.1概述-代码生成解决语义gap
高级语言支持的概念 Type value expression Variable procedure Function parameters
静态存储分配举例
(1) PROGRAM CNSUME (2) CHARACTER * 50 BUF //程序体所拥有的静态量BUF (3) INTEGER NEXT //程序体所拥有的静态量NEXT (4) CHARACTER C, PRDUCE //程序体所拥有的静态量C (5) DATA NEXT /1/, BUF / ‘ ’ / (6) 6 C=PRDUCE() (7) BUF(NEXT:NEXT)=C (8) NEXT=NEXT+1 (9) IF(C .EN. ‘ ’ )GOTO 6 (10) WRITE ( * ,‘ (A)’ )BUF (11) END (12) CHARACTER FUNCTION PRDUCE() (13) CHARACTER * 80 BUFFER (14) INTEGER NEXT (15) SAVE BUFFER, NEXT //PRDUCE函数体所拥有的静态量BUFFER, NEXT (16) DATA NEXT /81/ (17) IF (NEXT .GT.80)THEN (18) READ ( * ,‘ (A)’ )BUFFER (19) NEXT=1 (20) END IF (21) PRDUCE=BUFFER(NEXT:NEXT) 在Fortran 90 之前的Fortran 版本 (22) NEXT=NEXT+1 都没有递归.有递归则不能进行静态 (23) END
10.3目标程序运行时的存储组织
存储分配策略: 静态存储分配 动态存储分配——栈式 和 堆式 注:可以混合使用

简单的栈式分配方案 嵌套过程的栈式分配方案 分程序结构的存储分配方案 堆式存储
静态存储分配
这种存储分配非常简单,如果在编译时能确 定目标程序运行中所需的全部数据空间的大小, 编译时安排好目标程序运行时的全部数据空间, 确定每个数据对象的存储位置,称这种分配策略 为静态存储分配。
例子1(简略图)
//sort的例程体的简略视图 begin var a: array [0..10] of integer;x: integer; ……… 只要一个函数在调用点前出 现过,则可以对该函数进行 调用。 sort可以调用r,e,q(在哪里?) quicksort中可以调用partition (在哪里? ) partition中可以调r,e,q 但是在s,r,e中都不能调用p, 因为它是q私有的。 因此一个函数被激活的时候, 它的外层都处于激活状态, 也就是说在栈中有活动记录。 因此不会出现p被调用时, 找不到quicksort的活动记录。 (p只可能在q中被调用)
相关文档
最新文档