第1页:第九章运行时存储空间组织
第九章运行时存储空间组织
第2页:9.1目标程序运行时的活动
9.1目标程序运行时的活动
- 以Pascal为例,假定程序由若干个过程组成
- 过程(procedure)定义
- 一个过程的活动指的是该过程的一次执行
- 过程P一个活动的生存期,指的是从执行该过程体第一步操作到最后一步操作之间的操作序,包括执行P时调用其它过程花费的时间
- 过程可以是递归的
第3页:9.1目标程序运行时的活动(续)
9.1目标程序运行时的活动(续)
t)(2)varaarray[0..10]ofinteger;(3)procedurereadarray;(4)vari:integer;(5)begin(6)fori:=1to9doread(a[i])(7)end;(8)functionpartition(y,z:integer):integer;(9)vari:integer;(10)begin......(11)end;program sortprocedure readarrayfunction partition(yprocedure quicksort
第4页:9.1目标程序运行时的活动
9.1目标程序运行时的活动
integer);(13)vari:integer;(14)begin(15)if(n>m)thenbegin(16)i:=partition(m,n);(17)quicksort(m,i-1);(18)quicksort(i+1,n)(19)end;(20)end;(21)begin(22)a[0]:=-9999;a[10]:=9999;(23)readarray;(24)quicksort(1,9)(25)end.program sortprocedure readarrayfunction partition(yprocedure quicksort
第5页:参数传递
参数传递
- 过程定义
- procedure add(x,y:integer; var z:integer)beginz:=x+y;end;
- 过程是模块程序设计的主要手段,同时也是节省程序代码和扩充语言的主要途径。
- 过程调用add(a,b,c);
第6页:一.传地址
一.传地址
- 参数传递方式
- 把实在参数的地址传递给相应的形式参数
- 方法:
- 调用段预先把实在参数的地址传递到被调用段可以拿到的地方;
- 程序控制转入被调用段之后,被调用段首先把实在参数的地址抄进自己相应的形式单元中;
- 过程体对形式参数的引用域赋值被处理成对形式单元的间接访问。
- PASCAL的变量参数方式
第7页:一.传地址(续)
一.传地址(续)
- integer; var n
- integer);var i:integer;begini:=m;m:=n;n:=i;end
- m
- =j1;
- n
- =j2;
- i
- =m↑;
- m↑
- = n↑;
- swap(a,b)
- 把a,b的地址送到已知单元j1和j2中
- n↑:=i;
第8页:二.得结果
二.得结果
- 参数传递方式
- 传地址的一种变形
- 方法:
- 每个形参对应两个形式单元,第一个形式单元存放实参地址,第二个单元存放实参的值。
- 在过程体中对形式参数的任何引用或赋值都看作对它的第二个单元的直接访问。
- 过程完成返回前把第二个单元的内容存放到第一个单元所指的实参单元中。
- 有些Fortran采用这种方式;
第9页:三.传值
三.传值
- 参数传递方式
- 把实在参数的值传递给相应的形式参数
- 方法:
- 调用段预先把实在参数的的值计算出来并放在被调用段可以拿到的地方;
- 被调用段开始工作时,首先把实参的值抄入形式参数相应的单元;
- 被调用段中,象引用局部数据一样引用形式单元。
- PASCAL的值参数
第10页:四.传名
四.传名
- 参数传递方式
- 过程调用的作用相当于把被调用段的过程体抄到调用出现的地方,但把其中任一出现的形式参数都替换成相应的实参。
- 方法:
- 在进入被调用段的之前不对实在参数预先进行计值,而是让过程体中每当使用到相应的形式参数时才逐次对它实行计值(或计算地址)。因此,通常把实在参数处理成一个子程序(称为参数子程序),每当过程体中使用到相应的形式参数时就调用这个子程序。
第11页:四.传名(续)
四.传名(续)
integer;PROCEDURE P(B:integer)…varA:integer;BEGINA:=0;B:=B+1;A:=A+B;END;BEGINA:=2;TA:=0;A:=A+1;TA:=TA+A;write(A);ENDBEGINA:=2;P(A);write(A);END
第12页:四.传名
四.传名
- …procedure P(w,x,y,z);beginy := y*w;z := z+x;endbegina := 5;b := 3;P(a+b,a-b,a,a);write(a);end传值:传地址:得结果:传名:542777
第13页:过程是否允许递归
过程是否允许递归
- 过程是否允许递归?
- 当控制从一个过程的活动返回时,对局部名称的值如何处理?
- 过程是否允许引用非局部名称?
- 过程调用时如何传递参数;过程是否可以做为参数被传递和做为结果被返回?
- 存储空间可否在程序控制下进行动态分配?
- 存储空间是否必须显式地释放?
第14页:9.2运行时存储器的划分
9.2运行时存储器的划分
- 一个目标程序运行所需的存储空间包括:
- 存放目标代码的空间
- 存放数据项目的空间
- 存放程序运行的控制或连接数据所需单元(控制栈)
第15页:9.2运行时存储器的划分(续)
9.2运行时存储器的划分(续)
第16页:9.2.2活动记录
9.2.2活动记录
- 假定语言的特点为
- 允许过程递归调用、允许过程含有可变数组,但过程定义不允许嵌套,如C语言。
- 活动记录
- 运行时,每当进入一个过程就有一个相应的活动记录累筑于栈顶。此记录含有连接数据、形式单元、局部变量、局部数组的内情向量和临时工作单元等。
第17页:9.2.2活动记录(续)
9.2.2活动记录(续)
- dx[SP]dx
- 变量X相对于活动记录起点的地址,在编译时可确定。参数个数返回地址形式单元临时单元内情向量局部变量SP
- 012老SPTOP
- 每个过程的活动记录内容(非嵌套语言)
第18页:返回地址
返回地址
- 动态链
- 指向调用该过程前的最新活动记录地址的指针。
- 静态链
- 指向静态直接外层最新活动记录地址的指针,用来访问非局部数据。静态链动态链形式单元临时单元内情向量局部变量SP
- 012返回地址TOP
- 每个过程的活动记录内容(嵌套语言)
第19页:局部数据区
局部数据区
- 局部变量、内情向量、临时工作单元(如存放对表达式求值的结果)。静态链动态链形式单元临时单元内情向量局部变量SP
- 012返回地址TOP
- 每个过程的活动记录内容
第20页:局部数据区(续)
局部数据区(续)
- 时数据空间的大小则必须采用动态分配方法。允许递归过程和动态申请释放内存。
- 栈式动态分配
- 堆式动态分配9.2.3存储分配策略
第21页:局部数据区
局部数据区
- ,YCOMMON /C/A,B…ENDSUBROUTINE SUB1…real X,ZCOMMON /C/A1,B1…END9.3静态存储管理
第22页:9.3静态存储管理
9.3静态存储管理
- FORTRAN程序的特点
- 整个程序所需数据空间的总量在编译时完全确定,每个数据名的地址可以静态地进行分配。
- 由于每个FORTRAN程序段可以独立编译,运行前由装入程序把各段连成可运行的整体。通常按数据区组织存储:
- 每个程序段定义一个局部数据区,用来存放程序段中未出现在COMMON里的局部名的值。
- 每个公用块定义一个公用数据区,用来存放公用块里各个名字的值。
第23页:9.3静态存储管理(续)
9.3静态存储管理(续)
- 寄存器保护区返回地址形式单元临时变量数组简单变量01A
第24页:9.3静态存储管理
9.3静态存储管理
考虑子程序段:SUBROUTINE SWAP(A,B)T=AA=BB=TRETURNEND寄存器保护区返回地址ATB01a
第25页:9.4一个简单栈式存储分配
9.4一个简单栈式存储分配
- 假定语言的特点为
- 允许过程递归调用、允许过程含有可变数组,但过程定义不允许嵌套,如C语言。
- 活动记录
- 运行时,每当进入一个过程就有一个相应的活动记录累筑于栈顶。此记录含有连接数据、形式单元、局部变量、局部数组的内情向量和临时工作单元等。
第26页:9.4一个简单栈式存储分配(续)
9.4一个简单栈式存储分配(续)
- idR(){R中的数据说明}…voidQ(){Q中的数据说明}
- 主程序→过程Q→过程RQ的活动记录主程序活动记录TOP
- R的活动记录SP
- 参数个数返回地址形式单元内情向量局部变量老SP临时单元全局数据区
第27页:9.4一个简单栈式存储分配
9.4一个简单栈式存储分配
第28页:9.4一个简单栈式存储分配(续)
9.4一个简单栈式存储分配(续)
过程调用的四元式序列:par T1par T2…par Tncall P,n9.4.2C的过程调用、过程进入、数组空间分配和过程返回
第29页:9.4一个简单栈式存储分配
9.4一个简单栈式存储分配
- 如下指令(i+3)[TOP]
- = Ti(传值)(i+3)[TOP]:=addr(Ti)(传地址)2)call P,n被翻译成:1[TOP]:=SP (保护现行SP)3[TOP]:=n (传递参数个数)JSR P (转子指令)参数个数返回地址形式单元内情向量局部变量老SP临时单元对于par和call产生的目标代码如下:TOP
第30页:9.4一个简单栈式存储分配(续)
9.4一个简单栈式存储分配(续)
- 首先应执行下述指令
- SP:=TOP+1(定义新的SP)1[SP]:=返回地址(保护返回地址)TOP:=TOP+L(新TOP)L:过程P的活动记录所需单元数,在编译时可确定。参数个数返回地址形式单元内情向量局部变量老SP临时单元TOP
第31页:9.4一个简单栈式存储分配
9.4一个简单栈式存储分配
- 应执行下列指令
- TOP:=SP-1(恢复调用前TOP)SP:=0[SP](恢复调用前SP)X:=2[TOP](把返回地址取到X中)UJ 0[X](按X返回)参数个数返回地址形式单元内情向量局部变量老SP临时单元调用过程的活动记录TOP
第32页:9.5嵌套过程语言的栈式实现
9.5嵌套过程语言的栈式实现
- PASCAL
- 非局部名字的访问的实现
- 静态链和活动记录
- 嵌套层次显示表display
- 过程调用、过程进入、过程返回
第33页:嵌套过程语言的栈式实现
嵌套过程语言的栈式实现
- PASCAL
- 非局部名字的访问的实现
- 静态链和活动记录
- 嵌套层次显示表display
- 过程调用、过程进入、过程返回
第34页:9.5嵌套过程语言的栈式实现
9.5嵌套过程语言的栈式实现
- 假定语言不仅允许过程的递归调用(和可变数组),而且允许过程定义的嵌套,如PASCAL,PL语言。
第35页:9.5嵌套过程语言的栈式实现(续)
9.5嵌套过程语言的栈式实现(续)
- 一个PASCAL过程
- 过程头;说明段(由一系列的说明语句组成);begin执行体(由一系列的执行语句组成);end9.5嵌套过程语言的栈式实现
第36页:一个在子程序B1中说明
一个在子程序B1中说明
- 允许同一个标识符在不同的过程中代表不同的名字。
- 名字作用域规则--"最近嵌套原则"
- 如果B2是B1的一个内层子程序且B2中对标识符X没有新的说明,则原来的名字X在B2中仍然有效。如果B2对X重新作了说明,那么,B2对X的任何引用都是指重新说明过的这个X。
第37页:PASCAL嵌套过程作用域示例
PASCAL嵌套过程作用域示例
- real;…procedure P1var B:boolean;…begin…endprocedure P2var A:integer;…begin…endbegin…endA(real)B(real)B(bool)A(integr)
第38页:嵌套过程语言的栈式实现
嵌套过程语言的栈式实现
- PASCAL
- 非局部名字的访问的实现
- 静态链和活动记录
- 嵌套层次显示表display
- 过程调用、过程进入、过程返回
第39页:9.5.1非局部名字的访问的实现
9.5.1非局部名字的访问的实现
- 主程序的层次为0;在i层中定义的过程,其层次为i+1;(层数,偏移量)
- 过程运行时,必须知道其所有外层过程的当前活动记录的起始地址。
第40页:嵌套过程语言的栈式实现
嵌套过程语言的栈式实现
- PASCAL
- 非局部名字的访问的实现
- 静态链和活动记录
- 嵌套层次显示表display
- 过程调用、过程进入、过程返回
第41页:嵌套过程语言的栈式实现(续)
嵌套过程语言的栈式实现(续)
- 图;var a, x
- integer;procedure Q(b: integer);var i: integer;procedure R(u: integer; var v:integer);var c, d: integer;beginif u=1 then R(u+1, v)......v:=(a+c)*(b-d);......end {R}begin......R(1,x);......end {Q}procedure S;var c, i:integer;begina:=1;Q(c);......end {S}begina:=0;S;......end. {P}主程序P
第42页:嵌套过程语言的栈式实现
嵌套过程语言的栈式实现
- 静态链
- 指向本过程的直接外层过程的活动记录的起始地址,也称存取链。
- 动态链
- 指向本过程的调用过程的活动记录的起始地址,也称控制链。参数个数返回地址形式单元临时单元内情向量局部变量SP
第43页:嵌套过程语言的栈式实现(续)
嵌套过程语言的栈式实现(续)
第44页:嵌套过程语言的栈式实现
嵌套过程语言的栈式实现
- 个数)8c9i10SP
- TOP
- 动态链静态链
- 主程序P
- 过程S?第N层过程调用第N+1层过程,如何确定被调用过程(第N+1层)过程的静态链?A:调用过程(第N层过程)的最新活动记录的起始地址.
第45页:嵌套过程语言的栈式实现(续)
嵌套过程语言的栈式实现(续)
- 个数)8c9i10SP
- TOP
- 动态链静态链
- 主程序P
- 过程S
- 过程Q511返回地址120131(形参个数)14b(形参)15i16?第N层过程调用第N层过程,如何确定被调用过程(第N层)过程的静态链?A:调用过程(第N层过程)的静态链的值。
第46页:嵌套过程语言的栈式实现
嵌套过程语言的栈式实现
- 个数)8c9i10动态链静态链
- 主程序P
- 过程S
- 过程Q
- 过程R511返回地址120131(形参个数)14b(形参)15i161117返回地址1811192(形参个数)20u(形参)21v(形参)22c23d24SP
- TOP
第47页:嵌套过程语言的栈式实现(续)
嵌套过程语言的栈式实现(续)
- 个数)8c9i10动态链静态链
- 主程序P
- 过程S
- 过程Q
- 过程R
- 过程R511返回地址120131(形参个数)14b(形参)15i161117返回地址1811192(形参个数)20u(形参)21v(形参)22c23d241725返回地址2611272(形参个数)28u(形参)29v(形参)30c31d32TOP
- SP
第48页:嵌套过程语言的栈式实现
嵌套过程语言的栈式实现
- 个数)8c9i10动态链静态链
- 主程序P
- 过程S
- 过程Q
- 过程R
- 过程Q511返回地址120131(形参个数)14b(形参)15i161117返回地址1811192(形参个数)20u(形参)21v(形参)22c23d24TOP
- SP
- 1725返回地址260271(形参个数)28b(形参)29i30?第N层过程调用第N-x层过程,如何确定被调用过程(第N-x层)过程的静态链?A:沿着调用过程(第N层过程)的静态链的向前走x步到达的活动记录的静态链的值。
第49页:嵌套过程语言的栈式实现(续)
嵌套过程语言的栈式实现(续)
- PASCAL
- 非局部名字的访问的实现
- 静态链和活动记录
- 嵌套层次显示表display
- 过程调用、过程进入、过程返回
第50页:嵌套过程语言的栈式实现
嵌套过程语言的栈式实现
- 当进入一个过程后,在建立其活动记录区的同时建立一张嵌套层次显示表diaplay,把diaplay表作为活动记录的一部分。
第51页:嵌套过程语言的栈式实现(续)
嵌套过程语言的栈式实现(续)
令过程R的外层为Q,Q的外层为主程序为P,则过程R运行时的DISPLAY表内容为:
第52页:嵌套过程语言的栈式实现
嵌套过程语言的栈式实现
问题:当过程P1调用过程P2而进入P2后,P2应如何建立起自己的display表?P0P1P2P0P2P1P0P1P2
第53页:嵌套过程语言的栈式实现(续)
嵌套过程语言的栈式实现(续)
问题:当过程P1调用过程P2而进入P2后,P2应如何建立起自己的display表?P0P1P2l2:P1的最新活动记录的起始地址P0的最新活动记录的起始地址P1的display表P0的最新活动记录的起始地址l2:P2的最新活动记录的起始地址…………P2的display表从P1的display表中自底而上地取过l2个单元(l2为P2的层数)再添上进入P2后新建立的SP值就构成了P2的display表。
第54页:嵌套过程语言的栈式实现
嵌套过程语言的栈式实现
问题:当过程P1调用过程P2而进入P2后,P2应如何建立起自己的display表?P0P2P1l2-1:P1的最新活动记录的起始地址P0的最新活动记录的起始地址P1的display表P0的最新活动记录的起始地址P1的最新活动记录的起始地址…………P2的display表从P1的display表中自底而上地取过l2个单元(l2为P2的层数)再添上进入P2后新建立的SP值就构成了P2的display表。l2:P2的最新活动记录的起始地址
第55页:嵌套过程语言的栈式实现(续)
嵌套过程语言的栈式实现(续)
问题:当过程P1调用过程P2而进入P2后,P2应如何建立起自己的display表?P0P1P2P1的最新活动记录的起始地址P0的最新活动记录的起始地址P1的display表P0的最新活动记录的起始地址…………P2的display表从P1的display表中自底而上地取过l2个单元(l2为P2的层数)再添上进入P2后新建立的SP值就构成了P2的display表。l2:P2的最新活动记录的起始地址l2: P2的最新活动记录的起始地址
第56页:嵌套过程语言的栈式实现
嵌套过程语言的栈式实现
- 把P1的display表地址作为连接数据之一传送给P2就能够建立P2的display表。P0P1P2P0P2P1P0P1P2
第57页:嵌套过程语言的栈式实现(续)
嵌套过程语言的栈式实现(续)
- 量那么,可用下面两条指令获得X的地址:LD R1(d+k)[SP]LD R2dx[R1]嵌套过程语言活动记录参数个数返回地址形式单元临时单元内情向量局部变量SP
- 012老SPTOP
- Display表全局Diaplay3d…
第58页:嵌套过程语言的栈式实现
嵌套过程语言的栈式实现
- 图;var a, x
- integer;procedure Q(b: integer);var i: integer;procedure R(u: integer; var v:integer);var c, d: integer;beginif u=1 then R(u+1, v)......v:=(a+c)*(b-d);......end {R}begin......R(1,x);......end {Q}procedure S;var c, i:integer;begina:=1;Q(c);......end {S}begina:=0;S;......end. {P}主程序P
第59页:嵌套过程语言的栈式实现(续)
嵌套过程语言的栈式实现(续)
- 地址62(全局display)70(形参个数)809510主程序
- 过程Sc11i12TOP
- SP
- 动态链
第60页:嵌套过程语言的栈式实现
嵌套过程语言的栈式实现
- 地址62(全局display)70(形参个数)809510主程序P
- 过程S
- 过程Qc11i12动态链513返回地址149(全局display)151(形参个数)16b(形参)170181319i20TOP
- SP
第61页:嵌套过程语言的栈式实现(续)
嵌套过程语言的栈式实现(续)
- 地址62(全局display)70(形参个数)809510主程序P
- 过程S
- 过程Q
- 过程Rc11i12动态链513返回地址149(全局display)151(形参个数)16b(形参)170181319i201321返回地址2218(全局display)232(形参个数)24u(形参)25v(形参)2602713282129c30d31TOP
- SP
第62页:嵌套过程语言的栈式实现
嵌套过程语言的栈式实现
- 地址62(全局display)70(形参个数)809510主程序P
- 过程S
- 过程Q
- 过程R
- 过程Rc11i12动态链513返回地址149(全局display)151(形参个数)16b(形参)170181319i201321返回地址2218(全局display)232(形参个数)24u(形参)25v(形参)2602713282129c30d31TOP
- SP
- 2132返回地址3327(全局display)342(形参个数)35u(形参)36v(形参)3703813393240c41d42
第63页:嵌套过程语言的栈式实现(续)
嵌套过程语言的栈式实现(续)
- PASCAL
- 非局部名字的访问的实现
- 静态链和活动记录
- 嵌套层次显示表display
- 过程调用、过程进入、过程返回
第64页:嵌套过程语言的栈式实现
嵌套过程语言的栈式实现
- PDisplay表全局Diaplay1.每个par Ti(i=1,2,…n)可直接翻译成如下指令(i+4)[TOP]:= Ti(传值)(i+4)[TOP]:=addr(Ti)(传地址)过程调用、过程进入、过程返回TOP
- SP
- 调用过程的活动记录……形式单元
第65页:嵌套过程语言的栈式实现(续)
嵌套过程语言的栈式实现(续)
- PDisplay表全局Diaplay2.call Pn被翻译成:1[TOP]:=SP(保护现行SP)3[TOP]:=SP+d(传送现行display地址)4[TOP]:=n(传递参数个数)JSR(转子指令)过程调用、过程进入、过程返回TOP
- SP
- 调用过程的活动记录……老SP全局Diaplay参数个数
第66页:3.转进过程P后
3.转进过程P后
- 首先定义新的SP和TOP,保存返回地址。4.根据"全局display"建立现行过程的display:从全局display表中自底向上地取l个单元,在添上进入P后新建立的SP值就构成了P的display。参数个数返回地址形式单元临时单元内情向量局部变量老SPDisplay表全局DiaplayTOP
- SP
- 调用过程的活动记录……返回地址Display表
第67页:5.过程返回时
5.过程返回时
- 执行下述指令
- TOP:=SP-1SP:=0[SP]X:=2[TOP]UJ 0[X]参数个数返回地址形式单元临时单元内情向量局部变量老SPDisplay表全局DiaplayTOP
第68页:嵌套过程语言的栈式实现
嵌套过程语言的栈式实现
- PASCAL
- 非局部名字的访问的实现
- 静态链和活动记录
- 嵌套层次显示表display
- 过程调用、过程进入、过程返回
第69页:嵌套过程语言的栈式实现(续)
嵌套过程语言的栈式实现(续)
- 建立一个总的运行时的diaplay表(而不是每个过程的活动记录中都有一个),它记录正被调用执行的过程及其所有外层过程的活动记录的起始地址。通过这个diaplay访问数据。
- 在各过程活动记录之间保留一条"静态链SL",它主要用于由层次大的过程调用层次小的过程后返回时,恢复调用前的display内容。(这时,调用返回后,执行一条UDIS指令)
第70页:返回地址RA
返回地址RA
- 动态链DL,指向过程调用者的活动记录起始地址
- 静态链SL,指向过程的直接外层过程活动记录起始地址静态链指针SL形式单元局部变量数组SP
- 012返回地址RATOP
- 动态链指针DL3
第71页:返回地址RA(续)
返回地址RA(续)
var x,y: integer;...procedure P1;var i,j:integer;...procedure P11(a,b:integer);...begin...end;begin...call P11(i,j);...end;procedure P2;var s,t:integer;...procedure P21;begin...end;begin...call P1...end;begin...call P2;...end.
第72页:返回地址RA
返回地址RA
- 0152主程序P
- 过程P2
- 过程P1
- 过程P11DisplayP的活动记录P2的活动记录RA10SL(0)11DL(5)12i13j14102P1的活动记录RA15SL(10)16DL(10)17a18b19P11的活动记录153
第73页:返回地址RA(续)
返回地址RA(续)
- RA10SL(0)11DL(5)12i13j14RA15SL(10)16DL(10)17a18b1901102主程序P
- 过程P2
- 过程P1
- 过程P11P的活动记录P2的活动记录P1的活动记录P11的活动记录15352Display
第74页:返回地址RA
返回地址RA
var x,y: integer;...procedure P1;var i,j:integer;...procedureP11(a,b:integer);...begin...end;begin...call P11(i,j);...end;procedure P2;var s,t:integer;...procedure P21;var u,v:integer;...begin...call P1...end;begin...call P21...end;begin...call P2;...end.
第75页:返回地址RA(续)
返回地址RA(续)
- 0152主程序P
- 过程P2
- 过程P21
- 过程P1DisplayP的活动记录P2的活动记录RA10SL(5)11DL(5)12u13v14103P21的活动记录RA15SL(0)16DL(10)17i18j19P1的活动记录152
第76页:返回地址RA
返回地址RA
- RA10SL(0)11DL(5)12u13v14RA15SL(0)16DL(10)17i18j1901主程序P
- 过程P2
- 过程P21
过程P1P的活动记录P2的活动记录P21的活动记录P1的活动记录10352Display152由层次大的过程调用层次小的过程后返回时,要根据“静态链SL”恢复调用前的display内容(通过执行UDIS指令实现)udis:beginh1:=a;h2:=l;h3:=base;repeatdisplay[h1]:=h3;h1:=h1-1;h3:=s[h3+2]until h1=h2end;h3:=s[h3+1]
第77页:返回地址RA(续)
返回地址RA(续)