web-dev-qa-db-ja.com

addとadduの違い

Addとadduの違いについて混乱しています。

MIPS命令リファレンスは次のように述べています。

  • 追加(オーバーフローあり)
  • 符号なしを追加(オーバーフローなし)

私の理解は、符号付きオペランドでaddを使用し、符号なしオペランドでadduを使用することです。

しかし、この例を考えてみましょう(6ビットのみ):

オーバーフロー
 | 
 V 
 1 | 1 1 1 <-キャリー
 | 1 1 1 1 0 1 + 
 | 1 1 1 1 1 0 = 
 ----------------- 
 | 1 1 1 0 1 1 

そしてこれは私の推論です:

  • 1番目と2番目のオペランドsigned数値(2の補数)を検討すると、結果は正しく(-3 + -2 = -5)、オーバーフロー例外は必要ありません。そのため、私はこの例外を回避するためにadduを使用しますが、結果は同じですが、名前は符号なしの数値用であることを示唆しています。
  • 最初のオペランドと2番目のオペランドnsignedを考慮すると、例外が発生します(61 + 62は59と等しくないため)。そのため、名前からわかるように、adduではなく、addを使用して例外を発生させます。

今私の質問は:

  • オペランドが符号付き(上記の例では負)の数値であると仮定すると、(推論が示唆するように)adduを使用すべきですか、それとも(名前が示唆するように)addを使用すべきですか?
  • オペランドが符号なしの(正の)数値であるとすると、add(私の推論が示唆するとおり)またはaddu(名前が示唆するとおり)を使用する必要がありますか?
15
collimarco

命令名は誤解を招くものです。 notオーバーフローでトラップが必要な場合は、符号付きオペランドと符号なしオペランドの両方にadduを使用します。

何らかの理由でオーバーフローのトラップが必要な場合は、addを使用してください。ほとんどの言語は、署名されたオーバーフローのトラップを望まないため、addが役立つことはほとんどありません。

12
markgz

符号付きの数値を使用している場合、結果がオーバーフローしたときにトラップを生成するには、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...
5
gusbro

OVERFLOW is [〜#〜] not [〜#〜]質問で宣言されているように、このキャリービットはオーバーフロービットではありません。この例では、OVERFLOWはなく、オーバーフローは次の場合に発生します。

MSB1 = 1 && MSB2 = 1 && MSBofRESULT = 0
OR
MSB1 = 0 && MSB2 = 0 && MSBofRESULT = 1 

したがって、addに固執すると、オーバーフローのフラグが立てられ、例のキャリービット(オーバーフローではない)が気になりません。 adduは、例外が発生しないことを除いて、同じことを行います。

3
Stack Player

基本的に両方のオペコードは符号付き加算です。 MIPSでは31ビットを使用してデータを格納し、最大数は(2を31に上げる)-1で、1ビットは数値の符号を格納するために予約されています。上記で説明したように、「add」と「addu」の基本的な違いは、結果の数が31ビットが占有する最大数より大きい場合に前者が例外をスローすることです。後者は警告を表示せずに実行されます。

たとえば、3ビットの加算の最大値num =(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

それだ。

2
Henok Tesfaye

あなたの例では実際にはオーバーフローではありません。オーバーフローは、符号ビットへのキャリーが符号ビットのキャリーと等しくないときに発生します。あなたの例では、符号ビットの桁上げは "1"(オーバーフローのように見える)ですが、符号ビットへの桁上げも "1"です。したがって、この状態ではMIPSはそれをオーバーフローと見なしません。オーバーフローが発生するパターンは、実際には結果が正しいかどうかに対応しています。つまり、結果がビットが表現できる範囲外の場合、オーバーフローが発生します。たとえば、2つの4ビット数値0111(7)と0010(2)を一緒に追加すると、結果(9)が4ビット数値が表すことができる範囲(-8〜7)を超えているため、オーバーフローが発生します。 。あなたが算術を見れば:

0111 (7) + 0010 (2) = 1001 (-7)

符号ビットのキャリーはありませんが、結果はまだ正しくないことがわかります。したがって、これはオーバーフローです(そしてMIPSがそれを検出します)。

0
shengjiex98