Diferença entre Adicionar e adicionar
Estou confuso sobre a diferença entre Adicionar e adicionar.
A referência da instrução MIPS diz:- adicionar (com transbordamento)
- Adicionar sem sinal (sem transbordamento)
o meu entendimento é usar adicionar com operandos assinados e adicionar com operandos não assinados.
mas vamos considerar este exemplo (com apenas 6 bits):
overflow | V 1 | 1 1 1 <- carry | 1 1 1 1 0 1 + | 1 1 1 1 1 0 = ----------------- | 1 1 1 0 1 1E este é o meu raciocÃnio:
- Se eu considerar o primeiro e o segundo operando assinado números (dois complemento), então o resultado é correto (-3 + -2 = -5) e eu não quero uma exceção de transbordamento. Então eu usaria addu para evitar esta exceção, mas, embora o resultado seja o mesmo, o nome sugere usar addu é para números não assinados!
- Se eu considerar os números do primeiro e do segundo operando sem sinal , Então eu quero uma exceção a ser levantada (porque 61 + 62 não é igual a 59). Assim, eu usaria o add para levantar a exceção, e não o addu, como o nome sugere a fazer.
- assumindo que os operandos são assinados (negativos no exemplo acima) números, devo usar addu (como o meu raciocÃnio sugere) ou devo usar add (como o nome sugere)?
- assumindo que os operandos são números Sem sinal (positivos), devo usar Adicionar (como o meu raciocÃnio sugere) ou adicionar (como o nome sugere)?
5 answers
addu
tanto para os operandos assinados como não assinados, se você fizer não deseja uma armadilha no overflow.
Utilize add
Se precisar de uma armadilha para transbordar por alguma razão. A maioria das lÃnguas não quer uma armadilha no overflow assinado, por isso add
raramente é útil.
Se estiver a usar números assinados, deve usar add
Se quiser gerar uma armadilha quando o resultado transbordar.
Se estiver a usar números Sem sinal, deve usar sempre {[[2]} e verificar o excesso da adição comparando o resultado com qualquer um dos números (se o resultado for inferior aos operandos, então a adição transbordou).
Aqui vai um excerto para mostrar como é que você iria verificar o excesso na adição não assinada:
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...
OVERFLOW is NOT as declared in the question, this carry bit is NOT a overflow bit, in the given example there is NO OVERFLOW, overflow is when:
MSB1 = 1 && MSB2 = 1 && MSBofRESULT = 0
OR
MSB1 = 0 && MSB2 = 0 && MSBofRESULT = 1
Então fique com add
ele vai flag transbordar, e o bit de transporte em seu exemplo (que não é um transbordamento) não vai incomodá-lo. addu
faz o mesmo, excepto que nunca é levantada nenhuma excepção.
Basicamente, ambos os opcodes são uma adição assinada. então em MIPS eles usam 31 bits para armazenar dados, o número máximo é (2 aumento para 31)-1 e 1 bit é reservado para armazenar o sinal para os números. Como delineado acima, a diferença básica entre" Adicionar "e" adicionar " é que o primeiro lança uma exceção quando o número do resultado é maior do que o número máximo do que 31 bit occupy. O último executa sem mostrar qualquer aviso.
Eg, adição máxima de 3 bits num = (2**(n-1)) - 1 minumem num = - (2**(n-1)) então, no nosso caso max = 3 e min = -4
li $t1,3
li $t2,1
add $t3,$t1,$t2 -----> throws an arthimetic overflow exception
addu $t3,$t1,$t2 ------> t3 = -4
É isso.
0111 (7) + 0010 (2) = 1001 (-7)
Você pode ver que apesar de não haver nenhuma realização do bit do sinal, o resultado ainda está incorreto. Portanto, este é um overflow (e MIPS irá detectá-lo).