MARS 模拟器有 PC-relative 寻址是指字节数而不是字数?
MARS Simulator has PC-relative addressing refer to the number of bytes instead of words?
我目前正在阅读 David Patterson 和 John Hennesy 的书,标题为:"Computer Organisation and Design - 4th Edition"。在某些方面,这本书说:
Since all MIPS instructions are 4 bytes long, MIPS stretches the distance of the branch by having PC-relative addressing refer to the number of
words to the next instruction instead of the number of bytes.
我一读到它,就去 MARS Simulator 看看它在实践中的表现。令我惊讶的是,我观察到 $pc 寄存器不遵循该规则并且始终存储字节内存地址。
$pc 寄存器在执行位于指令地址中的以下指令之前不应该是这样的吗?
Instruction Address | $pc Content
|
0x00400000 | 0x00100000
0x00400004 | 0x00100001
0x00400008 | 0x00100002
.... | ....
换个角度看:PC的低2位固定为0
。
根据您的提议,高2位将固定为0
。 jr $ra
或其他 jump-to-register 指令也必须 left-shift 寄存器而不是简单地设置 $pc = function-pointer
.
(否则差异在体系结构上是可见的,并且必须将代码作为数据访问,反之亦然,以便从数据地址转换为同一字的代码地址。)
正如 Jester 指出的那样,$pc
是指向指令字的普通指针,就像 MIPS 用于处理 一样。 MIPS 使用 byte-addressable 内存,但字加载必须对齐(直到 MIPS32r6)。因此 $pc
每次使用时都会增加 4 而不是 缩放 4。
实际设计所需的唯一缩放比例是分支 (I-type) 和跳转 (J-type) 的立即数。请参阅 How to Calculate Jump Target Address and Branch Target Address? 了解其工作原理。这只是您将立即数位连接到加法器的哪个位置的问题,而将较低的位留为零。而且它只发生在这些指令的解码中;其他一切都只适用于普通字节地址。
... stretches the distance of the branch by having PC-relative addressing refer to the number of words to the next instruction instead of the number of bytes.
这句话只有的意思是:
地址X存储的指令0x1000nnnn(b nnnn
)会跳转到地址X+4+4*nnnn
的指令,不会跳转到地址[=12=的指令].
这句话没有提到 PC 寄存器及其值本身。
I observed that the $pc
register doesn't follow that rule and has always the byte memory address stored.
Shouldn't the $pc
register be something like this before the execution of the below instructions located in the instruction addresses?
这里的问题是:$pc
寄存器到底是什么?
在某些 CPU(如 ARM)上,有一些指令可以用 MIPS 汇编语言写成 addu $t0,$t0,$pc
。谈论这样的 CPU 很容易回答这个问题:
如果addu $t0,$t0,$pc
指令被执行,$pc
寄存器的值是将被添加到$t0
的值。
在真正的 MIPS CPU(不是 MIPS 仿真器)上,PC 寄存器是某种内存(30 位锁存器),可以保存 30 位信息。
但是,当谈到存储在某些内存中的信息时,我们必须定义如何解释这些信息:
位 10000111
可以解释为 135(无符号)、87(BCD)、-121(二进制补码)、-120(一个补码)、-7(符号和绝对值)、SOME_ENUM_CONSTANT
(枚举),-0.09、0.7、1.35(各种浮动和 fixed-point 变体)...
明确定义PC寄存器中的0000...011100
位指向地址为0x70的指令。但是,如果这个值必须写成 PC=0x1C
或 PC=0x70
.
则没有定义
因此一些 MIPS 仿真器可能显示 $pc=0x400000
而另一个可能显示 $pc=0x100000
因为 PC 寄存器中的 相同 值!
不过,我认为(几乎)所有 MIPS 仿真器都会显示 $pc=0x400000
,因为用户对指令指向的地址感兴趣。
我目前正在阅读 David Patterson 和 John Hennesy 的书,标题为:"Computer Organisation and Design - 4th Edition"。在某些方面,这本书说:
Since all MIPS instructions are 4 bytes long, MIPS stretches the distance of the branch by having PC-relative addressing refer to the number of words to the next instruction instead of the number of bytes.
我一读到它,就去 MARS Simulator 看看它在实践中的表现。令我惊讶的是,我观察到 $pc 寄存器不遵循该规则并且始终存储字节内存地址。
$pc 寄存器在执行位于指令地址中的以下指令之前不应该是这样的吗?
Instruction Address | $pc Content
|
0x00400000 | 0x00100000
0x00400004 | 0x00100001
0x00400008 | 0x00100002
.... | ....
换个角度看:PC的低2位固定为0
。
根据您的提议,高2位将固定为0
。 jr $ra
或其他 jump-to-register 指令也必须 left-shift 寄存器而不是简单地设置 $pc = function-pointer
.
(否则差异在体系结构上是可见的,并且必须将代码作为数据访问,反之亦然,以便从数据地址转换为同一字的代码地址。)
正如 Jester 指出的那样,$pc
是指向指令字的普通指针,就像 MIPS 用于处理 一样。 MIPS 使用 byte-addressable 内存,但字加载必须对齐(直到 MIPS32r6)。因此 $pc
每次使用时都会增加 4 而不是 缩放 4。
实际设计所需的唯一缩放比例是分支 (I-type) 和跳转 (J-type) 的立即数。请参阅 How to Calculate Jump Target Address and Branch Target Address? 了解其工作原理。这只是您将立即数位连接到加法器的哪个位置的问题,而将较低的位留为零。而且它只发生在这些指令的解码中;其他一切都只适用于普通字节地址。
... stretches the distance of the branch by having PC-relative addressing refer to the number of words to the next instruction instead of the number of bytes.
这句话只有的意思是:
地址X存储的指令0x1000nnnn(b nnnn
)会跳转到地址X+4+4*nnnn
的指令,不会跳转到地址[=12=的指令].
这句话没有提到 PC 寄存器及其值本身。
I observed that the
$pc
register doesn't follow that rule and has always the byte memory address stored.Shouldn't the
$pc
register be something like this before the execution of the below instructions located in the instruction addresses?
这里的问题是:$pc
寄存器到底是什么?
在某些 CPU(如 ARM)上,有一些指令可以用 MIPS 汇编语言写成 addu $t0,$t0,$pc
。谈论这样的 CPU 很容易回答这个问题:
如果addu $t0,$t0,$pc
指令被执行,$pc
寄存器的值是将被添加到$t0
的值。
在真正的 MIPS CPU(不是 MIPS 仿真器)上,PC 寄存器是某种内存(30 位锁存器),可以保存 30 位信息。
但是,当谈到存储在某些内存中的信息时,我们必须定义如何解释这些信息:
位 10000111
可以解释为 135(无符号)、87(BCD)、-121(二进制补码)、-120(一个补码)、-7(符号和绝对值)、SOME_ENUM_CONSTANT
(枚举),-0.09、0.7、1.35(各种浮动和 fixed-point 变体)...
明确定义PC寄存器中的0000...011100
位指向地址为0x70的指令。但是,如果这个值必须写成 PC=0x1C
或 PC=0x70
.
因此一些 MIPS 仿真器可能显示 $pc=0x400000
而另一个可能显示 $pc=0x100000
因为 PC 寄存器中的 相同 值!
不过,我认为(几乎)所有 MIPS 仿真器都会显示 $pc=0x400000
,因为用户对指令指向的地址感兴趣。