运行时存储空间组织Word下载.docx
《运行时存储空间组织Word下载.docx》由会员分享,可在线阅读,更多相关《运行时存储空间组织Word下载.docx(30页珍藏版)》请在冰豆网上搜索。
五、递归
进程的递归挪用,当一个进程在没有退出当前的活动时,又开始其新的活动称递归挪用:
直接递归挪用:
procedurep
begin
P()
end
间接递归挪用:
Q()
procedureQ
p()
六、作用域
若是变量在一进程中概念并只在该进程中被引用,称之为局部变量,不然为全局变量。
二、参数的四种传递方式
例PROCEDUREP(X,Y,Z)PROCEDUREq()
beginbegin{挪用段}
Y:
=y+1A:
=2;
Z:
=Z+XB:
=3;
end{p}P(A+B,A,A)
PRINTA
end
一、传地址
每一个形参寄存相应的实参的地址,对形参的任何访问都按间接地址访问(访问的对象是实参的地址)。
挪用段实参单元被挪用段形参单元
T
5
X
Y
<
T>
A
238
A>
B
3
Z
因为Z,Y均为A的地址,因此PRINTA的值为8。
二、得结果
每一个形参对应两个单元:
一个寄存实参的地址,一个寄存实参的值,在进程体中对形参的任何引用或赋值,都看成对它的第二单元直接访问(结果间接存入第一单元(地址))。
X
Y:
=Y+1
2+1
Y
23
Z:
=Z+X
2+5
Z
27
因为Z,Y的第一单元均寄存A的地址,而第二单元均寄存A的值,因此PRINTA的值为7。
3、传值
每一个形参对应一个单元,寄存相应的实参的值,在进程体中对
形参能够直接访问(计算只是在进程体进行,不改变实参的值)。
Y=Y+1=3
23
Z=Z+X=7
27
因为无法将Z的值传给A对应的单元,因此PRINTA的值为2。
4、传名
把被挪用段中所有形参都换成相应的实参,直接访问实参。
实参形参
A:
=A+1;
-Y:
=y+1;
=A+A+B-Z:
239
因用实参的值,直接执行进程体,因此PRINTA的结果为9。
三、存储空间组织必需考虑的问题
一、进程是不是许诺递归?
二、当操纵从一个进程的活动返回时,对局部名称值的如何处置?
3、进程是不是许诺引用非局部名称?
4、进程调历时如何传递参数;
进程是不是能够作为参数被传递和作为结果被返回?
五、存储空间可否在程序操纵下进行动态分派?
六、存储空间是不是必需显示地释放?
第二节运行时存储器的安排
一、运行时存储器的安排
目标代码
过程调用时使用。
用于动态数据申请
静态数据
栈
↓
↑
堆
二、活动记录
进程在一次执行中所需要的存储空间(数据空间)。
TOP
临时单元
动态数组
连接数据
内情向量
局部变量
形式单元
静态链
动态链
返回地址
SP
老SP(动态链)
说明:
一、SP为现行进程活动记录的基地址,作为变址器的基地址。
二、连接数据
用于保留挪用段中挪用语句下一条代码地址
指向挪用该进程前的挪用段最新活动记录地址的指针,用
于返回挪用段的活动记录(数据空间)
指向直接外层最新活动记录地址指针,访问非局部数据。
3、内情向量
用于保留动态数组的大体信息。
4、形式单元
寄存相应实参的地址或数值。
三、存储分派策略
一、静态分派
在编译时对所有数据对象分派固定大小的存储单元,且在运行时始终不变。
对程序语言的要求:
不许诺进程递归挪用;
不含可变体积的数组。
二、动态分派
在编译时不能确信其数据在存贮空间的位置及所要求数据空间的大小。
即无法确信所需数据空间大小和位置。
动态数组
数组所需数据空间大小在运行时才能确信
动态分派的实现
在编译时生成一些代码,在运行时动态申请和释放空间。
3、堆式动态分派
用户程序中申请和回收空间
第三节静态存储分派
在编译时可确信数据单元的地址(相对地址)
一、局部数据区的安排(布局)
临时变量
数组
简单变量
确定大小的数组
寄存器保护区
图局部数据区
二、编译程序的地址分派
编译程序的地址分派工作,是对符号表中变量名字填入地址(数据区序号,相对地址),在生成目标代码时变量用地址表示。
三、临时变量的地址分派
若是两个临时变量的作用域不相交,那么它们共用一个存储单元。
大多临时变量只被定值一次,引用一次,利用栈寄存临时变量地址,K为栈指针。
例:
X:
=A*B-C*D+E*F四元式序列如下:
四元式临时变量名地址
(*,A,B,T1)T1a
(*,C,D,T2)T2a+1
(-,T1,T2,T3)T3a
(*,E,F,T4)T4a+1
(+,T3,T4,T5)T5a
(:
=,T5,,X)
临时变量地址代真后的四元式序列如下:
四元式K(初值为a)
(*,A,B,$a)a+1
(*,C,D,$(a+1))a+2
(-,$a,$(a+1),$a)a+1
(*,E,F,$(a+1))a+2
(+,$a,$(a+1),$a)a+1
(:
=,$a,,X)a+1
第四节简单的栈式分派
一、对程序语言的要求
一、许诺进程递归挪用;
二、许诺利用可变数组;
3、不许诺嵌套的进程概念。
二、进程挪用利用数据区的特点
一、非递归挪用
一个进程只对应一个数据区(活动记录),挪用一个进程,利用该进程的数据区,该进程终止后才可能被再次挪用,因此能够利用同一数据区。
二、递归挪用
一个进程可能对应多个活动记录,挪用一进程,需要为进程的该次活动申请数据区(活动记录),假设这次活动未终止,该进程又被挪用(开始一次新的活动),需为这次活动再申请另一块数据区(活动记录)。
3、进程挪用的特点
先挪用的后返回(退出),挪用进程时,先申请一个数据空间(活动记录),假设该次活动未终止,又被调动,再申请一活动记录…,当一次活动终止时,回收该次的活动记录,因为先挪用的后返回,活动记录回收为:
先分派的后回收,因此,活动记录的申请和回收用栈的方式。
全局数听说明
Main()
{Main中的数听说明
}Q的活动记录
voidR()TOP→
{R中的数听说明R的活动记录
挪用Q进程SP→
…Q的活动记录
}
…
voidQ()Main的活动记录
{Q中的数听说明
挪用R进程
…全局数据
}
栈式数据空间
其中:
TOP始终指向栈顶单元,SP指向现行进程活动记录的起始地址(基地址)。
三、活动记录的数据安排
TOP→
临时工作单元
参数个数
SP→
老SP
连接数据(用于进程终止返回挪用段):
一、老SP值,挪用段最新活动记录的基地址。
二、返回地址,挪用段代码地址,用于返回挪用段。
在目标代码表示为X[SP](变址访问)。
四、进程挪用、进程返回时的代码
一、编译时如何为目标程序进行动态分派
对进程挪用语句时生成一系列”申请空间”代码,当目标程序运行这些代码时,便在运行栈顶申请空间,一样,在进程挪用返回时,运行编译生成的“回收”代码,即能够回收空间。
申请活动记录(数据空间)和回收空间要紧体此刻活动记录基地址SP的转变,目标代码用变址方式X[SP],即(SP(基地址)+数据的相对地址)就能够够访问相应的数据空间。
进入进程前的代码
中间代码:
目标代码
parT1(i+3)[TOP]:
=Ti
ParT2
或(i+3)[TOP]:
=addr(Ti)
ParTn1[TOP]:
SP
Callp,n3[TOP]:
n
JSRP
进入进程后先执行
SP:
=TOP+1;
1[SP]:
=返回地址
TOP:
=TOP+1
Return(E)返回语句的代码
把当前活动记录基地址改成挪用段最新活动记录基地址,
依照返回地址,代码运行转到该地址。
=SP-1
=0[SP]老SPTOP→
X:
=2[TOP]返回地址返回地址被挪用段活动记录
UJ0[X]SP→老SP
挪用段活动记录
第五节嵌套式进程语言的栈式实现
一、嵌套式进程语言的特点
一个进程的活动期间,如安在本进程活动记录中引用包围它的某一外层进程的数据。
现在SP仅指向本进程活动记录基地址。
解决方式:
一、编译识别每一个进程概念时,为其编上层次号
二、引用包围它的某一外层进程的数据,要依照数据所在的层次确信该外层进程最新活动记录基地址。
3、能够用两种方法记录外进程最新活动记录的基地址(静态链和display表)。
例(P258图)
层次变量作用域
0ProgramP;
Vara,x:
integer;
1ProcedureQ(b:
integer)
Vari:
2ProcedureR(u:
Varv:
integer);
Varc,d:
integer
Begin
Ifu=1thenR(u+1,v)
……u,v,
V:
=(a+c)*(b-d);
c,db
………i
end{R}
begin
…a
R(1,x);
x
end{Q}
procedureS;
varc,i:
1begin
a:
=1;
引用0层的a
Q(c);
c,i
end
begin
=0;
S;