2010-02-22 167 views

Respuesta

11

Aquí hay una manera bastante simple de hacerlo.

#assume you want the absolute value of r1 
     ori $2, $zero, $1  #copy r1 into r2 
     slt $3, $1, $zero  #is value < 0 ? 
     beq $3, $zero, foobar #if r1 is positive, skip next inst 
     sub $2, $zero, $1  #r2 = 0 - r1 
foobar: 
#r2 now contains the absolute value of r1 
1

La manera más fácil sería simplemente hacer un poco de matemática binaria en los valores.

http://en.wikipedia.org/wiki/Signed_number_representations describe cómo varios sistemas almacenan sus números negativos. Creo que MIPS utiliza un esquema de dos complementos para almacenar números con signo. Esto hace que sea un poco más difícil que una bandera de bit, que podría ser desactivada simplemente por ANDing el número con 0b01111111, pero todavía es factible.

17

Aquí es una variante rama menos:

# input and output in $t0 
sra $t1,$t0,31 
xor $t0,$t0,$t1 
sub $t0,$t0,$t1  

¿Cómo funciona esto?
Primero, $t1 está lleno con el signo-bit de $t0. Por lo tanto, si $t0 es positivo $t1 se establecerá en 0, y si $t0 es negativo, $t1 se configurará en 0xFFFFFFFF.

A continuación, cada bit de $t0 se invierte si $t1 es 0xFFFFFFFF, o se deja sin cambios si $t1 es 0. Se da la circunstancia de que la inversión de todos los bits de un número es el mismo que para ajustar a (-number)-1 (en complemento a dos).

Finalmente, 0xFFFFFFFF (que equivale a -1) o 0 se resta del resultado intermedio.

Así que si $t0 originalmente fue negativa que obtendrá:
$t0 = ($t0^0xFFFFFFFF) - 0xFFFFFFFF == == (-$t0 - 1) - -1(-$t0 - 1) + 1 == -$t0.
Y si originalmente fue positivo obtendrá:
$t0 = ($t0^0) - 0 == $t0.

+1

Advertencia: este método está cubierto por la patente de Estados Unidos Nº 6073150. Probablemente inválido como el infierno, sin embargo, ya que se conoce desde hace más de 1997. – Myria

8

La manera más simple de todas. Hay una instrucción de pseudo que hace esto:

abs $t1, $t1 

tomará el valor absoluto del valor en el registro $ t1 y colocarlo en $ t1

+1

Esta pseudoinstrucción es la secuencia 'sra/xor/sub' que se muestra en otra respuesta. – Myria

1

Aquí hay una versión tamaño optimizado de la misma. Es más lento que la respuesta SRA/xor/subu, debido a problemas de predicción de saltos, pero es una instrucción más pequeña:

bgtz $t0, label 
label: 
    subu $t0, $zero, $t0 

Esto funciona debido a la ranura de retardo MIPS: si $t0 es positivo, la instrucción subu para negar $t0 ejecuta dos veces Es posible que necesite habilitar .set noreorder en su ensamblador.