Question

Disons que je $t0, et je voudrais partager son contenu entier par deux, et le stocker dans $t1.

dit mon tube digestif: srl $t1, $t0, 2

... mais ce ne serait pas un problème si ... disons ... le droit bit le plus était de 1? Ou est-ce que tout cela dans le lavage parce que le droit bit le plus (si elle est positive) fait $t0 un nombre impair, qui devient même lorsqu'il est divisé?

Apprends-moi, les O sages ...

Était-ce utile?

La solution

Utilisez sra d'instruction: décalage arithmétique à droite !!

sra $t1, $t0, 1

Divise le contenu de t0 $ par la première puissance de 2.

  

Description: Quarts de travail une valeur de registre   droit de la quantité de décalage (shamt) et   place la valeur dans la destination   S'inscrire. Le bit de signe est décalé dans.

     

Opération: $ d $ t = >> h;

     

advance_pc (4);

     

Syntaxe: sra $ d $ t, h

     

Encoding:   0000 00-- --- t tttt dddd dhhh hh00   0011

Pourquoi est-ce important? Vérifiez ce programme simple qui divise un nombre entier (entrée du programme) par 2.

    #include <stdio.h>

    /*
    * div divides by 2 using sra
    * udiv divides by 2 using srl
    */
    int div(int n);//implemented in mips assembly.
    int udiv(int n);
    int main(int argc,char** argv){

            if (argc==1) return 0;
            int a = atoi(argv[1]);

            printf("div:%d udiv:%d\n",div(a),udiv(a));
            return 1;
    }
    //file div.S
    #include <mips/regdef.h>

    //int div(int n)
    .globl div 
    .text
    .align 2
    .ent div
    div:
            sra v0,a0,1
            jr  ra        //Returns value in v0 register.
    .end div

    //int udiv(int n)
    .globl udiv
    .text
    .align 2
    .ent udiv
   udiv:
     srl v0,a0,1
     jr  ra        //Returns value in v0 register.
   .end udiv

Compile

root@:/tmp#gcc -c div.S
root@:/tmp#gcc -c main.c
root@:/tmp#gcc div.0 main.o -o test

lecteurs de test:

root@:~# ./test 2
div:1 udiv:1
root@:~# ./test 4
div:2 udiv:2
root@:~# ./test 8
div:4 udiv:4
root@:~# ./test 16
div:8 udiv:8
root@:~# ./test -2
div:-1 udiv:2147483647
root@:~# ./test -4
div:-2 udiv:2147483646
root@:~# ./test -8
div:-4 udiv:2147483644
root@:~# ./test -16
div:-8 udiv:2147483640
root@:~#

Voyez ce qui se passe? srl instruction se déplace le bit de signe

  

= -2 0xfffffffe

si on passe un peu à droite, nous obtenons 0x7fffffff

  

0x7ffffffff = 2147483647

Bien sûr, ce n'est pas un problème lorsque le nombre est un entier positif, parce que le bit de signe est 0.

Autres conseils

Pour la division entier non signé, thats droit. Cela ne fonctionne que pour les entiers non signés et si vous ne se soucient pas de la partie décimale.

Vous voulez utiliser une quantité de décalage de 1, pas 2:

srl $t1, $t0, 1

Si vous utilisez 2, vous finirez en divisant par 4. En général, décalage vers la droite par x Divise par 2 x .

Si vous êtes préoccupé par l ' « arrondissement » et que vous voulez arrondir, vous pouvez juste augmenter de 1 avant de faire le déplacement logique (non signé).

Et d'autres ont déclaré qu'il auparavant, mais vous passez seulement par 1 à diviser par 2. Un décalage vers la droite par N bits Divise par 2 ^ N.

Pour utiliser l'arrondi (arrondi à 0,5 ou plus) avec des valeurs de décalage des N autres que 1, il suffit d'ajouter 1 << (N-1) avant le changement.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top