我对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
这是我的理由:
现在我的问题是:
mar*_*kgz 13
指令名称具有误导性.addu如果您不希望溢出陷阱,请用于有符号和无符号操作数.
add如果由于某种原因需要溢出陷阱,请使用.大多数语言都不希望有符号溢出的陷阱,因此add很少有用.
如果使用带符号的数字,则应使用,add如果希望在结果溢出时生成陷阱.
如果使用无符号数,则应始终使用addu并检查加法的溢出,方法是将结果与任一数字进行比较(如果结果小于操作数,则加法会溢出).
这里有一个片段,显示如何检查无符号加法中的溢出:
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...
Run Code Online (Sandbox Code Playgroud)
溢出不是问题中声明的,该进位不是溢出位,在给定的示例中没有溢出,溢出是在以下情况下:
MSB1 = 1 && MSB2 = 1 && MSBofRESULT = 0
OR
MSB1 = 0 && MSB2 = 0 && MSBofRESULT = 1
Run Code Online (Sandbox Code Playgroud)
因此坚持下去add会标记溢出,并且示例中的进位位(不是溢出)不会打扰您。addu执行相同的操作,但不会引发任何异常。
基本上这两个操作码都是有符号的添加。因此,MIPS 使用 31 位来存储数据,最大数量为 (2 raise to 31)-1,并保留 1 位来存储数字的符号。如上所述,“add”和“addu”之间的基本区别在于,前者在结果数大于31位可以占用的最大数时抛出异常。后一个执行时不会显示任何警告。
例如,3 位加法最大 num = (2**(n-1))-1 最小值 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
Run Code Online (Sandbox Code Playgroud)
这就对了。
| 归档时间: |
|
| 查看次数: |
30527 次 |
| 最近记录: |