2011-10-03 13 views
5

Estoy estudiando el lenguaje ensamblador MIPS y encontré este ejemplo en el libro y para mí parece incorrecto. Si es así, no sería el primer error que encontré en este libro.Convertir C a MIPS - Matrices anidadas

Las variables f y g registros son asignados $s0 y $s1 respectivamente, las direcciones de base para las matrices A y B son $s6 y $s7 respectivamente.

El ejemplo de código C es:

f = g - A[B[4]]; 

y el conjunto del MIPS correspondiente proporcionada es:

lw $t0, 16($s7) 
lw $s0, 0($t0) 
sub $s0, $s1, $s0 

Desde mi comprensión de lo anterior código MIPS sería cargar algunos datos aleatorios de la memoria en la dirección proporcionada por $t0 y luego restarlo de $s1 y no acceder al índice $t0 de la matriz indicada en $s6.

El ensamblador del MIPS correcta desde mi entendimiento sería lo largo de las líneas de:

lw $t0, 4($s7) 
add $t0, $t0, $s6 
sll $t0, $t0, 2 
lw $s0, 0($t0) 
sub $s0, $s1, $s0 

estoy en lo cierto que se trata de un error en el libro o estoy mal entendido algo.


Editar: Se ha corregido un error en el código MIPS corregido como se ha señalado por Chris Dodd

+3

Creo que estás en lo correcto. ¡Bien hecho! – davin

+1

Tu explicación es excelente. La mayor prueba del hecho de que ese código no está haciendo lo que se supone que es, es que no se menciona nada de '$ s6', por lo que no hay manera de que pueda recuperar un elemento de la matriz' A'. – davin

+4

Suponiendo que la matriz A tiene 4 bytes por elemento (como parece ser la matriz B, está utilizando un desplazamiento de 16 para obtener el elemento 4 y usando las instrucciones lw para obtener 4 bytes), deberá agregar un multiplicar por 4 aquí también (o un cambio equivalente por 2) –

Respuesta

0

Como señalé mi número, hubo un error en el libro. Desde que descubrí este error, encontré varios de esos errores.

-1

Pero muy bien podría ser que el autor copiar el código antes de tiempo de enlace. Esto dejaría abierta la posibilidad de que el enlazador se llena en la dirección de memoria de A [] en lugar del 0 en la declaración

lw $s0, 0($t0) 

en el ejecutable final. No sé si MIPS permite compensaciones de ese tamaño (es decir, el rango de direcciones donde finalmente se coloca A []). Esto, por supuesto, no es una buena manera de explicar algo en un libro, rompiendo las propias premisas en silencio y, en general, sin saber lo que está sucediendo.

+1

Esto no funcionaría ya que el desplazamiento está firmado por un desplazamiento de bytes de 16 bits y '$ s6' podría, en principio, usar el rango completo de direcciones de 32 bits. Es mucho más probable que simplemente sea un error en el libro. (Tampoco creo que ningún enlazador MIPS haga este tipo de optimización, ya que sería realmente desagradable con el desplazamiento relativo y teniendo que lidiar con casos en los que el desplazamiento es demasiado grande) – user786653

+0

Ningún ensamblador/enlazador sensato haría eso. No hay absolutamente ninguna confusión sobre lo que hace esa instrucción. Esa es una carga explícita con una dirección reg + imm. No es como un compilador de un HLL que puede insertar las instrucciones que desee. –

4

Esto es para cualquier persona (posiblemente estudiantes de CprE 381) que pueden tropezar con esto en busca de un buen ejemplo. El código editado del OP aún es incorrecto. El desplazamiento en la primera función de palabra de carga debe ser 16. Podría ser 4 si el ancho de la memoria es de 32 bits, pero entonces no sería necesario el desplazamiento/multiplicación. Suponiendo que la memoria tiene 8 bits de ancho, las funciones de agregar y cambiar deben cambiarse. En el código de OP, está multiplicando la dirección de A [B [4]/4] por 4. Al cambiar/multiplicar primero obtendrá el índice correcto. El código correcto es:

lw $t0, 16($s7) # gets the value of B[4] 
        # offset could be 4 depending on memory width 
        # but then the shift would not be needed 
sll $t0, $t0, 2 # this multiplies the index by 4 to get the address offset 
add $t0, $t0, $s6 # adds the base address of A and the offset 
lw $t0, 0($t0) # loads the value at the address 
sub $s0, $s1, $t0 # performs subtraction and stores in f 

En caso de que alguien está confundido acerca de la totalidad de desplazamiento de 16 vs 4 y si se necesita el cambio, me explico. Si el ancho de la memoria es de 32 bits, se puede almacenar un entero entero de 32 bits en una ubicación de memoria. Si este es el caso, entonces el índice de matriz es el mismo que el desplazamiento de dirección. Sin embargo, si la memoria tiene solo 8 bits (1 byte) de ancho, se almacena un entero de 32 bits en 4 ubicaciones de memoria (1 dirección para cada byte). Es por eso que necesita cambiar el índice por 2 (o multiplicar por 4) para obtener el desplazamiento correcto de la dirección.