2010-02-22 18 views

Répondre

11

Voici une façon assez simple de le faire.

#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

Le plus simple serait de faire un peu de calcul binaire sur les valeurs.

http://en.wikipedia.org/wiki/Signed_number_representations décrit comment divers systèmes stockent leurs nombres négatifs. Je crois que MIPS utilise un complément à deux pour stocker les numéros signés. Ceci le rend un peu plus dur qu'un drapeau de bit, qui pourrait juste être éteint par ANDing le numéro avec 0b01111111, mais c'est toujours faisable.

17

est ici une variante de branche moins:

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

Comment ça marche?
Tout d'abord, $t1 est rempli avec le bit de signe $t0. Donc, si $t0 est positif $t1 sera mis à 0, et si $t0 est négatif $t1 sera mis à 0xFFFFFFFF.

Ensuite, chaque bit de $t0 est inversée si $t1 est 0xFFFFFFFF ou laissé inchangé si $t1 est 0. Il se trouve que inversant tous les bits d'un nombre est le même que la mise à (-number)-1 (en complément de deux).

Enfin, soit 0xFFFFFFFF (qui vaut -1) soit 0 est soustrait du résultat intermédiaire.

Donc, si $t0 était à l'origine négative vous obtenez:
$t0 = ($t0^0xFFFFFFFF) - 0xFFFFFFFF == == (-$t0 - 1) - -1(-$t0 - 1) + 1 == -$t0.
Et s'il était à l'origine positif, vous obtiendrez:
$t0 = ($t0^0) - 0 == $t0.

+1

Avertissement: Cette méthode est couverte par le brevet américain n ° 6073150. Probablement invalide comme l'enfer, cependant, puisqu'il est connu depuis plus de 1997. – Myria

8

Le moyen le plus simple de tous. Il y a une pseudo-instruction qui fait cela:

abs $t1, $t1 

prendra la valeur absolue de la valeur dans le registre t1 $ et le placer dans t1

+1

Cette pseudo-instruction est la séquence 'sra/xor/sub' montrée dans une autre réponse. – Myria

1

$ Voici une version de taille optimisée de celui-ci. Il est plus lent que la réponse sra/XOR/de subu, en raison de problèmes de prédiction de branchement, mais il est une instruction plus petite:

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

Cela fonctionne en raison de l'emplacement de retard MIPS: si $t0 est positif, l'instruction subu pour annuler $t0 exécute deux fois. Vous devrez peut-être activer .set noreorder dans votre assembleur.