add和addu之间的区别

时间:2013-05-19 11:21:05

标签: 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(顾名思义)?

5 个答案:

答案 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将检测它)。