Разница между 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
делает то же самое, если только исключение не возникает.