2

我应该回答这个问题。经过一些研究,它说 add 和 sub 具有相同的操作码,并且仅在功能领域有所不同。这是答案还是其他?

更新

Nios II CPU 手册中提供了它:

subi
subtract immediate
Operation: rB ← rA – σ (IMMED)
Assembler Syntax: subi rB, rA, IMMED
Example: subi r8, r8, 4
Description: Sign-extends the immediate value IMMED to 32 bits, subtracts it from the value of rA and then
            stores the result in rB.
Usage: The maximum allowed value of IMMED is 32768. The minimum allowed value is
–32767.
Pseudo-instruction:
© March 2009
subi is implemented as addi rB, rA, -IMMED
4

3 回答 3

10

我不知道 MIPS 甚至正确的subi指令(尽管某些环境可能会为它实现宏)。

由于您要减去一个立即数,您只需将它的否定提供给addi指令:

addi $r1, $r2, -42     ; equivalent to subi $r1, $r2, 42

直接操作数是一个二进制补码值,这意味着它完全可以成为负数,而二进制补码的工作方式意味着您可以以无符号方式添加一个负数,并给出与减法相同的结果(因为您环绕)。

例如,-42在 16 位二进制补码中是无符号值65494。当您在 65536 添加5065494环绕时,您最终会得到:

     50
+ 65494 (ie, -42)
  -----
  65544 (overflow, so
- 65536  we wrap at 64K)
  -----
      8 (identical to "50 - 42")
于 2012-08-16T06:27:33.357 回答
3

在 ISA 设计的硬件/机器代码级别,MIPS 没有subi/subiu指令。 这是有道理的,因为 MIPS 没有 FLAGS 寄存器。

没有进位标志可以记录添加负数或减去正数之间的差异,就像在许多其他架构(x86、ARM 和许多其他较少 RISCy 架构)上一样。因此,花费额外的操作码(以及解码它的晶体管)是没有意义的。

添加否定立即数不会改变/的有符号溢出检测。当您将两个具有相同符号的数字相加并且结果具有相反的符号时,您会得到有符号溢出。或者在减法时,如果 x 和 y 有相反的符号,并且有相反的符号,那就是减法溢出(你想要捕获的地方。) 是直接的,所以将它实现为使' 的溢出检测工作。addisubiz = x - yzxsubiyz = x + y_negatedaddi

当然,通常您(或 C 编译器)只会使用addiu/subiu因为您不想陷入陷阱,并且宁愿将环绕作为签名溢出行为,除非您使用-fsanitize=undefined-behavior或其他东西进行编译。


在 asm 源代码级别,为方便起见,它可以实现为伪指令,正如您在 NIOS II 手册中的引用所示。(或者甚至作为一个宏,在不支持伪指令的汇编器上。)

subi硬件/保存指令的唯一时间subiu是您想要加32768/ 减-32678。(注意 NIOS II 手册指出subi支持-32767 .. 32768范围内的立即数,与正常有符号的 16 位 2 的补码相反-32768 .. 32767

2 的补码中最负数是异常的,它的负数需要额外的位才能正确表示。即-(0x8000)溢出到0x800016 位立即数。任何subi作为伪指令实现的体面的汇编程序都应该对此发出警告,或者警告不要对addi/使用带符号的 16 位范围之外的立即数addiu


addiu将其立即数符号扩展为 32 位,与 . 相同addi。“未签名”是用词不当。 为什么我们要使用 addiu 而不是 addi?. 对于 2 的补码机器,有符号和无符号加法是相同的二进制运算。命名类型匹配 C 有符号溢出是未定义的行为,但请注意未定义不需要故障。将addi其视为溢出检查的签名加法,并且仅在您特别需要时才使用它。

有趣的事实:ori其他布尔值对它们的立即数进行零扩展,因此可以使用或li $t0, val扩展为仅一条指令。val = -32768 .. 65535addiu $t0, $zero, signed_int16ori $t0, $zero, uint16

于 2018-08-21T08:04:02.687 回答
-1

同意楼上。说明一些环境。提出我在这件事上看到的小真理。发展我自己的(阴谋)理论。

关键字在倒数第二行(第三行,包括版权)中-它是伪指令。这一直是一个常见的课堂问题,所以值得说清楚。一些仿真器(看着你的火星)将其视为真正的指令,而其他仿真器(qtspim - 耻辱!)甚至不会费心编译它。

虽然我从来没有找到一个很好的例子,但据说将一个转换为另一个太简单了,所以它是多余的。他们试图遵循“简单的设计原则”。对我来说,这有点崩溃,因为已经有很多伪指令代表对其他命令的简单修改。分支伪指令分解为 2 个命令,这将需要 2 个甚至 3 个命令。所以,这一款也不例外。那么像“li”这样的东西呢?我的意思是,来吧,那只是补充。没有其他的。如果他们加上这一点,那就没有任何借口了。老实说,为了简单和对称,我认为添加它会更容易。但是,每个人最喜欢的 MIPS 考试问题会发生什么?

这就是没有 SUBI 的真正原因。让陈旧的 ASM 程序员与本科生搞混。

于 2018-08-21T07:17:47.627 回答