add和addu之间的区别

col*_*rco 14 add mips isa

我对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

这是我的理由:

  • 如果我考虑第一个和第二个操作数有符号数(二进制补码),那么结果是正确的(-3 + -2 = -5),我不想要溢出异常.所以我会使用addu来避免这个异常,但是,虽然结果是一样的,但名称建议使用addu是为了无符号数!
  • 如果我考虑第一个和第二个操作数无符号数,那么我想要引发一个异常(因为61 + 62不等于59).因此,我会使用add来引发异常,而不是addu,正如名称所暗示的那样.

现在我的问题是:

  • 假设操作数已签名(上例中为负数),我应该使用addu(正如我的推理所示)还是应该使用add(顾名思义)?
  • 假设操作数是无符号(正数),我应该使用add(如我的推理所示)还是addu(顾名思义)?

mar*_*kgz 13

指令名称具有误导性.addu如果您希望溢出陷阱,请用于有符号和无符号操作数.

add如果由于某种原因需要溢出陷阱,请使用.大多数语言都不希望有符号溢出的陷阱,因此add很少有用.


gus*_*bro 5

如果使用带符号的数字,则应使用,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)


Sta*_*yer 5

溢出不是问题中声明的,该进位不是溢出位,在给定的示例中没有溢出,溢出是在以下情况下:

MSB1 = 1 && MSB2 = 1 && MSBofRESULT = 0
OR
MSB1 = 0 && MSB2 = 0 && MSBofRESULT = 1 
Run Code Online (Sandbox Code Playgroud)

因此坚持下去add会标记溢出,并且示例中的进位位(不是溢出)不会打扰您。addu执行相同的操作,但不会引发任何异常。


Hen*_*aye 5

基本上这两个操作码都是有符号的添加。因此,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)

这就对了。