欢迎来到三一办公! | 帮助中心 三一办公31ppt.com(应用文档模板下载平台)
三一办公
全部分类
  • 办公文档>
  • PPT模板>
  • 建筑/施工/环境>
  • 毕业设计>
  • 工程图纸>
  • 教育教学>
  • 素材源码>
  • 生活休闲>
  • 临时分类>
  • ImageVerifierCode 换一换
    首页 三一办公 > 资源分类 > PPT文档下载  

    运行时的存储组织哈工大王宏志.ppt

    • 资源ID:6611419       资源大小:1.67MB        全文页数:126页
    • 资源格式: PPT        下载积分:15金币
    快捷下载 游客一键下载
    会员登录下载
    三方登录下载: 微信开放平台登录 QQ登录  
    下载资源需要15金币
    邮箱/手机:
    温馨提示:
    用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)
    支付方式: 支付宝    微信支付   
    验证码:   换一换

    加入VIP免费专享
     
    账号:
    密码:
    验证码:   换一换
      忘记密码?
        
    友情提示
    2、PDF文件下载后,可能会被浏览器默认打开,此种情况可以点击浏览器菜单,保存网页到桌面,就可以正常下载了。
    3、本站不支持迅雷下载,请使用电脑自带的IE浏览器,或者360浏览器、谷歌浏览器下载即可。
    4、本站资源下载后的文档和图纸-无水印,预览文档经过压缩,下载后原文更清晰。
    5、试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。

    运行时的存储组织哈工大王宏志.ppt

    第8章 运行时的存储组织,School of Software Harbin Institute of Technology,重点:符号表的内容、组织,过程调用实现,静态存储分配、动态存储分配的基本方法。难点:参数传递,过程说明语句代码结构,过程调用语句的代码结构,过程调用语句的语法制导定义,栈式存储分配。,2023/11/17,2,第8章运行时的存储组织,8.1 与存储组织有关的源语言概念与特征8.2 存储组织8.3 静态存储分配8.4 栈式存储分配8.5 栈中非局部数据的访问8.6 堆管理8.7 本章小结,2023/11/17,3,8.1 与存储组织有关的源语言概念与特征,编译程序必须准确地实现包含在源程序中的各种抽象概念,如名字、作用域、数据类型、操作符、过程、参数和控制流结构等,这些概念反映了源语言所具有的一些特征,对它们的支持往往会影响运行时的存储组织和分配策略 给定一个源程序,编译程序必须根据源语言的特征(规定)为源程序中的许多问题做出决策,包括何时、怎样为名字分配内存地址。静态策略:在编译时即可做出决定的策略动态策略:直到程序执行时才能做出决定的策略,2023/11/17,4,8.1.1 名字及其绑定,“名字”、“变量”和“标识符”的区别与联系名字和变量分别表示编译时的名字和运行时该名字所代表的内存位置。标识符则是一个字符串,用于指示数据对象、过程、类或对象的入口。所有标识符都是名字,但并不是所有的名字都是标识符,名字还可以是表达式。例如,名字x.y可能表示x所代表结构的域y。同一标识符可以被声明多次,但每个声明都引入一个新的变量。即使每个标识符只被声明一次,局部于某个递归过程的标识符在不同的运行时刻也将指向不同的内存位置。,2023/11/17,5,名字的绑定,从名字到值的两步映射环境把名字映射到左值,而状态把左值映射到右值赋值改变状态,但不改变环境。如果环境将名字x映射到存储单元s,我们就说x被绑定到s,名字,内存位置(变量),状态,值,环境,2023/11/17,6,8.1.2 声明的作用域,x的声明的作用域是程序中的这样一段区域,在该区域中,x的引用均指向x的这一声明。对于某种程序设计语言,如果只通过考察其程序就可以确定某个声明的作用域,则称该语言使用静态作用域;否则称该语言使用动态作用域。C+、Java和C#等还提供了对作用域的显式控制,其方法是使用public、private和protected这样的关键字。声明的作用域是通过符号表进行管理的,详见8.4节的讨论。,2023/11/17,7,1.静态作用域,在具有程序块结构的语言中,变量声明的静态作用域规则如下:如果名字x的声明D属于程序块B,则D的作用域是B的所有语句,只有满足如下条件的程序块B除外:B嵌套在B中(可以是任意的嵌套深度),且B中具有同一名字x的一个新的声明。令B1,B2,Bk是包围x的本次引用的所有程序块,Bk-1是Bk的直接外层程序块,Bk-2是Bk-1的直接外层程序块,如此类推。找到使x的某个声明属于Bi的最大i,则x的本次引用指向Bi中的这个声明。换句话说,x的本次引用处在Bi中的这个声明的作用域中。,2023/11/17,8,1.静态作用域,表8.1 图8.10所示程序中声明的作用域,2023/11/17,9,2.显式访问控制,类和结构为其成员引入了一种新的作用域如果p是某个带有域(成员)x的类的对象,则p.x中x的引用将指向该类定义中的域x。与程序块结构类似的是,类D中成员x的声明的作用域将会扩展到D的任何子类D,除非D中具有同一名字x的一个局部声明。,2023/11/17,10,2.显式访问控制,通过使用像public、private和protected这样的关键字,C+或Java类的面向对象语言提供了一种对超类中成员名字的显式访问控制。这些关键字通过限制访问来支持封装。因此,私有名的作用域只包含与该类及其友类相关联的方法声明和定义,保护名只对其子类是可访问的,而公用名从类的外部也是可以访问的。,2023/11/17,11,3.动态作用域,动态作用域规则相对于时间而静态作用域规则相对于空间静态作用域规则要求我们找出某个引用所指向的声明,条件是该声明处在包围该引用的“空间上最近的”单元(程序块)中。动态作用域也是要求我们找出某个引用所指向的声明,但条件是该声明处在包围该引用的“时间上最近的”单元(过程活动)中。,2023/11/17,12,3.动态作用域,“动态作用域”通常是指下面的策略名字x的引用指向带有x声明的最近被调用的过程中x的这个声明。例如,过程被当做参数进行传递时,2023/11/17,13,8.1.3 过程及其活动,将“过程、函数和方法”统称为“过程”过程定义是一个声明,它的最简单形式是把一个标识符和一个语句联系起来。该标识符是过程名,而这个语句是过程体。当过程名出现在可执行语句中时,称相应的过程在该点被调用。过程调用就是执行被调用过程的过程体。注意,过程调用也可以出现在表达式中。,2023/11/17,14,8.1.3 过程及其活动,出现在过程定义中的某些标识符具有特殊的意义,称为该过程的形式参数,简称为形参。调用过程时,表达式作为实在参数(或实参)传递给被调用的过程,以替换出现在过程体中的对应形式参数。节将讨论实参和形参的结合方法。过程体的每次执行叫做该过程的一个活动。过程p的一个活动的生存期是从过程体执行的第一步到最后一步,包括执行被p调用的过程的时间,以及再由这样的过程调用其它过程所花的时间,等等。,2023/11/17,15,8.1.3 过程及其活动,如果a和b是过程的活动,那么它们的生存期或者不交迭,或者嵌套。也就是说,如果在a结束之前b就开始了,那么b必须在a结束之前结束。如果同一个过程的一次新的活动可以在前一次活动结束前开始,则称这样的过程是递归的。递归过程p也可以间接地调用自己。如果某个过程是递归的,则在某一时刻可能有它的几个活动同时活跃,这时必须合理组织这些同时活跃着的活动的内存空间。,2023/11/17,16,8.1.4 参数传递方式,当一个过程调用另一个过程时,它们之间交换信息的方法通常是通过非局部名字和被调用过程的参数来实现的。传值传地址传值结果传名其主要区别在于实参所代表的究竟是左值、右值还是实参的正文本身,2023/11/17,17,1.传值,计算实参并将其右值传递给被调用过程 传值方式可以如下实现:被调用过程为每个形参开辟一个称为形式单元的存储单元,用于存放相应实参的值。调用过程计算实参,并把右值放入相应的形式单元中。,调用者,被调用者直接使用,A,实际参数A,形式参数X,A的值,单向传值,2023/11/17,18,2.传地址,调用过程将实参的地址传递给被调用过程 传地址方式可以如下实现:如果实参是一个具有左值的名字或表达式,则传递该左值本身 如果实参是a+b或2这样的没有左值的表达式,则调用过程首先计算实参的值并将其存入一个新的存储单元,然后将这个新单元的地址传递给被调用过程,调用者,被调用者间址访问,A,实际参数A,形式参数X,A的地址,传地址,2023/11/17,19,3.传值结果,传值结果就是将传值和传地址这两种方式结合起来传值结果方式可以如下实现:实参的右值和左值同时传给被调用过程。在被调用过程中,像传值方式那样使用实参的右值。当控制返回调用过程时,根据传递来的实参的左值,将形参当前的值复制到实参存储单元。,调用者,被调用者,A,实际参数A,形式参数X,A的值,传值/传地址,A的地址,2023/11/17,20,4.传名,用实参表达式对形参进行文字替换。传名方式可以如下实现:在调用过程中设置计算实参左值或右值的形实转换子程序。被调用过程为每个形参开辟一个存储单元,用于存放该实参的形实转换子程序的入口地址。被调过程执行时,每当要向形参赋值或取该形参的值时,就调用相应于该形参的形实转换子程序,以获得相应的实参地址或值。注意,形实转换子程序的运行环境是调用程序。形实转换子程序又称为换名子程序thunk。,2023/11/17,21,例,procedure swap(var x,y:integer);var temp:integer;begin 调用swap(i,ai)temp:=x;temp:=i;x:=y;i:=ai;y:=tempai:=temp end,2023/11/17,22,子程序P(X,Y,Z);Y:=Y+1;Z:=Z+X,传值:2,传地址:X=T=5,Y=Z=A=2A:=A+1=2+1A:=A+T=3+58,传名A:=A+1=3A:=A+A+B=3+3+39,主程序A:=2;B:=3;P(A+B,A,A);print A,临时单元:T:A+B=5,2023/11/17,23,编译程序组织存储空间时必须考虑的问题,过程能否递归?当控制从过程的活动返回时,局部变量的值是否要保留?过程能否访问非局部变量?过程调用的参数传递方式?过程能否作为参数被传递?过程能否作为结果值传递?存储块能否在程序控制下动态地分配?存储块是否必须显式地释放?,2023/11/17,24,8.2 存储组织,8.2.1 运行时内存的划分8.2.2 活动记录8.2.3 局部数据的组织8.2.4 全局存储分配策略,2023/11/17,25,7.2.1 运行时内存的划分,目标代码,静态数据,栈,堆,空闲 空间,2023/11/17,26,过程的每个活动所需要的信息用一块连续的存储区来管理,这块存储区叫做活动记录 假定语言的特点为:允许过程递归调用、允许过程含有可变数组,过程定义允许/不允许嵌套。采用栈式存储分配机制活动记录:运行时,每当进入一个过程就有一个相应的活动记录压入栈顶。活动记录一般含有连接数据、形式单元、局部变量、局部数组的内情向量和临时工作单元等。,8.2.2 活动记录,2023/11/17,27,对任何局部变量X的引用可表示为变址访问:dxSPdx:变量X相对于活动记录起点的地址,在编译时可确定。,参数个数,返回地址,形式单元,临时变量,数组内情向量,简单变量,SP 0,1,2,旧SP,TOP,每个过程的活动记录内容 非嵌套语言(如C),2023/11/17,28,连接数据 返回地址 动态链:指向调用该过程前的最新活动记录地址的指针。静态链:指向静态直接外层最新活动记录地址的指针,用来访问非局部数据。,静态链,动态链,形式单元,临时变量,数组内情向量,局部变量,SP0,1,2,返回地址,TOP,每个过程的活动记录内容 嵌套语言(如Pascal),2023/11/17,29,形式单元:存放相应的实在参数的地址或值。局部数据区:局部变量、内情向量、临时工作单元(如存放对表达式求值的结果)。,静态链,动态链,形式单元,临时变量,数组内情向量,局部变量,SP 0,1,2,返回地址,TOP,每个过程的活动记录内容,2023/11/17,30,8.2.3 局部数据的组织,字节是可编址内存的最小单位。变量所需的存储空间可以根据其类型而静态确定。一个过程所声明的局部变量,按这些变量声明时出现的次序,在局部数据域中依次分配空间。局部数据的地址可以用相对于某个位置的地址来表示。数据对象的存储安排还有对齐的问题。整数必须放在内存中特定的位置,如被2、4、8整除的地址,2023/11/17,31,8.2.3 局部数据的组织,在SPARC/Solaris工作站上下面两个结构的size分别是24和16,为什么不一样?typedef struct _atypedef struct _bchar c1;char c1;long i;char c2;charc2;long i;double f;double f;a;b;,2023/11/17,32,8.2.3 局部数据的组织,在SPARC/Solaris工作站上下面两个结构的size分别是24和16,为什么不一样?typedef struct _atypedef struct _bchar c1;0 char c1;0long i;4 char c2;1charc2;8 long i;4double f;16 double f;8a;b;,2023/11/17,33,8.2.3 局部数据的组织,在X86/Linux机器的结果和SPARC/Solaris工作站不一样,是20和16。typedef struct _atypedef struct _bchar c1;0 char c1;0long i;4 char c2;1charc2;8 long i;4double f;12 double f;8a;b;,2023/11/17,34,静态存储分配策略(FORTRAN)如果在编译时能确定数据空间的大小,则可采用静态分配方法:在编译时刻为每个数据项目确定出在运行时刻的存储空间中的位置。动态存储分配策略(PASCAL)如果在编译时不能确定运行时数据空间的大小,则必须采用动态分配方法。允许递归过程及动态申请、释放内存。栈式动态存储分配堆式动态存储分配,8.2.4 全局存储分配策略,2023/11/17,35,8.3 静态存储分配策略,如果在编译时就能确定一个程序在运行时所需要的存储空间的大小,则在编译时就能安排好目标程序运行时的全部数据空间,并能确定每个数据项的地址,存储空间的这种分配方法称为静态存储分配。必须满足如下条件:数据对象的长度和它在内存中的位置在编译时必须是已知的;不允许过程的递归调用,因为一个过程的所有活动都是用同样的局部名字绑定的;数据结构不能动态建立,因为没有运行时的存储分配机制。,2023/11/17,36,某分段式程序运行时的内存划分,2023/11/17,37,每个数据区有一个编号,地址分配时,在符号表中,对每个数据名登记其所属数据区编号及在该区中的相对位置。考虑子程序段:SUBROUTINE SWAP(A,B)T=AA=BB=TRETURNEND,寄存器保护区,返回地址,A,T,B,0,1,a,2023/11/17,38,静态存储分配策略,顺序分配算法(基于调用图)按照程序段出现的先后顺序逐段分配,程序段 区域 021 2236 3754 5571 7294 95104共需要105个存储单元,程序段号/所需数据空间,能用更少的空间么?,2023/11/17,39,分层分配算法,允许程序段之间的覆盖(覆盖可能性分析),程序段 区域6095022 4016323402173114162共需要63个存储单元,思考:如何设计分配算法?,7/80,2023/11/17,40,8.4 栈式存储分配策略,如果过程允许递归某一时刻过程A可能已被自己调用了若干次,但只有最近一次处于执行状态。其余各次等待返回被中断的那次调用必须保存每次调用相应的数据区内容(活动记录)引入一个运行栈让过程的每次执行和过程的活动记录相对应。每调用一次过程,就把该过程的活动记录压入栈中,返回时弹出。假设寄存器top标记栈顶,局部名字x的相对地址为dx,则x的地址为top+dx 或 dxtop,2023/11/17,41,8.4.1 调用序列和返回序列,过程调用和过程返回都需要执行一些代码来管理活动记录栈,保存或恢复机器状态等过程调用和返回是通过在目标代码中生成调用序列和返回序列来实现的 调用序列负责分配活动记录,并将相关信息填入活动记录中 返回序列负责恢复机器状态,使调用过程能够继续执行 调用序列和返回序列常常都分成两部分,分处于调用过程和被调用过程中,2023/11/17,42,8.4.1 调用序列和返回序列,即使是同一种语言,过程调用序列、返回序列和活动记录中各域的排放次序,也会因实现而异设计这些序列和活动记录的一些原则:以活动记录中间的某个位置作为基地址;长度能较早确定的域放在活动记录的中间;一般把临时数据域放在局部数据域的后面,以便其长度的改变不会影响数据对象相对于中间那些域的位置;用同样的代码来执行各个活动的状态保存和恢复;把参数域和可能有的返回值域放在紧靠调用者活动记录的地方。,2023/11/17,43,8.4.1 调用序列和返回序列,调用者和被调用者之间的任务划分,2023/11/17,44,8.4.1 调用序列和返回序列,一种可能的调用序列:调用者计算实参调用者把返回地址和sp的旧值存入被调用者的活动记录中,然后将sp移过调用者的局部数据域和临时变量域,以及被调用者的参数域和状态域被调用者保存寄存器值和其它机器状态信息被调用者初始化其局部数据,并开始执行。,2023/11/17,45,8.4.1 调用序列和返回序列,一种可能的返回序列:被调用者将返回值放入临近调用者的活动记录的地方。利用状态域中的信息,被调用者恢复sp和其它寄存器,并且按调用者代码中的返回地址返回。尽管sp的值减小了,调用者仍然可以将返回值复制到自己的活动记录中,并用它来计算一个表达式。,2023/11/17,46,8.4.1 调用序列和返回序列,过程的参数个数可变的情况函数返回值改成用寄存器传递编译器产生将这些参数逆序进栈的代码被调用函数能准确地知道第一个参数的位置被调用函数根据第一个参数到栈中取第二、第三个参数等等如C语言的printf,2023/11/17,47,过程调用的三地址码:param x1param x2 param xncall p,n,8.4.2 C语言的过程调用和返回,2023/11/17,48,1)每个param xi(i=1,2,n)可直接翻译成如下指令:(i+3)top:=xi(传值)(i+3)top:=addr(xi)(传地址)2)call p,n 被翻译成如下指令:1top:=sp(保护现行sp)3top:=n(传递参数个数)JSR p(转子指令),参数个数,返回地址,内情向量,局部变量,老sp,临时单元,对于par和call产生的目标代码,top sp,调用过程的活动记录,老sp,参数个数,形式单元,形式单元,2023/11/17,49,3)进入过程p后,首先应执行下述指令:sp:=top+1(定义新的sp)1sp:=返回地址(保护返回地址)top:=top+L(新top)L:过程P的活动记录所需单元数,在编译时可确定。,TOP,调用过程的活动记录,返回地址,top,sp,2023/11/17,50,4)过程返回时,应执行下列指令:top:=sp-1(恢复调用前top)sp:=0sp(恢复调用前SP)X:=2top(把返回地址取到X中)UJ 0X(按X返回)UJ为无条件转移指令,即按X中的返回地址实行变址转移,调用过程的活动记录,top,sp,sp,top,2023/11/17,51,8.4.3 栈中的可变长数据,活动记录的长度在编译时不能确定的情况局部数组的大小要等到过程激活时才能确定在活动记录中为这样的数组分别存放数组指针的单元运行时,这些指针指向分配在栈顶的存储空间,2023/11/17,52,8.4.3 栈中的可变长数据,图8.13 访问动态分配的数组,2023/11/17,53,栈式存储分配策略的局限,栈式分配策略在下列情况下行不通:过程活动停止后,局部名字的值还必须维持被调用者的活动比调用者的活动的生存期更长,此时活动树不能正确描绘程序的控制流不遵守栈式规则的有Pascal语言和C语言的动态变量Java禁止程序员自己释放空间,2023/11/17,54,8.5 栈中非局部数据的访问,本节内容无嵌套过程的静态作用域的实现(C语言)包含嵌套过程的静态作用域的实现(Pascal语言)动态作用域的实现(Lisp语言),2023/11/17,55,8.5.1 无过程嵌套的静态作用域,假定:允许过程递归调用、允许过程含有可变数组,但过程定义不允许嵌套,如C语言。过程体中的非局部引用可以直接使用静态确定的地址局部变量在栈顶的活动记录中,可以通过sp指针来访问无须深入栈中取数据,无须访问链过程可以作为参数来传递,也可以作为结果来返回,C语言的函数声明不能嵌套,函数不论在什么情况下激活,要访问的数据分成两种情况:非静态局部变量(包括形式参数),它们分配在活动记录栈顶的那个活动记录中外部变量(包括定义在其它源文件中的外部变量)和静态的局部变量,它们都分配在静态数据区,8.5.1 无过程嵌套的静态作用域,2023/11/17,57,全局数据说明main()main中的数据说明 void R()R中的数据说明void Q()Q中的数据说明,主程序过程Q 过程R,Q的活动记录,主程序活动记录,TOP,R的活动记录,SP,参数个数,返回地址,形式单元,内情向量,局部变量,老SP,临时单元,全局数据区,2023/11/17,58,8.5.2 有过程嵌套的静态作用域,假定语言不仅允许过程的递归调用(和可变数组),而且允许过程定义的嵌套,如PASCAL,PL语言。sortreadarrayexchangequicksortpartition,2023/11/17,59,(1)program sort(input,output)(2)var a:array0.10 of integer;(3)procedure readarray;(4)var i:integer;(5)begin(6)for i:=1 to 9 do read(ai)(7)end;(8)function partition(y,z:integer):integer;(9)var i:integer;(10)begin.(11)end;,program sort procedure readarray function partition(y procedure quicksort,2023/11/17,60,(12)procedure quicksort(m,n:integer);(13)var i:integer;(14)begin(15)if(nm)then begin(16)i:=partition(m,n);(17)quicksort(m,i-1);(18)quicksort(i+1,n)(19)end;(20)end;(21)begin(22)a0:=-9999;a10:=9999;(23)readarray;(24)quicksort(1,9)(25)end.,program sort procedure readarray function partition(y procedure quicksort,2023/11/17,61,8.5.2 有过程嵌套的静态作用域,引入概念:过程嵌套深度sort1readarray2exchange2quicksort2partition3变量的嵌套深度:它的声明所在过程的嵌套深度作为该名字的嵌套深度,2023/11/17,62,8.5.2 有过程嵌套的静态作用域,1.访问链,2023/11/17,63,8.5.2 有过程嵌套的静态作用域,假定过程p的嵌套深度为np,它引用嵌套深度为na的变量a,na np。如何访问a的存储单元?从栈顶的活动记录开始,追踪访问链np-na次。到达a的声明所在过程的活动记录。访问链的追踪用间接操作就可完成。,2023/11/17,64,8.5.2 有过程嵌套的静态作用域,过程p对变量a访问时,a的地址由下面的二元组表示:(np na,a在活动记录中的偏移),2023/11/17,65,8.5.2 有过程嵌套的静态作用域,如何建立访问链假定嵌套深度为np的过程p调用嵌套深度为nx的过程xnp nx的情况x必须在p中进行定义,否则它对于p来说就是不可访问的被调用过程的访问链必须指向调用过程的活动记录的访问链,2023/11/17,66,有过程嵌套的静态作用域,如何建立访问链假定嵌套深度为np的过程p调用嵌套深度为nx的过程xnp nx的情况p和x的嵌套深度分别为1,2,nx 1的外围过程肯定相同追踪访问链np nx+1次,到达了静态包围x和p的且离它们最近的那个过程的最新活动记录所到达的访问链就是x的活动记录中的访问链应该指向的那个访问链,2023/11/17,67,有过程嵌套的静态作用域,2.过程型参数的访问链program param(input,output);procedure b(function h(n:integer):integer);begin writeln(h(2)end b;procedure c;var m:integer;function f(n:integer):integer;begin f:=m+n end f;begin m:=0;b(f)end c;begin cend.,过程作为参数传递时,怎样在该过程被激活时建立它的访问链从b的访问链难以建立f的访问链,激活f,c传递参数f时,像调用f一样为f建立一个访问链,该访问链同f一起传递给b。f被激活时用这个访问链建立f的活动记录的访问链,2023/11/17,68,有过程嵌套的静态作用域,program param(input,output);(过程作为参数)procedure b(function h(begin writeln(h(2)end;procedure c;var m:integer;function f(n:integer)begin f:=m+n end f;begin m:=0;b(f)end c;begin cend.,2023/11/17,69,有过程嵌套的静态作用域,program ret(input,output);(过程作为返回值)var f:function(integer):integer;function a:function(integer):integer;var m:integer;function addm(n:integer):integer;begin return m+n end;begin m:=0;return addm end;procedure b(g:function(integer):integer);begin writeln(g(2)end;begin f:=a;b(f)end.,ret,a,b,addm,被调过程addm活动的生存期超出了调用过程a活动的生存期,栈式存储分配策略失效!,活动树,2023/11/17,70,3.Display表Display表是一个指针数组d,在运行过程中,若当前活动的过程的嵌套深度为i,则di中存放当前的活动记录地址,di-1,di-2,d1 中依次存放着当前活动的过程的直接外层,,直至最外层(主程序)等每一层过程的最新活动地址。这样,嵌套深度为j的变量a存放在由dj所指出的活动记录中。在运行过程中维持一个Display表实现非局部访问比存取链效率要高。,有过程嵌套的静态作用域,2023/11/17,71,Display表的维护(过程不作为参数传递)当嵌套深度为i的过程的活动记录压在栈顶时:(1)在新的活动记录中保存di的值;(2)置di指向新的活动记录。在一个活动结束前,di置成保存的旧值。用Display表如何访问非局部量?1.Display表是一个数组,开始地址用通用 寄存器指出;2.Display表由一组寄存器实现。,有过程嵌套的静态作用域,2023/11/17,72,一个例子,program P;var a,x:integer;procedure Q(b:integer);var i:integer;procedure R(u:integer;var v:integer);var c,d:integer;begin if u=1 then R(u+1,v).v:=(a+c)*(b-d);.end Rbegin.R(1,x);.end Q,procedure S;var c,i:integer;begina:=1;Q(c);.end Sbegina:=0;S;.end.P,主程序P 过程 S 过程 Q 过程 R 过程 R,2023/11/17,73,一、通过静态链访问非局部数据 静态链:指向本过程的直接外层过程的活动记录的起始地址,也称访问链。动态链:指向本过程的调用过程的活动记录的起始地址,也称控制链。,参数个数,返回地址,形式单元,临时单元,内情向量,局部变量,SP0,1,2,动态链(老SP),TOP,静态链,2023/11/17,74,SP,TOP,主程序P,2023/11/17,75,2,a,3,SP,TOP,动态链,静态链,主程序P过程 S,问:第N层过程调用第 N+1层过程,如何确定被调用过程(第 N+1层)的静态链?,答:调用过程(第N层过程)的最新活动记录的起始地址.,0,2023/11/17,76,6,SP,TOP,动态链,静态链,主程序P 过程 S 过程 Q,问:第N层过程调用第 N层过程,如何确定被调用过程(第 N层)的静态链?,答:调用过程(第N层过程)的静态链的值。,返回地址,2023/11/17,77,1,0,2,6,动态链,静态链,主程序P 过程 S 过程 Q 过程 R,12,SP,TOP,返回地址,返回地址,返回地址,2023/11/17,78,1,a,3,6,动态链,静态链,主程序P 过程 S 过程 Q 过程 R 过程 R,12,返回地址,18,TOP,SP,返回地址,返回地址,返回地址,2023/11/17,79,返回地址,1,返回地址,6,动态链,静态链,主程序P 过程 S 过程 Q 过程 R 过程 Q,返回地址,12,返回地址,18,TOP,SP,问:第N层过程调用第 N-x层过程,如何确定被调用过程(第 N-x层)过程的静态链?,答:沿着调用过程(第N层过程)的静态链向前走x步到达的活动记录的静态链的值。,2023/11/17,80,二、通过Display表访问非局部数据,SPn为第n层过程数据区首址,有过程嵌套的静态作用域,SPnSPn-1SP1SP0,SP,2023/11/17,81,令过程R的外层为Q,Q的外层为主程序P,则过程R运行时的DISPLAY表内容为:,2023/11/17,82,问题:当过程P1调用过程P2而进入P2后,P2应如何建立起自己的display表?,2023/11/17,83,问题:当过程P1调用过程P2而进入P2后,P2应如何建立起自己的display表?,l2:P1的最新活动记录的起始地址,P0的最新活动记录的起始地址,P1的display表,P0的最新活动记录的起始地址,l2:P2的最新活动记录的起始地址,P2的display表,从P1的display表中自底而上地取过l2个单元(l2为P2的层数)再添上进入P2后新建立的SP值就构成了P2的display表。,2023/11/17,84,问题:当过程P1调用过程P2而进入P2后,P2应如何建立起自己的display表?,l2-1:P1的最新活动记录的起始地址,P0的最新活动记录的起始地址,P1的display表,P0的最新活动记录的起始地址,P1的最新活动记录的起始地址,P2的display表,从P1的display表中自底而上地取过l2个单元(l2为P2的层数)再添上进入P2后新建立的SP值就构成了P2的display表。,l2:P2的最新活动记录的起始地址,2023/11/17,85,问题:当过程P1调用过程P2而进入P2后,P2应如何建立起自己的display表?,P1的最新活动记录的起始地址,P0的最新活动记录的起始地址,P1的display表,P0的最新活动记录的起始地址,P2的display表,从P1的display表中自底而上地取过l2个单元(l2为P2的层数)再添上进入P2后新建立的SP值就构成了P2的display表。,l2:P2的最新活动记录的起始地址,l2:P2的最新活动记录的起始地址,2023/11/17,86,问题:当过程P1调用过程P2而进入P2后,P2应如何建立起自己的display表?,答案:从P1的display表中自底而上地取过l2个单元(l2为P2的层数)再添上进入P2后新建立的SP值就构成了P2的display表。把P1的display表地址作为连接数据之一(称为全局display地址)传送给P2就能够建立P2的display表。,2023/11/17,87,diaplay表在活动记录中的相对地址d在编译时能完全确定。假定在现行过程中引用了某层过程(令其层次为k)的X变量,那么,可用下面两条指令获得X的地址:LD R1(d+k)SP LD R2 dxR1,嵌套过程语言活动记录,参数个数,返回地址,形式单元,临时单元,内情向量,局部变量,SP 0,1,2,老SP,TOP,Display 表,全局Display,3,d,2023/11/17,88,一个例子,program P;var a,x:integer;procedure Q(b:integer);var i:integer;procedure R(u:integer;var v:integer);var c,d:integer;begin if u=1 then R(u+1,v).v:=(a+c)*(b-d);.end Rbegin.R(1,x);.end Q,procedure S;var c,i:integer;begina:=1;Q(c);.end Sbegina:=0;S;.end.P,主程序P 过程 S 过程 Q 过程 R 过程 R,2023/11/17,89,主程序过程 S,TOP,SP,动态链,2023/11/17,90,返回地址,1,返回地址,6,主程序P过程 S 过程 Q,动态链,TOP,SP,2023/11/17,91,返回地址,1,返回地址,6,主程序P过程 S 过程 Q 过程 R,动态链,返回地址,14,TOP,SP,2023/11/17,92,返回地址,1,返回地址,6,主程序P 过程 S 过程 Q 过程 R 过程 R,动态链,返回地址,14,返回地址,22,TOP,SP,2023/11/17,93,过程调用、过程进入、过程返回,每个par Ti(i=1,2,n)可直接翻译成如下指令:(i+4)TOP:=Ti(传值)(i+4)TOP:=addr(Ti)(传地址),参数个数,返回地址,形式单元,临时单元,内情向量,局部变量,老SP,Display 表,全局Display,TOP,SP,调用过程的活动记录,形式单元,2023/11/17,94,参数个数,返回地址,形式单元,临时单元,内情向量,局部变量,老SP,Display 表,全局Display,2.call P,n 被翻译成:1TOP:=SP(保护现行SP)3TOP:=SP+d(传送现行display地址)4TOP:=n(传递参数个数)JSR(转子指令),过程调用、过程进入、过程返回,TOP,SP,调用过程的活动记录,老SP,全局Display,参数个数,2023/11/17,95,3.转进过程P后,首先定义新的SP和TOP,保存返回地址。4.根据全局display建立现行过程的display:从全局display表中自底向上地取l个单元,在添上进入P后新建立的SP值就构成了P的display。,参数个数,返回地址,形式单元,临时单元,内情向量,局部变量,老SP,Display 表,全局Display,TOP,SP,调用过程的活动记录,返回地址,Display 表,过程调用、过程进入、过程返回,2023/11/17,96,5.过程返回时,执行下述指令:TOP:=SP-1SP:=0SPX:=2TOPUJ 0X,参数个数,返回地址,形式单元,临时单元,内情向量,局部变量,老SP,Display 表,全局Display,TOP,SP,调用过程的活动记录,TOP,SP,过程调用、过程进入、过程返回,2023/11/17,97,动态作用域的实现,从技术上讲,如果作用域策略需要基于程序运行时才能知道的因素,则任何作用域策略都将是动态的。但“动态作用域”这个术语通常是指下面的策略:名字x的引用指向带有x声明的最近被调用的过程中x的这个声明。在某种意义上说,动态作用域规则相对于时间,而静态作用域规则相对于空间。,2023/11/17,98,动态作用域,程序运行时,一

    注意事项

    本文(运行时的存储组织哈工大王宏志.ppt)为本站会员(小飞机)主动上传,三一办公仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知三一办公(点击联系客服),我们立即给予删除!

    温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载不扣分。




    备案号:宁ICP备20000045号-2

    经营许可证:宁B2-20210002

    宁公网安备 64010402000987号

    三一办公
    收起
    展开