我从来源发现,Rs 和 Rt 的内容被视为 mul 的有符号整数。
而对于 mulu,Rs 和 Rt 的内容被视为无符号整数。
但是每次我执行 mul 和 mulu 时,它们似乎都会给出相同的结果。
li $t0 -2
li $t1 2
mul $s0, $t0, $t1
mulu $s1, $t0, $t1
$s0 和 $s1 中都存储 -4。 我的问题是,Rs 和 Rt 被视为有符号/无符号整数是什么意思,以及 mul 和 mulu 如何以不同方式对待 Rt 和 Rs? 在什么具体情况下我可以看到 mul 和 mulu 给出不同的结果? 我正在使用 MARS 模拟器。 谢谢。如果您对这个问题有任何困惑,请询问我。
MIPS 有一个乘法单元,可以给出准确的答案:它需要 32 位 × 32 位 → 64 位,从数学上来说,这就是乘法的工作原理。
在火星上,
mul
是真正的指令。它产生在 hi
和 lo
中捕获的 64 位结果,并且还获取该结果的低 32 位并将其存储到 rd
中。 (此指令不是第一个 MIPS 的一部分;它是后来添加的。)如果执行此指令,您将看到 hi
和 lo
在 MARS 中受到影响,以及 rd
。
而在 MARS 上
mulu
是伪指令。它还生成在 hi
和 lo
中捕获的 64 位结果,并获取其中的低 32 位并将其存储到“rd
”中(我在这里用引号括起来,b/c 这个 mulu
是不是真正的指令,因此没有实际的寄存器字段),但由 MARS 汇编器实现为 2 个实际指令,如下所示:首先是 multu rs,rt
,然后是 mflo rd
。如果您在 MARS 中查看此指令的机器代码,您将看到此扩展为 2 条指令,如果您执行,您将首先看到 hi
和 lo
,然后是 rd
受到影响。
旧版 MIPS 通过两个操作数
mult
和 multu
仅提供 32 × 32 → 64 个结果,64 位结果在特殊 hi
和 lo
寄存器中捕获(这样乘法可能需要多个周期)并且不会干扰可以为并行运行的其他指令提供服务的整数寄存器文件),因此您可以考虑尝试这些,例如mult $t0, $t1
和multu $t0, $t1
。
以有符号形式完成的 2 × -2(例如使用
mult
)的答案是 0xffffffff 0xfffffffc,并且该值可以安全地截断为 32 位(或更少),因为该值只是 -4,适合较小的值位数1.
无符号中没有 -2,因此这些位被解释为一个大正数,fffffffe16又名 4,294,967,29410。
以无符号(使用
multu
)完成的 2 × 0xfffffffe 的答案是 0x00000001 0xfffffffc,并且这个值(正如您对无符号 × 无符号所期望的那样是正值)不适合 32 位2,所以当强制时在没有检查的情况下被截断,我们有溢出,也就是说:一个错误的答案。
低 32 的位模式与有符号和无符号的位模式相同,但由于溢出,这相对没有意义 - 当然,它对硬件很有用,因为这一事实意味着两种乘法类型共享很多电路。
1 我们如何知道这个 64 位值适合 32 位?上部结果要么全 0,要么全 1,并且这些位也与下部结果的符号位(最高位,MSB)匹配。
我们如何在 MIPS 上对此进行运行时测试?取出低 32 位结果并将其算术右移 31 个位置(仅在 LSB 位置保留符号位)。使用算术移位会在右移时复制符号位,因此我们将根据原始符号获得全 0 或全 1 的值。然后将移位后的值与高 32 位进行比较,如果相等,则 64 位值可以用 32 位表示,如果不相等,则无法用 32 位表示。
2 我们如何知道这个 64 位数字不适合 32 位?由于无符号数据类型的所有位都是幅度位(即无符号位),因此如果结果的高 32 位非零,则该数字需要超过 32 位来表示,并且仅保留低 32 位位将截断结果,就像对 232 取模一样。
去mulus99玩吧,非常值得信赖的好地方