运行时刻环境 (Runtime Environment)

Slides:



Advertisements
Similar presentations
2.5 函数的微分 一、问题的提出 二、微分的定义 三、可微的条件 四、微分的几何意义 五、微分的求法 六、小结.
Advertisements

第七章 运行时刻环境 赵建华 南京大学计算机系.
Chapter 3: SQL.
第六 章数据库访问页 6.1 数据访问页视图 6.2 创建数据访问页 6.3 编辑数据访问页 6.4 查看数据访问页 退出.
6.3 非局部名字的访问 本节介绍 无过程嵌套的静态作用域(C语言) 有过程嵌套的静态作用域(Pascal语言) 动态作用域(Lisp语言)
Oracle数据库 Oracle 子程序.
C++中的声音处理 在传统Turbo C环境中,如果想用C语言控制电脑发声,可以用Sound函数。在VC6.6环境中如果想控制电脑发声则采用Beep函数。原型为: Beep(频率,持续时间) , 单位毫秒 暂停程序执行使用Sleep函数 Sleep(持续时间), 单位毫秒 引用这两个函数时,必须包含头文件
在PHP和MYSQL中实现完美的中文显示
第九章 字符串.
EBNF与操作语义 请用扩展的 BNF 描述 javascript语言里语句的结构;并用操作语义的方法描述对应的语义规则
第八章 函数 §8.1 概述 一个较大程序一般分为若干个程序模块,每一个模块实现一个特定的功能。所有的高级语言中都有子程序的概念,在C中子程序就是函数。 一个C程序可由一个主函数和若干个函数构成,由主函数调用其它函数,其它函数也可以相互调用.
Hadoop I/O By ShiChaojie.
强连通分量 无向图 1、任意两顶点连通称该图为连通图 2、否则将其中的极大连通子图称为连通分量 A D C B E 有向图
编译原理与技术 运行环境 2018/11/24 《编译原理与技术》-运行环境.
编译原理与技术 第6章 运行时存储空间的组织和管理 6学时.
存储系统.
管理信息结构SMI.
走进编程 程序的顺序结构(二).
辅导课程六.
网络常用常用命令 课件制作人:谢希仁.
Zhao4zhong1 (赵中) C语言指针与汇编语言地址.
Zhao4zhong1 (赵中) C语言指针与汇编语言地址.
第一单元 初识C程序与C程序开发平台搭建 ---观其大略
Windows网络操作系统管理 ——Windows Server 2008 R2.
第十章 IDL访问数据库 10.1 数据库与数据库访问 1、数据库 数据库中数据的组织由低到高分为四级:字段、记录、表、数据库四种。
本节内容 模拟线程切换 视频提供:昆山滴水信息技术有限公司 官网地址: 论坛地址: QQ交流 :
逆向工程-汇编语言
动态规划(Dynamic Programming)
CPU结构和功能.
中国科学技术大学计算机系 陈香兰(0551- ) Spring 2009
第八章 运行时存储空间的组织与管理 目标程序运行时的存储结构 过程活动记录和运行时栈 变量访问环境 是CPU能直接寻址的存储空间.
《编译原理与技术》 期末复习 计算机科学与技术学院 郑启龙 李 诚 25/12/2018.
用event class 从input的root文件中,由DmpDataBuffer::ReadObject读取数据的问题
宁波市高校慕课联盟课程 与 进行交互 Linux 系统管理.
宁波市高校慕课联盟课程 与 进行交互 Linux 系统管理.
C++语言程序设计 C++语言程序设计 第七章 类与对象 第十一组 C++语言程序设计.
C语言程序设计 主讲教师:陆幼利.
EBNF与操作语义 请用扩展的 BNF 描述 javascript语言里语句的结构;并用操作语义的方法描述对应的语义规则
简单介绍 用C++实现简单的模板数据结构 ArrayList(数组, 类似std::vector)
$9 泛型基础.
顺序表的删除.
本节内容 随机读取 视频提供:昆山爱达人信息技术有限公司.
线 性 代 数 厦门大学线性代数教学组 2019年4月24日6时8分 / 45.
VisComposer 2019/4/17.
VB与Access数据库的连接.
目录 7.1 用户自定义函数的种类 7.2 函数的定义 7.3 被调函数的声明 7.4 函数的调用 7.5 函数的嵌套调用
<编程达人入门课程> 本节内容 内存的使用 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群: ,
第九节 赋值运算符和赋值表达式.
本节内容 结构体 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
数据报分片.
Chapter 18 使用GRASP的对象设计示例.
多层循环 Private Sub Command1_Click() Dim i As Integer, j As Integer
Visual Basic程序设计 第13章 访问数据库
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
Delphi 7.0开发示例.
临界区问题的硬件指令解决方案 (Synchronization Hardware)
本节内容 C语言的汇编表示 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
第二节 函数的极限 一、函数极限的定义 二、函数极限的性质 三、小结 思考题.
实验目的:掌握数据的顺序存储结构及它们在计算机中的操作。 实验内容:
基于列存储的RDF数据管理 朱敏
C++语言程序设计 C++语言程序设计 第一章 C++语言概述 第十一组 C++语言程序设计.
本节内容 动态链接库 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
C++语言程序设计 C++语言程序设计 第九章 类的特殊成员 第十一组 C++语言程序设计.
VB与Access数据库的连接.
本节内容 进程 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
第四章 UNIX文件系统.
使用Fragment 本讲大纲: 1、创建Fragment 2、在Activity中添加Fragment
顺序结构程序设计 ——关于“字符串”和数值.
多个Activity的使用 本讲大纲: 1、使用Bundle在Activity之间交换数据 2、调用另一个Activity并返回结果
计算机编程 信息管理与工程学院 2014年9月.
Presentation transcript:

运行时刻环境 (Runtime Environment)

在讨论代码生成之前,我们先介绍一些关于如何组织可 执行代码(executable code)的常见做法 代码和数据在执行时是什么样子的? 运行时刻环境: 代码和数据的存储分配 访问变量时使用的机制 过程之间的连接、参数传递的机制 和操作系统、目标机器的接口 重点讨论:过程调用的存储管理

从源代码到执行 a loader is a part of an OS

存储组织

存储组织 对目标程序运行时的逻辑地址空间的组织和管理 常见的编译器对于目标程序运行时刻的空间划分 包含代码区和数据区 以连续字节块存储 字节是内存最小的编址单位 一个字节是8个二进制位 4个字节构成一个机器字 ……

存储组织 代码区:放置可执行目标代码,在编 译时刻该区域的大小就可以确定。这 个区通常在存储的低地址端 静态区:程序的某些数据对象,如全 局变量和编译器产生的某些数据,它 们的大小可以在编译时刻知道 动态区域 为了将运行时刻空间利用率最大化,堆区 和栈区被放在剩余地址空间的两端。它们 的大小随着程序运行会发生改变 栈:存放活动记录(过程调用时有关机器 状态的信息)。通常向低地址方向增长 堆:malloc的数据对象。通常向高地址方 向增长

int x = 10; void func() { int a = 0; int int x = 10; void func() { int a = 0; int *p = &x; //p is pointing to the memory in data segment int *q = &a: //q is pointing to the memory in stack char *r = malloc(10); //r is pointing to memory in heap … }

空间的栈式分配 与过程调用相关的数据在栈中进行存储和管理 过程调用(过程的活动) 在时间上总是嵌套的 当一个过程被调用时,用于存放该过程的局部变量和 相关机器状态的空间(活动记录)被压入栈 当这个过程结束时,该空间从栈中弹出 过程调用(过程的活动) 在时间上总是嵌套的 后调用的先返回 因此用栈来分配过程活动所需内存空间

过程调用示例 使用递归的快速排序算法

活动树(activation tree) 程序运行期间的所有过程活动可以用树表示 每个结点对应于一个过程活动 根结点对应于main过程的活动 过程p的某次活动对应的结点的所有子结点 表示此次活动所调用的各个过程活动 从左向右,表示调用的先后顺序 一个子节点必须在其右兄弟节点的活动开始之前结束

活动树示例 过程调用序列和活动树的前序遍历相对应 过程返回序列和活动树的后序遍历相对应 假定控制流在某个过程的某次活动中,对应 于树上节点N。N及其祖先节点是当前活跃的 (未结束的)活动。这些活动被调用的顺序 是它们从根节点到N的路径上出现的顺序。 这些活动将按照该顺序的反向顺序返回。

活动记录(activation record) 对于每个过程活动,压入栈的数据和信息 也被称作stack frame 这个栈被称作call stack / control stack / runtime stack / stack 每个活跃的活动有一个位于栈中的活动记录 活动树的根位于栈底 当前程序控制所在活动的活动记录位于栈顶 栈中全部活动记录的序列对应于在活动树中从根节点 到达当前活跃的活动节点的路径 -- 所有的尚未返回 的过程调用

活动记录存储示例 x86 栈底 m 高地址 q(1, 9) q(1, 3) 栈顶 q(2, 3) 低地址

活动记录的内容 内容与所实现的语言相关 微处理器制造者会约定活动记录内容的某种布局 一般包括:函数实参、局部变量、返回地址等 称作calling conventions 如果所有编译器都使用同样的calling conventions,那 么一个编译器编译出的函数就可以调用另一个编译器 编译出的函数

本书中活动记录的内容: 临时变量:某些临时中间结果 局部数据:该函数的局部变量 靠近栈底/高地址 临时变量:某些临时中间结果 局部数据:该函数的局部变量 机器状态信息:在对此函数的此次调用之 前的机器状态信息(包括返回地址、寄存 器内容),函数返回时需要恢复这些信息 访问链:在其它活动记录中存放的数据, 访问时需要访问链进行定位(后面介绍) 控制链:指向调用者的活动记录 返回值:存放被调用函数返回给调用函数 的值 实参:存放调用函数提供的实在参数(尽 可能放在寄存器中) 靠近栈顶/低地址

调用代码序列、返回代码序列 调用代码序列(calling sequence):实现函数调 用的代码段 为一个活动记录在栈中分配空间,并在此记录的字段 中填写信息 返回代码序列(return sequence): 恢复机器状态,使得调用函数能够在调用结束后继续 执行的代码 一个调用代码序列通常被分割到调用者caller和 被调用者callee的代码中

调用代码序列如何分割? 本书期望把调用代码序列中尽可能多的部分放在被调用者中。当然,被调用者不可能知道所有的事。 生成的代码 int f(int x, int y) { … } main() { a = f(1, 2); b = f(a, a); c = f(a, b); 调用代码序列中被调用者部分; 函数体 … 对f的第1次调用的调用代码序列中调用者部分; 对f的第2次调用的调用代码序列中调用者部分; 对f的第3次调用的调用代码序列中调用者部分; 本书期望把调用代码序列中尽可能多的部分放在被调用者中。当然,被调用者不可能知道所有的事。

调用代码序列的设计 要与活动记录布局的设计相呼应 可以遵循下列原则: 调用者和被调用者之间传递的值(实参、返回值), 一般被放在被调用者活动记录的开始位置,因此它们 尽可能地靠近调用者的活动记录 好处: 调用者能够计算该次调用的实参的值并放在自身活动记录的 顶部,而不用创建整个被调用者的活动记录 调用者和被调用者都知道将来被调用者的返回值放在哪里

调用代码序列的设计 要与活动记录布局的设计相呼应 可以遵循下列原则: 调用者和被调用者之间传递的值(实参、返回值), 一般被放在被调用者活动记录的开始位置,因此它们 尽可能地靠近调用者的活动记录 固定长度的项(包括控制链、访问链和机器状态字段) 放在记录的中间位置 开始不知道大小的项(例如临时变量)被放置在活动 记录的尾部 “栈顶”指针top_sp所指的位置:活动记录中固定长 度字段的末端 那么固定长度的数据就可以通过固定的相对于top_sp的偏移 量来访问

调用者和被调用者合作管理栈示例 调用代码序列 调用者计算实参的值 调用者将返回地址和 当前top_sp的值放在 被调用者的活动记录 中,然后增加top_sp 的值 被调用者保存寄存器 值和其它状态信息 被调用者初始化其局 部数据并开始执行 调用者也可以做!

调用者和被调用者合作管理栈示例 返回代码序列 被调用者将返回值放 在与参数相邻的位置 被调用者恢复top_sp 和其它寄存器,然后 跳转到由调用者放在 机器状态字段中的返 回地址 尽管top_sp已经被减 小,但调用者仍然可 以根据当前top_sp的 位置找到返回值

栈中非局部数据的访问 讨论过程如何访问数据 特别是,如何找到在过程p中使用但又不属于p 的数据

没有嵌套函数的数据访问 C语言的变量要么在某个函数内定义,要么在所 有函数之外定义 全局变量被分配在静态区,在编译时刻即确定它们的 位置 其他变量一定是栈顶活动记录里的局部变量,且偏移 量已知,可以通过top_sp指针加上偏移量来访问这些 变量

带嵌套函数的数据访问

带嵌套函数的数据访问

嵌套深度

访问链(access link) 在活动记录中增 加一个访问链指 针 若函数p直接嵌套 在函数q中,那么 p的任何活动记录 中的访问链都指 向最近的q的活动 记录 嵌套深度沿着访 问链路逐一递减

访问链 假定函数p的嵌套深度为np,它引用嵌套深度为nq的函数q声明的变量x,nq ≤ np。如何访问x的存储单元? 从栈顶的活动记录开始,追踪访问链np - nq次,到达x的声明所在函数q的活动记录 x的地址由下面的二元组表示(在编译时刻已知):(np – nq, x在活动记录中的偏移)

访问链的维护 当过程q调用过程p时 p的深度大于q:根据作用域规则,p必然在q中直接 定义;那么p的访问链指向当前活动记录(即q) 例如:sort调用quicksort(1, 9)

访问链的维护 当过程q调用过程p时 递归调用p= q:新活动记录的访问链等于当前访问链 (即和前一个活动记录q指向同一目标) 例如:quicksort(1, 9)调用quicksort(1, 3)

访问链的维护 当过程q调用过程p时 p的深度小于等于q的深度:必然有过程r,p直接在r中 定义,而q嵌套在r中;p的访问链指向栈中r的活动记录 例如:partition调用exchange 找到r:从q的活动记录开始,沿着访问链经过nq – np +1步就可以找到r

访问链

显示表 如果嵌套深度太大,可能需要沿着一段很长的访 问链路才能找到需要的数据 显示表是一个更高效的数据访问实现方法 设定一个数组d,它为每个嵌套深度保存一个指 针,指针d[i]指向栈中最高的对应于某个嵌套深 度为i的函数的活动记录 如果函数p正在运行,且它需要访问属于某个嵌 套深度为i的某个函数q的变量x,那么只要查看 d[i]就可以找到q的活动记录,进而访问到x 注意 i = nq ≤ np

显示表的维护 需要在新的活动 记录p中保存显 示表条目的原来 的值。从而在p 返回时可以恢复 到调用前的值。

本章总结 运行时刻存储组织 栈、活动记录、栈中非局部数据访问