我正在学习 MIPS 32 位。我想问一下,在存储字的情况下,为什么我们在将 16 位偏移量(在单周期数据路径中)发送到 ALU 之前要对其进行签名?
6 回答
我不确定它现在是否对您有帮助,但无论如何我都会发布它。
让我们从一个非常笼统的意义上考虑,C++ 中的指令数组,即 A[0],A[1],A[2] .....任何两条指令之间的“比喻”距离是 1 UNIT。
让我们把这个类比为 MIPS。在 MIPS 中,比喻每条指令由“1 UNIT”分隔,然而,在 MIPS 中,1 UNIT = 4 Bytes。每条指令都是 4 字节长,这就是为什么当从一条指令移动到另一条指令时,PC 会增加 4,即 PC+4。因此,指令 i 和指令 i+2 之间的差距“象征性地”是 2 但实际上是 2*4=8 即 PC+4+4
回到分支指令中指定的偏移量,偏移量表示距下一条指令(分支之后的指令)的“象征性”距离。因此,为了获得“真实”距离,偏移量将乘以 4。这就是我们被指示将偏移量“符号扩展”2 位到“LEFT”的原因,因为,将任何二进制值左移n 位导致将该值乘以 2^n。在我们的例子中 2^2 = 4
所以分支指令的实际目标地址是PC+4+4*Offset。
希望这可以帮助。
听起来 16 位偏移量是带符号的 2 的补码,即它可以是正数或负数。
将其转换为 32 位时,需要将最高有效位复制到高 16 位,以保留符号信息。
在 32 位机器的硬件中,大多数 ALU 采用 32 位输入,所有寄存器都是 32 位寄存器。
要处理您的数据,它必须是 32 位宽,这就是我们进行 SIGN 扩展的原因,但是另一种方法是零扩展,但是在处理立即数和偏移量时使用 SIGN 扩展以保留 2 中的符号补充。
我认为您在这里的概念有些错误。
您认为进入 ALU 的 5 位实际上进入寄存器内存以选择 32[2^5] 个寄存器中的一个。
每个寄存器本身都是 32 位的。因此,要将偏移量添加到寄存器值,您需要将其符号扩展为 32 位。
ALU 操作总是在 MIPS 的单周期数据路径中的两个相同大小的寄存器之间进行。
据我所知,在加载或存储指令中,偏移值被添加到临时寄存器中的值中,如 temp。寄存器是 32 位的,不能进行 16 位和 32 位的加法运算,值是符号扩展的。
符号扩展发生在例如 M68xxx 机器的情况下,仅在加载地址寄存器的情况下。在数据寄存器的情况下不是这样。
有例如
movea.w addr,a0
move addr,d0
addr:
dc.w $FFFF
在数据寄存器加载的情况下导致 $0000FFFF,在地址寄存器加载的情况下导致 $FFFFFFFF。
为了理解这一点,构建带符号负表示的二补码 $FFFF,将数字扩展到 32 位并重做二补码,找到 32 位的相应表示。
干杯和亲切的问候,斯蒂芬·S。