Pregunta

Vamos a decir que tengo $t0, y me gustaría dividir su contenido enteros en dos, y almacenarlo en $t1.

Mi instinto dice: srl $t1, $t0, 2

... pero no que sea un problema si ... digamos ... más a la derecha poco era 1? O lo hace todo sale en el lavado ya que el bit más a la derecha (si es positivo) hace $t0 un número impar, lo que hace aún cuando se divide?

Enséñame, oh sabios ...

¿Fue útil?

Solución

SRA Uso de instrucciones: desplazamiento aritmético a la derecha !!

sra $t1, $t0, 1

Divide el contenido de $ t0 por la primera potencia de 2.

  

Descripción: Cambia un valor de registro   derecho por la cantidad de desplazamiento (shamt) y   coloca el valor en el destino   registro. El bit de signo se desplaza en.

     

Operación: $ D $ = t >> h;

     

advance_pc (4);

     

Sintaxis: SRA $ d, $ t, h

     

Codificación:   0000 00-- --- t tttt dddd dhhh hh00   0011

¿Por qué es importante esto? Compruebe este sencillo programa que divide un número entero (entrada de programa) por 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

Compilar

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

unidades de prueba:

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

Vea lo que sucede? El srl de instrucciones está cambiando el bit de signo

  

-2 = 0xFFFFFFFE

si cambiamos un poco a la derecha, obtenemos 0x7fffffff

  

0x7ffffffff = 2147483647

Por supuesto, esto no es un problema cuando el número es un entero positivo, ya que el bit de signo es 0.

Otros consejos

Para hacer una división de entero sin signo, eso es correcto. Esto sólo funciona para enteros sin signo y si no se preocupan por la parte fraccionaria.

Usted tendrá que utilizar una cantidad de cambio de 1, no 2:

srl $t1, $t0, 1

Si utiliza 2, el resultado final será dividir por 4. En general, desplazando a la derecha por x divide por 2 x .

Si usted está preocupado por el "redondeo" y que desea redondear hacia arriba, sólo puede incrementarse en 1 antes de hacer el desplazamiento lógico (sin firmar).

Y otros han declarado previamente, pero sólo cambiar por 1 a dividir por 2. Un desplazamiento a la derecha por la N bits se divide por 2 ^ N.

Para usar redondeo (redondeando hacia arriba en 0,5 o mayor) con valores de desplazamiento de N distintos de 1, sólo tiene que añadir 1 << (N-1) antes del cambio.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top