我对add和addu之间的区别感到困惑。
MIPS指令参考说:
我的理解是使用带有签名操作数的add和带有无符号操作数的addu。
但是让我们考虑这个例子(只有6位):
overflow | V 1 | 1 1 1 <- carry | 1 1 1 1 0 1 + | 1 1 1 1 1 0 = ----------------- | 1 1 1 0 1 1
这是我的理由:
现在我的问题是:
答案 0 :(得分:12)
指令名称具有误导性。如果不希望陷阱溢出,请使用addu
作为有符号和无符号操作数。
如果由于某种原因需要溢出陷阱,请使用add
。大多数语言都不希望有符号溢出的陷阱,因此add
很少有用。
答案 1 :(得分:5)
如果您使用带符号的数字,如果您希望在结果溢出时生成陷阱,则应使用add
。
如果使用无符号数,则应始终使用addu
并通过将结果与任一数字进行比较来检查加法的溢出(如果结果小于操作数,则加法会溢出)。 / p>
这里有一段代码,说明如何检查无符号加法中的溢出:
li $a1, 0xFFFF0FFF
li $a2, 0x00010000
addu $a3, $a1, $a2 # This unsigned addition overflows (set $a3 to $a1+$a2)
bgt $a1, $a3, overflowed
bgt $a1, $a2, overflowed
# If you get here, unsigned addition did not overflow
# your code goes here...
overflowed:
# If you get here, unsigned addition overflowed
# your code goes here...
答案 2 :(得分:3)
OVERFLOW在问题中声明 NOT ,这个进位不是溢出位,在给定的例子中没有OVERFLOW,溢出时是:
MSB1 = 1 && MSB2 = 1 && MSBofRESULT = 0
OR
MSB1 = 0 && MSB2 = 0 && MSBofRESULT = 1
坚持使用add
它会标记溢出,并且示例中的进位(不是溢出)不会打扰你。 addu
做同样的事情,除了没有例外。
答案 3 :(得分:2)
基本上两个操作码都是带符号加法。因此在MIPS中它们使用31位来存储数据,最大数量是(2加到31)-1并保留1位来存储符号数字。如上所述,“添加”与“增加”之间的基本区别“addu”是前者在结果数大于31位占用的最大数时抛出异常。后者执行时没有显示任何警告。
例如,3位加法最大值=(2 **(n-1)) - 1 minumem num = - (2 **(n-1)) 所以在我们的例子中max = 3和min = -4
li $t1,3
li $t2,1
add $t3,$t1,$t2 -----> throws an arthimetic overflow exception
addu $t3,$t1,$t2 ------> t3 = -4
就是这样。
答案 4 :(得分:0)
在你的例子中,它实际上并不是溢出。当进入符号位的进位不等于符号位的进位时,发生溢出。在您的示例中,虽然符号位的执行是&#34; 1&#34; (看似溢出),进入标志位也是&#34; 1&#34;。因此,在这种情况下,MIPS不会将其视为溢出。溢出如何发生的模式实际上对应于结果是否正确。也就是说,如果结果超出了您的位可以表示的范围,则会发生溢出。例如,如果将两个4位数字0111(7)和0010(2)一起添加,则会出现溢出,因为结果(9)超出了4位数字可以表示的范围(-8到7) 。如果你看一下算术:
0111 (7) + 0010 (2) = 1001 (-7)
你可以看到虽然没有执行符号位,但结果仍然不正确。因此,这是溢出(MIPS将检测它)。