Разница между add и addu

Я запутался в различии между add и addu.

В инструкции к MIPS говорится:

  • добавить (с переполнением)
  • добавить unsigned (без переполнения)

Мое понимание заключается в использовании 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 для неподписанных номеров!
  • Если я рассматриваю первый и второй операнды unsigned, то я хочу, чтобы исключение было поднято (потому что 61 + 62 не равно 59). Поэтому я бы использовал add для создания исключения, а не addu, как это предполагалось бы именем.

Теперь мои вопросы:

  • Предполагая, что операнды подписаны (отрицательные в приведенном выше примере) числах, следует ли использовать addu (как следует из моих рассуждений), или я должен использовать add (как следует из названия)?
  • Предполагая, что операнды являются неподписанными (положительными) числами, следует ли использовать add (как я полагаю) или addu (как следует из названия)?

Ответ 1

Имена команд вводят в заблуждение. Используйте addu для подписанных и неподписанных операндов, если вы не хотите перехват перехвата.

Используйте add, если по какой-то причине вам понадобится ловушка при переполнении. Большинство языков не хотят ловушки при переполнении подписей, поэтому add редко бывает полезным.

Ответ 2

Если вы используете подписанные числа, вы должны использовать 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...

Ответ 3

OVERFLOW НЕ, как заявлено в вопросе, этот бит переноса НЕ является переполняющим битом, в данном примере нет OVERFLOW, переполнение происходит, когда:

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

поэтому придерживайтесь add, он будет отмечать переполнение, а бит переноса в вашем примере (который не является переполнением) не беспокоит вас. addu делает то же самое, если только исключение не возникает.