【问题标题】:Why are there two ways to multiply arbitrary signed numbers in MIPS?为什么在 MIPS 中有两种方法可以将任意有符号数相乘?
【发布时间】:2019-03-15 20:29:59
【问题描述】:

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

mul $t0 $s0 $s1

或者这个:

mult $s0 $s1
mflo $t0

?

我在网上找到了关于每个含义的不一致答案。乍一看,我希望前者是后者的伪指令。 (甚至有一个网页声称这一点。)但是查看机器代码,mult 似乎是一个有效的 R 型指令(操作码 0),而 mul 有一个非零操作码(0x1c),所以应该t 是 R 类型,即使它包含 3 个寄存器?!

RISC 哲学说要经常使用伪指令,因为我们只有有限的真实指令。但我只是没有想到为什么你需要两种不同的乘法方式。两者都会影响lohi(使用 MARS),因此您可以使用其中任何一个来检查溢出。那么为什么会出现冗余呢?为什么不告诉大家一直使用mul

【问题讨论】:

  • (在有人问之前:我不是学生。我是一名试图理解、阻止学生提问的老师。)
  • “我在网上找到了关于每个含义的不一致答案。” 我建议按照 MIPS32™ 程序员架构第二卷的内容:在查看任何在线答案之前,MIPS32™ 指令集会说。
  • 仅供参考,为此目的有Computer Science Educators
  • @phuclv:这是关于如何将知识传授给学生的问题。这个问题不属于那里,这是一个关于 MIPS 乘法指令的严格技术问题,而不是关于如何教学生这些指令。 (为什么不告诉大家一直使用 mul? 是关于混淆在线搜索结果,而不是关于如何教学生)

标签: assembly mips instruction-set risc


【解决方案1】:

mul 不是伪指令。它确实修改hilo 寄存器,mult 所做的。它们是指令集中的不同真实指令。

一般来说,我们有a = b * c

由于将两个 32 位数字相乘产生 64 位结果,因此在一般情况下,我们使用 mult,然后使用 mflo 获取结果的低 32 位,使用 mfhi 获取结果的高 32 位。这允许更高的准确性,但需要额外的指令 [或两条] 来获得结果。

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

考虑一个简单的程序:

    .text
    .globl  main
main:
    mul     $v0,$a0,$a1
    mult    $v1,$a2
    mflo    $v0

现在,如果我们使用mars 组装它,我们会得到:

00400000:   70851002    mul     $v0,$a0,$a1
00400004:   00660018    mult    $v1,$a2
00400008:   00001012    mflo    $v0

请注意,我们在第 3 行有一个真正的 mflo 指令。如果 mul 是一个伪操作,mars 将 [必须] 在 @ 之间注入一个 mflo $v0 987654340@ 和mult


更新:

这很有趣。你是对的,它不是一个伪指令。 (你会在组装时看到它,如果是的话。)但是当我使用 MARS 时,mul 和 mult 都会修改 hi 和 lo。也许这是一个 MARS 错误?

可能。 spim 修饰 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

在该文档中,mul 指令将更改 hi 或 lo 列为副作用。

在我看过的一些文档中[我不记得是哪个],它指出[对于旧/真实硬件],您必须在 multmflo(例如nop)。模拟器不需要这个。

作为一种好的做法,我可能不会在 mult 之后依赖 lo/hi 的有效期太久,并且 对于 mul 完全不依赖它们,所以,对于课堂作业,这有点争议。

看看qemu 做了什么会很有趣。它比spimmars [我更喜欢] 更难使用,但可能更接近实际硬件的功能。

【讨论】:

  • 这很有趣。你是对的,它不是一个伪指令。 (你会在组装时看到它,如果是的话。)但是当我使用 MARS 时,mul 和 mult 都会修改 hi 和 lo。也许这是一个 MARS 错误?
  • 原始 MIPS (R2000) 有一个乘法单元,它只是松散地连接到整数内核的其余部分。 (见doc.lagout.org/electronics/doc/mips/See%20mips%20run.pdf)。由于乘法(或除法)需要 许多 个周期,并且他们希望整数寄存器修改由 5 级流水线中的 WB 级完成,因此必须付出一些努力。具有读/写lo/hi 的特殊指令让mult 变得超级慢,并且除了读取输入之外不必与普通寄存器文件交互。 (运行mult后,不允许修改几个insns!)
  • 后来的 MIPS 可以在 GP 整数寄存器上互锁指令(并且具有更长的流水线和更高性能的乘法单元)能够有效地引入新的乘法指令,从而提高了代码密度并减少了 @987654357 的开销@指令。
  • @AdamSmith - 这确实很有趣。 《数字设计与计算机体系结构》一书(Harris 和 Harris 合着)一书将mul 称为伪指令。
猜你喜欢
  • 2023-03-03
  • 1970-01-01
  • 2013-11-05
  • 1970-01-01
  • 1970-01-01
  • 2011-10-18
相关资源
最近更新 更多