我应该回答这个问题。经过一些研究后,它说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
答案 0 :(得分:6)
我不知道MIPS甚至有正确的subi
指令(虽然有些环境可能会为它实现一个宏)。
由于您正在减去立即值,因此您可以将其否定为addi
指令:
addi $r1, $r2, -42 ; equivalent to subi $r1, $r2, 42
立即操作数是一个二进制补码值,这意味着它完全能够成为负数,并且二进制补码的工作方式意味着您可以以无符号方式添加负数并且与减去相同的结果(因为你换行)。
例如,16位二进制补码中的-42
是无符号值65494
。当您在65536处添加50
和65494
时,最终会得到:
50
+ 65494 (ie, -42)
-----
65544 (overflow, so
- 65536 we wrap at 64K)
-----
8 (identical to "50 - 42")
答案 1 :(得分:1)
在ISA设计的硬件/机器代码级别,MIPS没有subi
/ subiu
指令。 这很有意义,因为MIPS没有FLAGS寄存器。
没有一个进位标志可以记录加一个负数或减去一个正数之间的差异,就像许多其他体系结构(x86,ARM和许多其他不那么RISCy的体系结构)一样。因此,花费额外的操作码(以及用于对其进行解码的晶体管)是没有道理的。
添加否定立即数不会更改addi
/ subi
的符号溢出检测。当您将两个具有相同符号的数字相加而结果具有相反的符号时,就会出现符号溢出。或在减去z = x - y
时,如果x和y具有相反的符号,而z
和x
具有相反的符号,则表示减法溢出(您希望subi
陷在其中。){ {1}}是立即执行的,因此将其实现为y
会使z = x + y_negated
的溢出检测工作。
当然,通常情况下,您(或C编译器)只会使用addi
/ addiu
,因为您不希望陷入陷阱,而是希望将回绕作为签名溢出行为,除非您使用subiu
进行编译。
在asm源代码级别,为方便起见,可以将其实现为伪指令,正如您在NIOS II手册中所引用的。 (或者甚至是宏,在不支持伪指令的汇编器上。)
硬件-fsanitize=undefined-behavior
/ subi
保存指令的唯一时间是您想添加subiu
/减去32768
。 (请注意,NIOS II手册指出-32678
支持subi
范围内的立即数,这与正常的带符号16位2的补码-32767 .. 32768
相反)
2的补码中最大的负数是一个异常,其负数需要额外的一位才能正确表示。即-32768 .. 32767
在16位立即数中溢出到-(0x8000)
。任何将0x8000
实现为伪指令的体面的汇编程序都应对此进行警告,或警告对于subi
/ addi
使用有符号16位范围之外的立即数。
addiu
将其立即数符号扩展为32位,与addiu
相同。 “未签名”是错误的称呼。 Why would we use addiu instead of addi?。对于2的补码机,有符号和无符号加法是相同的二进制操作。匹配C签名溢出的命名类型是未定义的行为,但请注意,未定义不会 require 错误。将addi
视为经过溢出检查的签名加法,只有在您特别需要时才使用它。
有趣的事实:addi
和其他布尔值对立即数进行零扩展,因此ori
可以使用li $t0, val
或{扩展为val = -32768 .. 65535
的单个指令。 {1}}。
答案 2 :(得分:-1)
同意以上内容。阐述一些环境。提出我在这件事上看到的小真理。发展我自己的(阴谋)理论。
该关键字位于倒数第二行(包括版权在内的第三行)-它是伪指令。这始终是班上一个常见的问题,因此值得澄清。一些仿真器(看着您的火星)将其视为一条真正的指令,而其他一些仿真器(qtspim-感到羞耻!)甚至都不会去编译它。
虽然我从来没有找到一个很好的例子,但据推测它太简单了,不能相互转换,因此是多余的。他们试图遵循“简单的设计原则”。对我来说,这有点麻烦了,因为已经有很多伪指令可以简单地重做其他命令。分支伪指令分解为2条命令,这将需要2条甚至3条命令。因此,这一点没有什么不同。那“ li”之类的东西呢。我的意思是,来吧,那只是addiu。没有其他的。如果他们加上这一点,那么就没有任何借口。老实说,为了简单和对称起见,我认为添加它会更容易。但是,那么,每个人最喜欢的MIPS考试问题将会如何?
那是没有SUBI的真正原因。对于笨拙的老ASM程序员来说,他们需要攻读本科生。