为什么在MIPS中有两种方法可以将任意有符号数相乘?

时间:2018-10-10 20:43:47

标签: mips risc

如果您需要在MIPS中将两个任意带符号的数字相乘,是否有理由更喜欢:

mul $t0 $s0 $s1

或者这个:

mult $s0 $s1
mflo $t0

我在网上发现关于每个人的含义不一致的答案。乍一看,我希望前者是后者的伪指令。 (甚至还有一个网页都声称这一点。)但查看机器代码,看来mult是有效的R型指令(操作码0),而mul的操作码非零(0x1c)因此,即使它包含3个寄存器,也不应该是R型吗?!

由于我们只有有限的真实指令,因此RISC哲学认为经常使用伪指令。但是我只是没有想到为什么您需要两种不同的方式进行乘法。两者都会影响lohi(使用MARS),因此您可以使用两者之一检查溢出。那么为什么要冗余呢?为什么不告诉所有人始终使用mul

1 个答案:

答案 0 :(得分:1)

mul不是伪指令。它不会修改hi所做的lomult寄存器。它们是指令集中不同的 real 指令。

通常,我们有a = b * c

由于将两个32位数字相乘会产生64位结果,因此通常情况下,我们使用mult,然后使用mflo获得结果的低32位,而使用{ {1}}。这样可以提高准确性,但需要额外的一条或多条指令来获得结果。

如果我们只关心乘法结果的低32位(例如,数组索引计算),则可以使用mfhi,它允许结果与参数位于不同的寄存器中(在< em>单指令)

考虑一个简单的程序:

mul

现在,如果我们使用 .text .globl main main: mul $v0,$a0,$a1 mult $v1,$a2 mflo $v0 进行组装,我们将得到:

mars

请注意,我们在第3行有一条真实的00400000: 70851002 mul $v0,$a0,$a1 00400004: 00660018 mult $v1,$a2 00400008: 00001012 mflo $v0 指令。如果 mflo是伪操作,则mul将[必须]插入一个marsmflo $v0行之间的mul


更新:

  

这很有趣。而且您认为它不是伪指令是正确的。 (如果组装的话,就会看到它。)但是当我使用MARS时,mul和mult都会同时修改hi和lo。也许这是一个MARS错误?

可能。 mult 修改hi和lo。

经过进一步的思考,考虑到最初的mips CPU内核时代(大约1985年)以及它们拥有的门数量极为有限,这似乎是合乎逻辑的。

但是,今天真正的mips内核仍然存在。该公司是“ MIPS Technologies,Inc”,到2017年仍然存在。

[AFAICT]公司的ISA参考手册在这里有副本:https://s3-eu-west-1.amazonaws.com/downloads-mips/documents/MD00086-2B-MIPS32BIS-AFP-6.06.pdf

在该文档中,spim指令没有 not 列表,将hi或lo更改为副作用。

some 文档中,我见过[我不记得是哪个],它指出[对于旧的/真实的硬件],您必须在mul之间插入一条中间指令。和mult(例如mflo)。模拟器不需要这样做。

作为一种好的做法,在nop之后,我可能不太会依赖lo / hi的有效期,而对于mult并非完全依赖它们。 ,对于课堂作业来说,这是有争议的。

看看mul的作用会很有趣。它比qemuspim [我更喜欢]难使用,但可能更接近实际的硬件功能。