Introducción
a MIPS
Ciencias de la Computación III
Diego José Figueroa
Assembler
- Lenguaje de bajo nivel
- Capa de abstracción
- Dependiente de la arquitectura
- ¿Cuándo debemos usar assembler?
- ¿Ventajas?
- ¿Desventajas?
ISA
- Vocabulario de assembler.
- Conjunto de instrucciones de una arquitectura.
- Abstracción entre hardware/software.
- Provee un medio de unión entre hardware y software.
CISC vs RISC
- Podemos clasificar una arquitectura de acuerdo a su ISA.
- CISC
- Complex Instruction Set Computer
- RISC
- Reduced Instruction Set Computer
CISC
- Complex Instruction Set Computer
- Muchas instrucciones
- Instrucciones 'raras'.
- Muchos modos de direccionamiento.
- Pocos registros.
- Instrucciones de tamaño variable.
- Ej: Intel :(
RISC
- Reduced Instruction Set Computer.
- Pocas instrucciones.
- Muchos registros.
- Pocos modos de direccionamiento
- Sólo se opera entre registros.
- Instrucciones de tamaño fijo.
- Diseño más elegante.
- Ej: MIPS :)
Cantidad de Operandos
Podemos clasificar una arquitectura en función de la cantidad de operandos explícitos en sus instrucciones:
- Stack Machine (0-Address Machine)
- add
- Accumulator Machine (1-Address Machine)
- add $1
- Register File (2-Address Machine)
- add $1 $2
- 3 Address Machine
- add $1 $2 $3
¿Por qué MIPS?
- Diseño sumamente simple.
- Creado con fines didácticos.
- Convenio de llamadas a funciones simple.
- Muchos registros (32).
- Elegante y fácil de entender.
¿Por qué no x86?
- Complejo (CISC).
- Muchas instrucciones, convenios confusos.
- Pocos registros (8).
MIPS Assembly Language
- Comúnmente llamado MAL
- Superset de las instrucciones soportadas en hardware.
- El ensamblador convierte MAL a assembler real.
- Brinda facilidades al programador.
- Permite escribir código más conciso.
¿Cómo escribo un programa?
- En MIPS cada instrucción ocupa una línea.
- Lleva el formato
- <operación> <destino> <operando1> <operando2>
add $v0 $a0 $a1
¿Comentarios?
- Cualquier cosa después de # es un comentario.
# esto es un comentario
add $0 $0 $0 # esto es otro comentario
Registros
- MIPS está diseñado para operar mayormente entre registros.
- Un registro
- es una memoria muy pequeña.
- del tamaño de la arquitectura.
- muy rápida.
- MIPS provee 32 registros de 32 bits.
- Cada registro puede almacenar cualquier cosa que quepa en 4 bytes.
Registros
- Un registro NO es una variable.
- Repitamos, un registro NO es una variable.
- Un registro NO tiene un tipo de dato.
¿Por qué usamos registros?
Registros de MIPS
- 32 registros:
- de $0 a $31
-
Todos se pueden usar en cualquier operación.
- Sin embargo, hay ciertos convenios, que asignan usos específicos a algunos registros.
- Por facilidad a los registros se les dieron nombres, de acuerdo a su función.
$zero
- $0 o $zero
- Siempre vale 0.
- Está alambrado a tierra, cualquier intento de escritura es ignorado.
- Usado comúnmente para inicializaciones, o donde no importa el registro.
$s0 - $s7
- $16 a $23.
- Conocidos como saved registers, sobreviven las llamadas a funciones.
- Es decir, no se modifican al llamar a una función.
- Esto permite que se usen para guardar valores importantes y cosas que queramos mantener al llamar a una función.
$t0 - $t9
- $8 a $15 más $24 y $25.
- Registros temporales, no se preservan al llamar a una función.
- Utilizados para valores temporales o poco importantes.
a = b+(c+d) # c + d es temporal
$a0 - $a3
- $4 a $a7.
- Para paso de argumentos.
- Permiten enviar los primeros 4 argumentos a una función.
$v0 y $v1
- $2 y $3.
- Utilizados para devolver resultados de una función.
- Todas las funciones deben colocar sus resultados en estos registros.
$sp
- $29
- Conocido como Stack Pointer.
- Apunta al stack, se utiliza para administrar el stack.
- Utilizando $sp se puede pedir/reservar espacio en el stack.
- Más de esto, más adelante.
$ra
- $31
- Conocido como Return Address.
- Se utiliza para guardar la dirección de retorno de una función.
- Las funciones, cuando terminan deben regresar a la instrucción que sigue a la instrucción que le llamó, $ra almacena esa dirección.
$gp, $fp
-
$28 y $30.
- Punteros, Global Pointer y Frame Pointer.
- No necesitan usarlos, por el momento.
$at
- $1
- Conocido como Assembler temporary.
- Registro temporal, utilizado por el ensamblador.
El programador NO debe utilizar
este registro.
$k0, $k1
- Utilizados por el kernel del sistema operativo.
- Sirven para manejo de excepciones/interrupciones.
El programador NO debe usar estos
registros.
add $s0 $s1 $s2
Instrucciones Aritméticas y Lógicas
- Las instrucciones aritméticas tienen formato de 3 operandos. El primer operando es el destino. Los dos siguientes son operandos.
add $s0 $s1 $s2 # $s0 <- $s1 + $s2
- Los operandos pueden ser ÚNICAMENTE registros. No direcciones de memoria, ni valores constantes.
a = b + c + d - e; // a -> $s0, b -> $s1
// c -> $s2, d -> $s3
// e -> $s4
add $t0 $s1 $s2 # $t0 <- $s1 + $s2
add $t0 $t0 $s3 # $t0 <- $t0 + $s3
sub $s0 $t0 $s4 # $s0 <- $t0 - $s4
Instrucciones Aritméticas y Lógicas
¿Y si queremos operar con constantes?
Aritméticas y Lógicas Inmediatas
- El tercer argumento es una constante, en vez de un registro.
- Sólo se permiten constantes de hasta 16bits.
addi $s0 $s1 10
- Se distinguen por la terminación en i.
- Aplica para todas las instrucciones anteriores.
Corrimientos
-
sll # shift left logical
- srl # shift right logical
- sra # shift right arithmetical
- Formato
- operación rd rt shamt
- operación es uno de: sll, srl, o sra.
- rd es el registro destino.
- rt es el registro a correr sus bits.
- shamt es la cantidad de bits a correr.
sll $s0 $s1 16
Corrimientos
- Existe una versión variable, recibe la cantidad de bits a correr en un registro en vez de una constante.
- sllv
- srlv
- srav
sllv $s0 $s1 $t0
Multiplicación
- Potencialmente puede producir un número de 64bits.
- Por lo que puede tomarse un tiempo en calcular.
- mult, recibe 2 argumentos:
- rs -> primer registro a multiplicar
- rt -> segundo registro a multiplicar
- El resultado se coloca en 2 registros especiales:
- La parte alta (32 bits más a la izq.) en el registro hi.
- La parte baja (32 bits más a la der.) en el registro lo.
mult $t0 $t1
Multiplicación
- Para obtener el resultado es necesario sacarlo de hi y/o lo.
- Para eso se utiliza:
- mfhi
- mflo
- Reciben un argumento, el registro a donde se copiará el valor.
mult $t0 $t1
mflo $s0 # $s0 = $t0 * $t1
División
- Funciona de modo similar a la multiplicación.
- Coloca el cociente en lo.
- Coloca el residuo en hi.
div $t0 $t1
mflo $s0 # $s0 = $t0 / $t1
Valores inmediatos
- li
- Carga un valor inmediato (constante) a un registro.
li $t0 10 # $t0 = 10
li $t1 'a' # $t1 = 'a'
Lectura de Memoria
- lb - Load byte
- lh - Load half-word
- lw - Load word
- ld - Load double
lw $s0 0($sp) # $s0 = *(0+$sp)
lw $s1 4($sp) # $s1 = *(4+$sp)
- El offset es un inmediato de 16 bits con signo, que se suma a la dirección contenida en el registro.
- El registro de la dirección, no se modifica.
Escritura de Memoria
- sb - Store byte
- sh - Store half-word
- sw - Store word
- sd - Store double
- Funciona de la misma forma que los anteriores, pero escriben a memoria en vez de leerla.
sw $t0 0($sp) # *(0+$sp) = $t0
Accesos a Memoria
- lw/sw mueven un word desde/hacia la memoria.
- Deben hacerse accesos a direcciones word-aligned.
- lh/sh mueven un half-word (2 bytes) desde/hacia la memoria.
- Deben hacerse accesos a direcciones múltiplo de 2.
- lb/sb mueven un byte (un char) desde/hacia la memoria.
Compilemos C
a = b + c;
f = (g + h) – (i + j);
// a -> $s0, b -> $s1, c -> $s2
// f -> $s3, g -> $s4, h -> $s5
// i -> $s6, j -> $s7
¿Equivalente en MIPS?
Compilemos C
string[i+1] = string[i] + 32;
// string -> $s0
// i -> $s1
¿Equivalente en MIPS?
Directivas
- Etiqueta
- Simboliza la dirección absoluta de la instrucción inmediatamente siguiente.
main: # main es una etiqueta
add $v0 $s0 $0
jr $ra
- .text
- Directiva que indica al ensamblador que lo siguiente es el texto del programa.
- .data
- Directiva que indica al ensamblador que lo que sigue es data global.
Más directivas...
- .byte <value>
- Reserva 1 byte en memoria.
- .word <value>
- Reserva 1 word en memoria.
- .space <n>
- Reserva <n> bytes consecutivos de memoria.
- Recuerden word-aligned!
- .asciiz <string>
- Reserva espacio para el <string> indicado, agrega el '\0' al final.
.data msg: .asciiz "hello world!\n"
.text main: la $a0 msg # carga el mensaje
li $v0 4 # print_string(msg) syscall
li $v0 10 # exit syscall
Title
05 - Intro MIPS
By Diego Figueroa
05 - Intro MIPS
- 1,032