Domanda

Diciamo che ho $t0, e mi piacerebbe dividere i suoi contenuti interi a due, e riporlo in $t1.

Il mio istinto dice: srl $t1, $t0, 2

... ma non vorrei che essere un problema se ... diciamo ... il più a destra bit era 1? O fa tutto uscito nel lavaggio perché il bit più a destra (se positivo) rende $t0 un numero dispari, che diventa anche quando diviso?

Insegnami, saggi O ...

È stato utile?

Soluzione

Usa istruzioni SRA: shift aritmetico a destra !!

sra $t1, $t0, 1

divide il contenuto di $ t0 dalla prima potenza di 2.

  

Descrizione: Sposta un valore di registro   destra dalla quantità di spostamento (shamt) e   pone il valore nella destinazione   Registrati. Il bit di segno viene spostato in.

     

Operazione: $ d = $ t >> h;

     

advance_pc (4);

     

Sintassi: sra $ d, $ t, h

     

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

Perché è importante? Controllare questo semplice programma che divide un numero intero (ingresso del programma) per 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

Compila

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

unità di 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@:~#

Vedi cosa succede? Il srl di istruzioni si sta spostando il bit di segno

  

-2 = 0xfffffffe

se ci spostiamo di un bit a destra, otteniamo 0x7fffffff

  

0x7ffffffff = 2147483647

Naturalmente questo non è un problema quando il numero è un numero intero positivo, perché il bit di segno è 0.

Altri suggerimenti

Per fare la divisione intero senza segno, questo è giusto. Questo funziona solo per i numeri interi senza segno e se non vi interessa circa la parte frazionaria.

Si vuole utilizzare una quantità di spostamento di 1, non 2:

srl $t1, $t0, 1

Se si utilizza 2, si finirà dividendo per 4. In generale, lo spostamento a destra da x divide per 2 x .

Se siete preoccupati per "arrotondamento" e si desidera per arrotondare, si può solo incrementare da 1 prima di fare la logica (non firmato) turno di lavoro.

E altri hanno affermato in precedenza, ma si sposta solo da 1 a dividere per 2. Uno spostamento a destra di n bit divide per 2 ^ N.

Per utilizzare l'arrotondamento (arrotondamento a 0,5 o superiore) con valori di spostamento di N diversi da 1, è sufficiente aggiungere 1 << (N-1) prima dello spostamento.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top