编译原理程序运行时的存储组织
合集下载
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
如果编译程序是在多程序任务的环境中;那么 目标地址可采用相对于程序数据区的基地址的相 对地址
若使用相对地址方式;那么程序的每一次执行; 程序及其数据区可以处在不同的存储区内
8 3 栈式动态存储分配
动态存储分配方式:有些语言允许有长度可变的串 动态数组;并允许过程递归调用;那么在编译时就无法 确定数据空间的具体大小;故其存储分配必须留到目 标程序运行时动态地进行
说明 第3次调fact函数n=2;返回2给全局 变量区的fact单元
第2次调fact函数n=3;返回6给全局 变量区的fact单元
第1次调fact函数n=4 返回24给全 局变量区的fact单元
主函数运行;m=4;调fact函数 ret0是运行完main后返回的地址; 可以是OS或留空
fact用于保存fact函数的返回值;开 始时无值;最后fact函数返回后为 24
8 2 静态存储分配
例 char array16; int i; j ; real a; b; 假设: 数据区开始位置的地址264 字符型占2个存贮单元 整型占4个存贮单元 实型占8个存贮单元
8 2 静态存储分配
目标地址可采用的地址形式: ➢绝对地址
如果编写的编译程序是用于单任务环境;那么; 通常采用绝对地址作为目标地址 ➢相对地址
第8章 程序运行时的存储组织及管理
影响存储分配策略的语言特征: ➢ 过程能否递归 ➢ 过程能否嵌套 ➢ 过程调用时参数如何传递 ➢ 哪些实体可以作为参数和返回值 ➢ 是否允许动态的为对象分配和撤销存储空间 ➢ 存储空间是否必须显式地释放 ➢ ……
8 1 程序运行时的存储组织
程序运行时;系统将为程序分配一块存储空间 这块 空间用来存储程序的目标代码以及目标代码运行时需 要或产生的各种数据 从用途上看;这块空间可分为以 下几个部分: ➢1目标程序区:用来存放目标代码 ➢2静态数据区:用来存放编译时就能确定存储空间 的数据 ➢3运行栈区:用来存放运行时才能确定存储空间的 数据 ➢4运行堆区:用来存放运行时用户动态申请存储空 间的数据
8 3 栈式动态存储分配
活动记录:当程序运行进入一个程序模块时;就 在运行栈的栈顶创建一个专用数据区;该数据区通 常称为活动记录
当程序模块执行结束时即到达模块的出口;其相 应的活动记录将从运行栈的栈顶删除 因此在该模 块中所定义的变量在该模块的外部是不存在的
8 3 栈式动态存储分配
一个典型的活动记录结构如右图所示
➢3不允许用户动态建立数据实体
8 2 静态存储分配
FORTRAN语言没有长度可变的串;也没有动态数组; 其子程序和函数也不允许递归调用;所以FORTRAN语
言采用静态存储分配方式
例P159 一个FORTRAN程序模块静态存储分配的典型
数据区格局如右图所示;其中:
1隐式参数主要用于和主调模块的通讯;它可以是主调过
8 3 栈式动态存储分配
栈式动态分配方式的实现:
➢1申请:在程序运行中;当程序模块被调用时;就从总 的数据区中请求一个空间作为其数据区即加入运行栈 中;并保留该空间直到执行完整个模块为止
➢2释放:当模块执行完毕;退出模块时;释放它所占有 的数据空间即从运行栈中弹出
➢3嵌套调用:从模块被调用到它运行结束之间;还可 以通过过程调用或程序块入口进入其他的模块;此时; 也按上面所介绍的方法将这些模块的数据区压入或弹 出运行栈 当嵌套的被调程序运行结束返回到主调程序 中的调用点时;运行栈中的格局和内容会恢复到调用之 前的情况
例P160设有如下C程序;其运行栈的变化情况如下图所示
real x; …………………块1
int m1int ind ……………块2
对于C语言;函数是程序块;
int x;
一对花括号内的程序即复合
x=m2ind+1;
语句也可以看成是一个程序
块
int m2int j ………………块3
int f10; ……………块4 bool test1;
d2
1) 如果j=i+1即进入一个程序块;则复 块4活动记录abp4 d1
制i层的display;然后增加一个指向i
j
层模块活动记录基地址的指针
abp2 return3
2) 如果j≤i即调用对当前模块来说是 属于全程声明的过程模块;则来自i层 模块活动记录中的display区前面j1 个入口将组成j层模块的display区
8 2 静态存储分配
静态存储分配方式:对于源程序中出现的各种数据 项;如常量 简单变量 常界数组 非变体记录等; 在编 译时就给它们分配固定的存储空间;而且在目标程序 运行时;总是使用这些在编译时就分配好的存储单元 作为它们的数据空间
采用静态存储分配的语言必须满足下列条件: ➢1不允许过程有递归调用 ➢2不允许有可变大小的数据项;如可变数组或可变字 符串
8 3 栈式动态存储分配
给定一个要访问的具有地址为BL;ON的变量;设该变量 在LEV 层的一个模块中 该变量的地址ADDR可按如下方 法计算P163:
if BL=LEV then ADDR=abp+BL1+nip+ON//局部变量 else if BL<LEV then //全局变量
ADDR=displayBL+BL1+nip+ON else write地址错;不合法的模块层次
8 3 栈式动态存储分配
栈式存储分配适合那些过程允许嵌套定义 递 归调用的语言;其过程的进入和退出具有后进 先出的特点 如果语言允许动态申请和释放存 储空间;那么;栈式存储分配就不适合了;这时; 可以采用堆式动态存储分配策略
8 4 堆式动态存储分配
堆式分配策略的基本思路:假设程序运行时有一个大 的连续的存储空间堆;当存储管理程序接收到运行程序的 存储空间请求时;就从堆中分配一块空间给运行程序 当 运行程序用完后再退还给堆即释放 管理程序回收其存储 空间以备后面使用 由于每块空间可以按任意顺序释放; 这样;程序经过一段运行后;堆将被划分成若干已用块和 空闲块
还有更好的处理返回值的方法
2 显式参数:显式参数区是形式参数的通讯区
形式参数的传递有传值 传地址 传名等方法
8 3 栈式动态存储分配
➢2 display区嵌套层次显示表 display区用于保存对当前正在执行的模块
来说是全局的程序变量区的信息;它由一系列地 址指针所组成;每一个指针指向一个程序块的活 动记录的开始位置;而这个程序块对于当前正在 执行的程序块来说是全局的
应是main;m2;m1;x
m1活动记录abp2 main活动记录abp1
abp0
test1 f abp3
d2 d1 j abp2 return3 d1 x;0 ind abp1 return2 d1 x ;2 abp0
d1 x 无前记录 OS
test1
f
构造一个display区的算法P162:
abp3
程序运行初期
u1 u3 u4
u7 u8
程序运行一段时间后
8 4 堆式动态存储分配
堆式存储分配需要解决的问题: ➢一是堆空间的分配
8 3 栈式动态存储分配
上例说明:当这段程序刚开始运行时;其存储 分配为图a所示;接下来主函数main运行;则为主函 数main分配数据区;运行栈为图 b;在main中调用 了函数m1;当函数m1运行时;运行栈为图 c;在函数 m1中又调用了函数m2;当函数m2运行时的运行栈 如图 d所示;由于函数m2中嵌套着块4;当运行块4 时;运行栈为图 e所示 当块4运行完后;块4数据区出 栈;运行栈恢复到图 d所示 当函数m2运行完后;运 行栈恢复到图 c所示 当函数m1运行完后;运行栈恢 复到图 b所示 当所有程序运行后;运行栈为空
main………………………块5
int x;
x=2;
printf"%d\n";m1x/5; 块5数据区
块1数据区
块1数据区
块2数据区 块5数据区 块1数据区
块3数据区 块2数据区 块5数据区 块1数据区
块4数据区 块3数据区 块2数据区 块5数据区 块1数据区
a程序刚开始 b运行main c运行m1 d运行m2 e运行块4
编译程序
初始数据
源程序 1.编译
目标程序
结果
2.运行
系统子程序
第8章 程序运行时的存储组织及管理P158
8 1 程序运行时的存储组织 8 2 静态存储分配 8 3 栈式动态存储分配 8 4 堆式动态存储分配
学习重点
影响存储分配策略的语言特征 静态存储分配 动态存储分配 活动记录 堆式存储分配变长块的方法
ret1
n;4 abp1 ret1 abp2 abp0 m;4
备注:返回地址ret1指示从fact函 数的特定动作返回到main函数内 部的调用点之后 返回地址ret2指 示从fact函数的特定动作返回到 fact函数内部的调用点之后
abp0 ret0 abp1 abp0 main fact;2;6;2 4 abp0 无前记录
程的返回地址;或是函数返回值
2形式参数存放相应实在参数的地址 或值
3程序变量部分将作为简单变量 参数
简单变量 数 组及其它程 序变量
8 2 静态存储分配
实现静态存储分配策略:编译程序对源程序进 行处理时;对每个变量在符号表中创建一个记录; 保存该变量的属性;其中包括为变量分配的存储空 间地址即目标地址 由于每个变量需要的空间大小 已知;可将数据区开始位置的地址A分配给第一个 变量;设第一个变量占n1个字节;则A+n1分配给第 二个变量;设第二个变量占n2个字节;同理; A+n1+n2分配给第三个变量等
例P163 C程序在程序执行期间 其运行栈的变化情况如右图所示
int factint n
地址
内容 n;2 abp3
ret2
if n<3 returnn else returnn*factn1;
abp4 abp0
ret2
n;3
abp2
main
ret2 abp3 abp0
int m; m=4;
printf"%d =%d\n";m;factm;
在上式中;abp是当前活动记录基址指针值;displayBL指 当前活动记录中display区中第BL个元素;nip是指隐式参 数的数目
注意:表达式BL1+nip可解释为display区的大小加隐式 参数区的大小
8 3 栈式动态存储分配
对于具有递归块程序结构的语言来说;一个程 序模块可以和多个活动记录相关 当程序运行 时;随着递归函数的每一次调用;在运行栈栈顶 将设置一个新的活动记录;返回地址也与每个 活动记录相联系
动态存储分配方式的分类: ➢栈式分配方式:主要采用一个栈作为动态存储分配 的存储空间 当调用一个程序时;过程中各数据项所需 的存储空间动态地分配于栈顶;当过程结束时;就释放 这部分空间 C PASCAL等语言即采用这种存储分配方 式
➢堆式分配方式:主要通过给运行程序分配一个大的 存储空间称为堆;每当运行需要时;就从这片空间中借 用一块;用过之后再退还给堆
real x; …………………块1 int m1int ind ……………块2
int x; x=m2ind+1;
int m2int j ………………块3
int f10; ……………块4 bool test1;
局部数据区 参数区 display区
块4活动记录abp4
m2活动记录abp3
main………………………块5 int x; x=2; printf"%d\n";m1x/5;
m2活动记录abp3 m1活动记录abp2
d1 x ind abp1 return2 d1 x
abp0
main活动记录abp1 abp0
d1 x 无前记录 OS
8 3 栈式动态存储分配
根据变量的二元地址BL;ON和display区的结 构可以计算出变量在运行栈中的地址;从而找到 变量的值 如果所引用的变量是一个外层模块的 局部变量;则它的层次号BL值必须小于当前正在 执行的模块的层次号 对这种情况而言;包含该变 量单元的活动记录能够间接通过当前活动记录 中display区中的相应指针来获取
➢1 参数区 1 隐式参数:
局部数据区 参数区 display区
返回地址:主调程序中调用语句的下一条可执行语句
的地址
指向前一个活动记录起始位置的指针:该基地址指针
存放该模块的主调模块的活动记录的基地址;用于确保
控制返回主调过程时;能使运行环境恢复到调用前的格
局
函数返回值:有的隐式参数区包含此项;有的不包括;
若使用相对地址方式;那么程序的每一次执行; 程序及其数据区可以处在不同的存储区内
8 3 栈式动态存储分配
动态存储分配方式:有些语言允许有长度可变的串 动态数组;并允许过程递归调用;那么在编译时就无法 确定数据空间的具体大小;故其存储分配必须留到目 标程序运行时动态地进行
说明 第3次调fact函数n=2;返回2给全局 变量区的fact单元
第2次调fact函数n=3;返回6给全局 变量区的fact单元
第1次调fact函数n=4 返回24给全 局变量区的fact单元
主函数运行;m=4;调fact函数 ret0是运行完main后返回的地址; 可以是OS或留空
fact用于保存fact函数的返回值;开 始时无值;最后fact函数返回后为 24
8 2 静态存储分配
例 char array16; int i; j ; real a; b; 假设: 数据区开始位置的地址264 字符型占2个存贮单元 整型占4个存贮单元 实型占8个存贮单元
8 2 静态存储分配
目标地址可采用的地址形式: ➢绝对地址
如果编写的编译程序是用于单任务环境;那么; 通常采用绝对地址作为目标地址 ➢相对地址
第8章 程序运行时的存储组织及管理
影响存储分配策略的语言特征: ➢ 过程能否递归 ➢ 过程能否嵌套 ➢ 过程调用时参数如何传递 ➢ 哪些实体可以作为参数和返回值 ➢ 是否允许动态的为对象分配和撤销存储空间 ➢ 存储空间是否必须显式地释放 ➢ ……
8 1 程序运行时的存储组织
程序运行时;系统将为程序分配一块存储空间 这块 空间用来存储程序的目标代码以及目标代码运行时需 要或产生的各种数据 从用途上看;这块空间可分为以 下几个部分: ➢1目标程序区:用来存放目标代码 ➢2静态数据区:用来存放编译时就能确定存储空间 的数据 ➢3运行栈区:用来存放运行时才能确定存储空间的 数据 ➢4运行堆区:用来存放运行时用户动态申请存储空 间的数据
8 3 栈式动态存储分配
活动记录:当程序运行进入一个程序模块时;就 在运行栈的栈顶创建一个专用数据区;该数据区通 常称为活动记录
当程序模块执行结束时即到达模块的出口;其相 应的活动记录将从运行栈的栈顶删除 因此在该模 块中所定义的变量在该模块的外部是不存在的
8 3 栈式动态存储分配
一个典型的活动记录结构如右图所示
➢3不允许用户动态建立数据实体
8 2 静态存储分配
FORTRAN语言没有长度可变的串;也没有动态数组; 其子程序和函数也不允许递归调用;所以FORTRAN语
言采用静态存储分配方式
例P159 一个FORTRAN程序模块静态存储分配的典型
数据区格局如右图所示;其中:
1隐式参数主要用于和主调模块的通讯;它可以是主调过
8 3 栈式动态存储分配
栈式动态分配方式的实现:
➢1申请:在程序运行中;当程序模块被调用时;就从总 的数据区中请求一个空间作为其数据区即加入运行栈 中;并保留该空间直到执行完整个模块为止
➢2释放:当模块执行完毕;退出模块时;释放它所占有 的数据空间即从运行栈中弹出
➢3嵌套调用:从模块被调用到它运行结束之间;还可 以通过过程调用或程序块入口进入其他的模块;此时; 也按上面所介绍的方法将这些模块的数据区压入或弹 出运行栈 当嵌套的被调程序运行结束返回到主调程序 中的调用点时;运行栈中的格局和内容会恢复到调用之 前的情况
例P160设有如下C程序;其运行栈的变化情况如下图所示
real x; …………………块1
int m1int ind ……………块2
对于C语言;函数是程序块;
int x;
一对花括号内的程序即复合
x=m2ind+1;
语句也可以看成是一个程序
块
int m2int j ………………块3
int f10; ……………块4 bool test1;
d2
1) 如果j=i+1即进入一个程序块;则复 块4活动记录abp4 d1
制i层的display;然后增加一个指向i
j
层模块活动记录基地址的指针
abp2 return3
2) 如果j≤i即调用对当前模块来说是 属于全程声明的过程模块;则来自i层 模块活动记录中的display区前面j1 个入口将组成j层模块的display区
8 2 静态存储分配
静态存储分配方式:对于源程序中出现的各种数据 项;如常量 简单变量 常界数组 非变体记录等; 在编 译时就给它们分配固定的存储空间;而且在目标程序 运行时;总是使用这些在编译时就分配好的存储单元 作为它们的数据空间
采用静态存储分配的语言必须满足下列条件: ➢1不允许过程有递归调用 ➢2不允许有可变大小的数据项;如可变数组或可变字 符串
8 3 栈式动态存储分配
给定一个要访问的具有地址为BL;ON的变量;设该变量 在LEV 层的一个模块中 该变量的地址ADDR可按如下方 法计算P163:
if BL=LEV then ADDR=abp+BL1+nip+ON//局部变量 else if BL<LEV then //全局变量
ADDR=displayBL+BL1+nip+ON else write地址错;不合法的模块层次
8 3 栈式动态存储分配
栈式存储分配适合那些过程允许嵌套定义 递 归调用的语言;其过程的进入和退出具有后进 先出的特点 如果语言允许动态申请和释放存 储空间;那么;栈式存储分配就不适合了;这时; 可以采用堆式动态存储分配策略
8 4 堆式动态存储分配
堆式分配策略的基本思路:假设程序运行时有一个大 的连续的存储空间堆;当存储管理程序接收到运行程序的 存储空间请求时;就从堆中分配一块空间给运行程序 当 运行程序用完后再退还给堆即释放 管理程序回收其存储 空间以备后面使用 由于每块空间可以按任意顺序释放; 这样;程序经过一段运行后;堆将被划分成若干已用块和 空闲块
还有更好的处理返回值的方法
2 显式参数:显式参数区是形式参数的通讯区
形式参数的传递有传值 传地址 传名等方法
8 3 栈式动态存储分配
➢2 display区嵌套层次显示表 display区用于保存对当前正在执行的模块
来说是全局的程序变量区的信息;它由一系列地 址指针所组成;每一个指针指向一个程序块的活 动记录的开始位置;而这个程序块对于当前正在 执行的程序块来说是全局的
应是main;m2;m1;x
m1活动记录abp2 main活动记录abp1
abp0
test1 f abp3
d2 d1 j abp2 return3 d1 x;0 ind abp1 return2 d1 x ;2 abp0
d1 x 无前记录 OS
test1
f
构造一个display区的算法P162:
abp3
程序运行初期
u1 u3 u4
u7 u8
程序运行一段时间后
8 4 堆式动态存储分配
堆式存储分配需要解决的问题: ➢一是堆空间的分配
8 3 栈式动态存储分配
上例说明:当这段程序刚开始运行时;其存储 分配为图a所示;接下来主函数main运行;则为主函 数main分配数据区;运行栈为图 b;在main中调用 了函数m1;当函数m1运行时;运行栈为图 c;在函数 m1中又调用了函数m2;当函数m2运行时的运行栈 如图 d所示;由于函数m2中嵌套着块4;当运行块4 时;运行栈为图 e所示 当块4运行完后;块4数据区出 栈;运行栈恢复到图 d所示 当函数m2运行完后;运 行栈恢复到图 c所示 当函数m1运行完后;运行栈恢 复到图 b所示 当所有程序运行后;运行栈为空
main………………………块5
int x;
x=2;
printf"%d\n";m1x/5; 块5数据区
块1数据区
块1数据区
块2数据区 块5数据区 块1数据区
块3数据区 块2数据区 块5数据区 块1数据区
块4数据区 块3数据区 块2数据区 块5数据区 块1数据区
a程序刚开始 b运行main c运行m1 d运行m2 e运行块4
编译程序
初始数据
源程序 1.编译
目标程序
结果
2.运行
系统子程序
第8章 程序运行时的存储组织及管理P158
8 1 程序运行时的存储组织 8 2 静态存储分配 8 3 栈式动态存储分配 8 4 堆式动态存储分配
学习重点
影响存储分配策略的语言特征 静态存储分配 动态存储分配 活动记录 堆式存储分配变长块的方法
ret1
n;4 abp1 ret1 abp2 abp0 m;4
备注:返回地址ret1指示从fact函 数的特定动作返回到main函数内 部的调用点之后 返回地址ret2指 示从fact函数的特定动作返回到 fact函数内部的调用点之后
abp0 ret0 abp1 abp0 main fact;2;6;2 4 abp0 无前记录
程的返回地址;或是函数返回值
2形式参数存放相应实在参数的地址 或值
3程序变量部分将作为简单变量 参数
简单变量 数 组及其它程 序变量
8 2 静态存储分配
实现静态存储分配策略:编译程序对源程序进 行处理时;对每个变量在符号表中创建一个记录; 保存该变量的属性;其中包括为变量分配的存储空 间地址即目标地址 由于每个变量需要的空间大小 已知;可将数据区开始位置的地址A分配给第一个 变量;设第一个变量占n1个字节;则A+n1分配给第 二个变量;设第二个变量占n2个字节;同理; A+n1+n2分配给第三个变量等
例P163 C程序在程序执行期间 其运行栈的变化情况如右图所示
int factint n
地址
内容 n;2 abp3
ret2
if n<3 returnn else returnn*factn1;
abp4 abp0
ret2
n;3
abp2
main
ret2 abp3 abp0
int m; m=4;
printf"%d =%d\n";m;factm;
在上式中;abp是当前活动记录基址指针值;displayBL指 当前活动记录中display区中第BL个元素;nip是指隐式参 数的数目
注意:表达式BL1+nip可解释为display区的大小加隐式 参数区的大小
8 3 栈式动态存储分配
对于具有递归块程序结构的语言来说;一个程 序模块可以和多个活动记录相关 当程序运行 时;随着递归函数的每一次调用;在运行栈栈顶 将设置一个新的活动记录;返回地址也与每个 活动记录相联系
动态存储分配方式的分类: ➢栈式分配方式:主要采用一个栈作为动态存储分配 的存储空间 当调用一个程序时;过程中各数据项所需 的存储空间动态地分配于栈顶;当过程结束时;就释放 这部分空间 C PASCAL等语言即采用这种存储分配方 式
➢堆式分配方式:主要通过给运行程序分配一个大的 存储空间称为堆;每当运行需要时;就从这片空间中借 用一块;用过之后再退还给堆
real x; …………………块1 int m1int ind ……………块2
int x; x=m2ind+1;
int m2int j ………………块3
int f10; ……………块4 bool test1;
局部数据区 参数区 display区
块4活动记录abp4
m2活动记录abp3
main………………………块5 int x; x=2; printf"%d\n";m1x/5;
m2活动记录abp3 m1活动记录abp2
d1 x ind abp1 return2 d1 x
abp0
main活动记录abp1 abp0
d1 x 无前记录 OS
8 3 栈式动态存储分配
根据变量的二元地址BL;ON和display区的结 构可以计算出变量在运行栈中的地址;从而找到 变量的值 如果所引用的变量是一个外层模块的 局部变量;则它的层次号BL值必须小于当前正在 执行的模块的层次号 对这种情况而言;包含该变 量单元的活动记录能够间接通过当前活动记录 中display区中的相应指针来获取
➢1 参数区 1 隐式参数:
局部数据区 参数区 display区
返回地址:主调程序中调用语句的下一条可执行语句
的地址
指向前一个活动记录起始位置的指针:该基地址指针
存放该模块的主调模块的活动记录的基地址;用于确保
控制返回主调过程时;能使运行环境恢复到调用前的格
局
函数返回值:有的隐式参数区包含此项;有的不包括;