基地址寄存器

基地址寄存器

基地址 寄存器 是指在基数位移定址系统中用于存放基地址的寄存器。 在执行指令时,通过将基地址寄存器中的基地址 与指令地址部的相对地址相加,得出实际地址。

加载

在加载过程中,假设当前正在执行的过程的静态层号为 i,则当前过程调用记录前部的区头地址表共有 i+1 个单元。当需要访问本过程中说明的简单变量或形式参数时,只需将 SP 加上该变量的位移地址即可获得该变量所分配的存储单元地址。而对于在嵌套深度为 k (k < i) 的过程中说明的变量或形式参数,其存储单元地址为 (SP + k) + 该变量的位移地址。尽管如此,由于具体的机器指令格式限制,仍需根据具体情况进一步讨论这个问题。

机器指令格式是一个与硬件相关的问题。以假想的 计算机 为例,涉及内存的机器指令的汇编指令格式为 OP R1, d2(R2),其中 R2 是与第二个操作数相关的基地址寄存器,d2 是第二个操作数的位移地址。在形成实际地址时,基地址寄存器中的地址与位移地址相加 ((R2) + d2) 得到第二个操作数的地址。通常情况下,机器指令中的位移区域位数较少(如 12 位),这种指令格式的设计目的是为了缩短每条指令的长度。然而,这给编译程序形成有效的指令带来了一定的难度。如果指令的位移区域仅占 12 位,则该指令只能访问相对于基地址的位移在 4095 个单元范围内的存储单元。对于超过 4095 个单元的相对地址,该指令无法进行存取。要存取相对于基地址的位移在 4095 个单元之外的存储单元中的内容,程序必须先修改基地址寄存器中的地址。由此可知,一个过程的数据区从存储分配的角度看是一个整体,但从具体指令的编址角度看,过程数据区可以划分为多个相互连接的部分。每个部分的大小与具体机器指令格式有关。为了访问某个部分内的存储单元,必须首先将该部分的首地址放入基地址寄存器,然后按照相对于该部分首地址的位移量访问该存储单元。

在代码生成阶段,r3 被保留作为一个特殊用途的 寄存器 。例如,可以指定 r3 作为基地址寄存器。由于硬件特性,r3 还被用来存放转子指令执行后的下一条指令地址。当程序流程进入一个过程时,运行时刻执行的过程数据区初始化 子程序 会将该过程数据区的首地址发送到基地址寄存器 r3。也就是说,当过程主体开始执行时,当前过程调用记录的第 0 块首地址已经在 r3 中。如果要访问的存储单元位于当前过程调用记录的第 0 块,则代码生成程序可以直接使用 r3 和保存在符号表登记项中的位移地址形成指令。否则,必须修改基地址寄存器的值,即将该存储单元所属块的首地址取到基地址寄存器。这项工作可以通过一个名为 CHECKBP 的专用子程序来完成。

运行时刻 子程序 CHECKBP 在工作时需要两个参数:变量所属过程的嵌套深度和所属块号。变量所属过程的嵌套深度可以从符号表中该标识符所属的登记项中获取。变量所属块的块号也可以从保存在符号表登记项的相对地址中计算得出,通过逻辑乘法截取出该相对地址的高位变量,即是所属块号。块号与每块长度相乘,再加上该过程调用记录的首地址,就可以得到块首址:

块首址 = 过程调用记录首址 + 块号 * 块长度

其中,过程调用记录首址可以根据变量所属过程的静态嵌套深度从当前过程调用记录的区头地址表中获取。

为了减少频繁调用运行 子程序 CHECKBP,应该注意到程序变量访问的就近原则:程序员在编写程序时,往往会将一段程序中使用的变量集中在一起进行说明。这就使得在同一段程序中访问的变量往往集中在同一个块或者集中在本过程数据区的第 0 块。由于假想 计算机 的 寄存器 已经被分配完毕,可以在运行程序工作区中设置两个工作单元 SP 和 BP。SP 存放当前正在执行的过程的调用记录的首地址,BP 存放当前访问变量所属数据块的首地址。运行子程序 CHECKBP 并不会将变量所属块的首地址直接发送到 r3,而是将其地址发送到运行时刻的工作单元 BP。运行时刻 子程序 CHECKBP 的代码编写工作对于读者来说并不困难。

为了了解运行时刻 r3、SP 和 BP 的情况,在代码生成程序中设置了三个工作变量 X、Y 和 Z。X、Y 和 Z 各有两个域:levelno 和 blockno,分别记录了运行时刻 r3、SP 和 BP 中地址对应的过程嵌套深度和块号。进入过程时,运行时刻的过程数据区初始化子程序将当前过程调用记录的首地址发送到 r3、SP 和 BP。相应的代码生成程序动作必须将此过程的嵌套深度和第 0 块标记 0 发送给变量 X、Y 和 Z。之后,每当代码生成程序要生成访问运行栈存储单元的指令时,都必须检查所要访问的变量的所属块首址是否已经在 寄存器 r3 中。如果该地址不在 r3 中,而在工作单元 BP(或工作单元 SP)中,则生成将 BP 值发送到 r3 的指令(或将 SP 值发送到 r3 的指令)。否则,代码生成程序生成转向运行时刻 子程序 CHECKBP 的转子指令,以便将所属块的首地址取到工作单元 BP,然后再生成将 BP 值发送到 r3 的指令。这些工作可以由子程序 CHECKr3 完成,读者不难编写该子程序的代码。需要注意的是,与 REGVALUE 工作区及 REGSTATE 工作区类似,代码生成程序的工作变量 X、Y 和 z 必须正确反映运行时刻 r3、SP 和 BP 中地址对应的过程嵌套深度和块号。

设定

基地址寄存器的设定是在程序中完成的。基地址 寄存器 的设定方法有两种,下面以 12 号寄存器为例进行说明:

示例一

```

BEGIN1 START

XXXX USING*, 12

SAVE(14, 12)

LR12, 15

在此示例中,15 号寄存器包含程序的起始地址(即 XXXX)。将 15 号寄存器的内容复制到 12 号寄存器,使基地址寄存器 12 将 XXXX 作为基地址放置。

示例二

```

BEGIN2 START

SAVE(14, 12)

USING*, 12

YYYY BALR 12

在这个例子中,BALR 指令将下一条指令的地址存储在 12 号 寄存器 中,而 USING 指令指示汇编程序以当前值为基础地址进行汇编。因此,基地址寄存器 12 将 YYYY 作为基地址放置。但需要注意的是,在此处不能将 BALR 和 USING 指令的位置颠倒,否则会出现错误。

参考资料

  1. 基于基地址寄存器映射的数据高速缓存设计研究 知网空间 2024-09-16
  2. 寄存器 博客园 2024-09-16
  3. 基地址 知网空间 2024-09-16