Sunteți pe pagina 1din 38

PRINCIPIOS DE COMPUTADORES

PROGRAMACIN ENSAMBLADOR MIPS

NDICE
Introduccin. Estructura de los programas de ensamblador MIPS. Tipos de datos. Registros. Datos, carga y almacenamiento y direccionamientos. Operaciones aritmticas bsicas. Operaciones de salto. Entrada y salida. Llamadas al sistema. Subprogramas. Instrucciones en punto flotante. Codificacin de las instrucciones.
2

INTRODUCCIN
El lenguaje ensamblador difiere de los lenguajes de alto nivel en que son dependientes, y por lo tanto ms cercanos a la arquitectura de la mquina. El estudio de un lenguaje de ensamblador permite conocer la arquitectura y el funcionamiento de los ordenadores. Hemos elegido MIPS por ser un lenguaje ensamblador sencillo, con un reducido conjunto de instrucciones. MIPS (siglas de Microprocessor without Interlocked Pipeline Stages) es toda una familia de microprocesadores de arquitectura RISC (Reduced Instruction Set Computer) desarrollados por MIPS Technologies. Los diseos del MIPS son utilizados en la lnea de productos informticos de SGI; en muchos sistemas embebidos; en dispositivos para Windows CE; routers Cisco; y videoconsolas como la Nintendo 64 o las Sony PlayStation, PlayStation 2 y PlayStation Portable. Para poder realizar las prcticas de ensamblador MIPS en una mquina con una familia de procesadores diferentes, vamos a usar un simulador. PCSpim
3

ASPECTO DE UN PROGRAMA SENCILLO

ESTRUCTURA DE UN PROGRAMA
Un programa en ensamblador ser un fichero de texto plano, que usar el sufijo .s Los programas debern estar comentados. Se considera un comentario todo lo que sigue a #
# esto es un ejemplo de comentario

Los programas empiezan por la seccin de declaracin de datos, seguido por la seccin de cdigo. La seccin de datos se identifica por la directiva .data En la seccin de datos se declaran los nombres de variables que se usan en el programa (se almacenarn en la memoria principal) La seccin de cdigo se identifica por la directiva .text Contiene las instrucciones del programa y el punto de comienzo del mismo se identifica por la etiqueta main: El punto de finalizacin del main suele ser una llamada al sistema exit (se carga el cdigo 10 en $v0 y se invoca a syscall)

PLANTILLA PARA PROGRAMAS

TIPOS DE DATOS
Todas las instrucciones son de 32 bits 1 byte = 8 bits 1 halfword = 2 bytes 1 word = 4 bytes Un carcter requiere un byte de almacenamiento Un entero requiere un word de almacenamientos Las constantes numricas se expresan con el nmero. Por ejemplo 4 Las constantes de caracteres se expresan entre comillas simples. Por ejemplo a b Las cadenas de caracteres (strings) entre comillas dobles esto es una cadena de caracteres
7

LOS REGISTROS
Existen 32 registros de propsito general Para nombrarlos se pone el smbolo $ Existe dos formas diferentes de llamar a los registros:
Usando exclusivamente $ y su nmero, por ejemplo $0 a $31 Usando su nombre equivalente, por ejemplo $t1, $sp

Existen dos registros especiales $lo y $hi que se usan para almacenar resultados de la multiplicacin y la divisin. No se puede acceder directamente a ellos como los anteriores, sino que hay que hacerlo a travs de instrucciones especiales mfhi (move from hi), o mflo (move from lo) La pila crece siempre desde memoria alta hacia memoria baja ($sp es el puntero de pila stack pointer)

DECLARACION DE DATOS
Recuerda: La seccin de datos se identifica por la directiva .data .En la seccin de datos se declaran los nombres de variables que se usan en el programa (se almacenarn en la memoria principal) El formato general de una declaracin es:
nombre:
radio: vocales: vector:

tipo_del_dato

valor(es)

Ejemplos de cargas de datos:


.word 3 #crea una variable word de nombre radio y valor 3 .byte a,e,i,o,u # array de nombre vocales con las letras .space 40 # vector de 40 bytes no inicializados que se puede usar # para 40 caracteres o 10 enteros .

LOS REGISTROS
Num Nombre Descripcin

0 1 2-3 4-7 8-15

zero $at Sv0-$v1 $a0-$a3 $t0-$t7

Constante valor cero Temporal reservado para el ensamblador. Usado al traducir las pseudoinstrucciones. Valores resultantes de funciones y evaluaciones Argumentos para subrutinas. No se preservan a travs de llamadas a subrutinas. Temporales. No se preservan a travs de llamadas de subrutinas, por lo que la rutina que llama debe salvarlos si los quiere conservar. Valores salvados. Una subrutina que los use debe salvar sus valores antes de usarlos, y restaurarlos al salir. Continuacin a los $t0-t7. Temporales. No se preservan a travs de llamadas de subrutinas, por lo que la rutina que llama debe salvarlos si los quiere conservar Reservados para el kernel (manejo de interrupciones) Puntero global. Apunta al medio del bloque de 64K en el segmento de datos estticos Puntero de pila (stack pointer). No se actualiza automticamente. Valor salvado. Puntero de marco. Se preserva a travs de llamadas. Permite acceder de modo indexado a los elementos de la pila. Direccin de retorno (return address). 10

16-23 24-25 26-27 28 29 30 31

$s0-$s7 $t8-$t9 $k0-$k1 $gp $sp $s8/$fp $ra

INSTRUCCIONES DE CARGA Y ALMACENAMIENTO


MIPS es una mquina de arquitectura carga-almacenamiento, lo que quiere decir que antes de usar un dato almacenado en memoria primero hay que cargarlo en un registro para poderlo utilizar. Instrucciones de carga y almacenamiento:
lw registro_destino, variable_fuente # copia un word de memoria en el registro especificado lb registro_destino, variable_fuente # copia un byte de memoria en el byte menos significativo del # registro especificado li registro_destino, valor_inmediato # copia el valor especificado en el registro destino sw registro_fuente, variable_destino # copia un registro en un word de memoria sb registro_fuente, variable_destino # copia el byte menos significativo del registro especificado en un # byte de memoria.

11

EL ACCESO A MEMORIA
El ancho del bus de datos es de tamao word (32 bits) El ancho del bus de direcciones es tambin de 32 bits, de lo cual podemos concluir que:
existen 232 direcciones de memoria diferentes de 1 byte de tamao. lo que significan que habr 230 words que son 4 GB

La forma en la que est organizada la memoria es bigendian. Esto significa que cada word tiene la direccin del byte ms significativo de los 4 que forman el word. De esto se puede concluir que la direccin de cada word tiene que ser mltiplo de 4.

12

EJEMPLO DE CARGA Y ALMACENAMIENTO

13

DIRECCIONAMIENTO INDIRECTO Y DIRECCIN BASE


Podemos almacenar en un registro la direccin de memoria de una variable (concepto de puntero). La sintaxis para hacerlo es: la registro, variable Ejemplo: la $t0, x # carga en $t0 la direccion de la variable x

Si un registro contiene una direccin de memoria, podemos usar el contenido de esa direccin de memoria usando parntesis alrededor del registro. Ejemplo: lw $t1, ($t0) # carga en $t1 el valor contenido en la
# direccin de memoria apuntada por $t0

Para acceder a direcciones de memoria consecutivas podemos usar direccionamiento base + desplazamiento (offset). Ejemplo:
lw $t2, 4($t0) # carga en $t2 el valor contenido en la direccin # de memoria apuntada por $t0+4. En este caso como # un word son 4 bytes, en $t2 tendramos el word de # memoria siguiente al apuntado por $t0

El desplazamiento (offset) puede ser negativo y su uso es exactamente el mismo


lw $t3, -8($t0) # carga en $t3 el valor contenido en la direccin # de memoria apuntada por $t0-8. En este caso como # un word son 4 bytes, en $t3 tendramos el word de

14

DIRECCIONAMIENTO INDIRECTO Y DIRECCIN BASE

15

OPERACIONES ARITMTICAS BSICAS


Condiciones generales:
La mayora de las operaciones usan 3 operandos Las operaciones se hacen sobre registros (no sobre posiciones de memoria). Uno de los operandos podr ser un valor inmediato (o el registro $zero). El tamao del operando obviamente es de 4 bytes.

Suma:
add $t0,$t1,$t2 addi $t0,$t3, 7 addu $t1,$t6,$t7 # # # # $t0=$t1+$t2 suman enteros con signo. Negativos representados en complemento a 2. $t0=$t3+7 (o cualquier valor inmediato) $t1=$t6+$t7 suman como enteros sin signo

Resta:
sub $t2,$t3,$t4 subu $t1,$t6,$t7 # $t2=$t3-$t4 resta de enteros # $t1=$t6-$t7 resta como enteros sin signo

Multiplicacin:
mult $t3,$t4 # La multiplicacin de dos registros de 32 bits da # un registro de 64 bits que ser ((Hi,Lo) # Lo = $t5/$t6 (divisin entera) # Hi= $t5 mod $t6 (Hi tendr el resto) # $t2 = $t3 # $t0 = Hi para los resultados de multip y divis. # $t1 = Lo para los resultados de multip y divis.

Divisin:
div $t5,$t6

Asignacin de valores de resultado:


move $t2,$t3 mfhi $t0 mflo $t1

16

OPERACIONES DE SALTO
Saltos incondicionales:
j etiqueta # salta a la parte del cdigo que empiece con etiqueta: b etiqueta # salta a la parte del cdigo que empiece con etiqueta: jr $t3 # salta a la direccin de programa contenida en $t3

Saltos condicionales:
beq blt ble bgt bge bne $t0,$t1,etiqueta $t0,$t1,etiqueta $t0,$t1,etiqueta $t0,$t1,etiqueta $t0,$t1,etiqueta $t0,$t1,etiqueta # # # # # # si si si si si si $t0=$t1 entonces salta a etiqueta: $t0<$t1 entonces salta a etiqueta: $t0<=$t1 entonces salta a etiqueta: $t0>$t1 entonces salta a etiqueta: $t0>=$t1 entonces salta a etiqueta: $t0<>$t1 entonces salta a etiqueta:

17

ENTRADA Y SALIDA. LLAMADAS AL SISTEMA


El simulador nos permite leer y escribir valores de entrada y salida en la ventana de la consola y hacer una salida correcta del programa. Usa para ello la llamada al sistema operativo syscall Se le pasa a la llamada syscall valores en los registros $v0 y adicionalmente en $a0 y $a1. Si syscall tiene valor de salida quedar registrado en $v0

18

ENTRADA Y SALIDA. LLAMADAS AL SISTEMA


Servicio
print_int print_float print_double print_string read_int read_float read_double read_string

$v0
1 2 3 4 5 6 7 8

Argumentos
$a0 = entero a imprimir $f12 = flotante a imprimir $f12-13 = double a imprimir $a0 = direccion de memoria de la cadena a imprimir

Resultados

$v0 = entero que se ley $f0 = flotante que se ley $f0-$f1 = double que se ley $a0 = direccin memoria donde se almacenar la cadena a leer. $a1 = nmero. tamao de la cadena $a0 = n bytes requeridos de memoria dinmica $v0 = direccin de memoria que contendr los bytes 19

sbrk

exit

10

ENTRADA Y SALIDA. LLAMADAS AL SISTEMA


La funcin print_string siempre espera que la cadena termine un carcter nulo. Con la directiva .asciiz se crea una cadena terminada en un nulo (ver ejemplo) Las funciones de lectura read_int, read_float, y read_double siempre esperan hasta que se introduzca un retorno de carro en la entrada. La funcin read_string (recordar que $a0 contiene la direccin del buffer y $a1 contiene el nmero de caracteres) se comporta de la siguiente manera:
Si introducimos caracteres hasta llenarlo, los mete en los n-1 primeros bytes, y a continuacin introduce un carcter nulo (suponiendo que el tamao del buffer es de n bytes) Si introducimos menos caracteres de los que tenamos reservados, termina la cadena con un newline (retorno de carro) y al final un carcter nulo.

La funcin sbrk sirve para solicitar memoria de forma dinmica. Busca n bytes (indicados por $a0) libres consecutivos y devuelve la direccin del primer byte libre en $v0. (NOTA: buscar si hay alguna manera de liberar el

espacio dinmico)
La funcin exit hace un que un programa termine de forma inmediata.
20

ENTRADA Y SALIDA. EJEMPLO.

21

SUBPROGRAMAS
Los subprogramas son piezas de cdigo que pueden ser invocados desde diferentes partes del programa principal o desde otra subrutina. Los principales motivos para hacer subprogramas son: descomposicin de un problema en problemas ms simples, o bien reutilizacin de cdigo. Lo habitual es que se definan con argumentos de entrada (recogidos en los registros que van desde $a0 a $a3) que variarn el comportamiento del subprograma en funcin de sus valores. Si el resultado de las operaciones se traduce en un valor que tiene que devolver se llama funcin. Si el resultado es la ejecucin de una serie de operaciones sin devolver un valor de manera explcita se llama procedimiento. General a todos los subprogramas: habr un punto de entrada que se explicitar con una etiqueta y una sentencia de retorno, que devolver el control del programa a la instruccin siguiente desde la que se invoc al subprograma.

22

SUBPROGRAMAS
En la invocacin y ejecucin de subprogramas se suelen llevar a cabo las siguientes acciones Se cargan los registros $a0-$a3 (tantos como sean necesarios) con los valores de los argumentos, o bien se cargan los parmetros que se requieran en la pila (se ver en un ejemplo) Se llama a la subrutina: jal etiqueta_subprg (esta instruccin no solo realiza un salto a la etiqueta especificada, sino que fija la direccin de retorno a la subrutina en la siguiente instruccin que debera ejecutar, es decir $ra <- PC+4 ya que las instrucciones mips ocupan 4 bytes) Hay que reservar espacio suficiente en la pila para las variables locales (si no da con los registros temporales). Ejecutar las instrucciones del subprograma. Si emite resultados explcitos (funciones) se devolvern en los registros $v0, $v1. Si con esto no fuera suficiente se deberan dejar los resultados en la cabecera de la pila. Devolver el control a la funcin llamadora, lo que corresponde con la ejecucin de la instruccin jr $ra

1.

2.

3. 4. 5.

6.

23

SUBPROGRAMAS. CONVENIOS DE USO DE LOS REGISTROS.


Cuando estudiamos los registros disponibles en MIPS vimos que por convenio ya hay algunos que deberan ser salvados y otros con carcter temporal. Lo mejor si se quiere proteger el valor de algunos registros antes de llamar a un subprograma y as evitar los indeseados efectos laterales es salvarlos en la pila, y cuando se devuelve el control a la rutina llamadora y recuperarlos al regreso de la misma. El subprograma invocado (el que es llamado) tiene la obligacin por convenio de salvar (suponiendo que los vaya a usar) y devolver intacto al subprograma llamador:
Los registros $s0-$s7 El puntero de pila $sp (stack pointer) La direccin de retorno $ra El puntero a la zona de datos globales $gp

El subprograma invocado (el que es llamado) NO tiene la obligacin de devolver intactos:


Los registros temporales $t0-$t9 Los registros argumentos $a0-$a3

El subprograma invocado (el que es llamado) obviamente podr modificar los registros $v0 y $v1 ya que es aqu donde se devuelven 24 los resultados explcitos

SUBPROGRAMAS. SUBRUTINAS ANIDADAS Y RECURSIVIDAD.


Una subrutina es anidada si desde su interior se llama a otra subrutina. Recordemos que cuando acabe la subrutina deber devolver el control del programa a la direccin de retorno. Sin embargo, si llama a otra subrutina el registro $ra se ver modificado, por lo que antes de hacer la llamada a la subrutina interior deber salvar el contenido de $ra. El lugar para salvar el contenido del registro $ra es la pila. La pila es una zona de memoria que crece hacia direcciones inferiores. El registro $sp (stack pointer) apuntar al word de memoria ltimo que se introdujo. Es igualmente usual salvar el valor de los argumentos que se usen $a0-$a3 en la pila, ya que si no se hace, al pasar los argumentos a la subrutina anidada perderemos su valor. Una subrutina recursiva es un caso particular de una subrutina anidada que se invoca a si misma.

25

SUBRUTINA. CLCULO DEL FACTORIAL EL PROGRAMA PRINCIPAL:

26

SUBRUTINA. CLCULO DEL FACTORIAL LA FUNCIN RECURSIVA FACTORIAL:

27

INSTRUCCIONES EN PUNTO FLOTANTE


MIPS tiene un coprocesador de punto flotante que opera en precisin simple (32 bits) y doble precisin (64 bits). El coprocesador tiene sus propios registros de 32 bits que que van desde el $f0 al $f31. Para ciertas operaciones se requerirn dos de estos registros, por eso de forma prctica solo se usan los pares. $f0-$f1 almacenan un doble, $f2-$f3 otro y as hasta $f30-$f31 Los registros de punto flotante tienen igualmente un convenio que se ha de respetar:
Registro $f0-$f2 $f4-$f10 $f12-$f14 $f16-$f18 $f20-$f30 Uso Valores de retorno en punto flotante a subprogramas Registros temporales. No se preservan entre llamadas Primeros 2 parmetros en punto flotante. No preservados Registros temporales. No se preservan entre llamadas Registros salvados. Se preservan entre llamadas.
28

INSTRUCCIONES EN PUNTO FLOTANTE


Instrucciones aritmticas
Ejemplo
add.s $f2,$f4,$f6 sub.s $f2,$f4,$f6 mul.s $f2,$f4,$f6 div.s $f2,$f4,$f6 add.d $f2,$f4,$f6 sub.d $f2,$f4,$f6 mul.d $f2,$f4,$f6 div.d $f2,$f4,$f6

Significado Comentario
$f2=$f4+$f6 $f2=$f4-$f6 $f2=$f4*$f6 $f2=$f4/$f6 $f2=$f4+$f6 $f2=$f4-$f6 $f2=$f4*$f6 $f2=$f4/$f6 Suma PF. Precisin simple Resta PF. Precisin simple Multiplicacin PF. Precisin simple Divisin PF. Precisin simple Suma PF. Precisin doble Resta PF. Precisin doble Multiplicacin PF. Precisin doble Divisin PF. Precisin doble 29

INSTRUCCIONES EN PUNTO FLOTANTE


Instrucciones carga y almacenamiento (c1 significa coprocesador 1) Ejemplo
lwc1 $f1,100($t2) swc1 $f1,100($t2) mov.s $f4,$f6 mov.d $f4,$f6 mtc1 $t0,$f0

Significado
$f1=Mem[$t2+100] Mem[$t2+100]=$f1 $f4 = $f6 $f4 = $f6 $f0 = $t0

Comentario
Carga en $f1 la dir. especificada Almacena en la dir. especificada el flotante almacenado en $f1 Mueve datos entre registros punto flotante de precisin simple Mueve datos entre registros punto flotante de precisin doble Es una copia cruda no pasa a flotante. Ojo porque el orden de los operandos no es el de convenio. Igual que antes es copia cruda. Ojo con el orden. 30

mfc1 $t0,$f0

$t0 = $f0

INSTRUCCIONES EN PUNTO FLOTANTE


Instrucciones de comparacin y salto
Ejemplo
bclt etiqueta bclf etiqueta c.eq.s $f2,$f4 (eq,ne,lt.le,gt,ge) c.eq.d $f2,$f4 (eq,ne,lt.le,gt,ge)

Significado
If (cond==1) go to etiqueta If (cond==0) go to etiqueta If ($f2==$f4) cond =1 else cond =0 If ($f2==$f4) cond =1 else cond =0

Comentario
Salto condicional si cond es cierto Salto condicional si cond es falso Comparacin en precisin simple. Pone cond a 1 o a 0. Comparacin en precisin doble. Pone cond a 1 o a 0.

Ejemplo:
c.eq.s $f2,$f4 bc1t exit: exit
31 # salta a la etiqueta exit si $f2==$f4

INSTRUCCIONES EN PUNTO FLOTANTE


Antes no se soportaban cargas de flotantes de forma inmediata, pero se pueden hacer a travs de etiquetas.
var1: .data .float 0.65 .text l.s

$f6, var1

# $f6=0.65

Las nuevas versionas si que dejan hacer cargas en simple y doble precisin con li.s y li.d
li.s $f4,0.65 # $f4 = 0.65

Las conversiones entre tipos se hacen de la siguiente manera:


cvt.s.w $f4, $f2 # $f4 es el destino y $f2 el fuente

La letra despus de cvt. Dice el tipo al que convierte, en este caso es simple s. La ltima letra dice el tipo desde el que convierte, en este caso entero w. Si hubira una d significa double. Ejemplo de uso:
li $t0,32 mtc1 $t0,$f2 cvt.s.w $f4,$f2 # $t0 = 32 # $f2 = 32 # $f4 = 32.0
32

EJEMPLO. CONVERSIN PTS- PROGRAMA PRINCIPAL

33

EJEMPLO. CONVERSIN PTS-


FUNCIN DE CLCULO

34

CODIFICACIN DE INSTRUCCIONES MIPS


Las instrucciones MIPS se clasifican en 4 grupos segn su formato. R-Type. Son aquellas que no requieren un valor inmediato (ni para especificar un offset). Incluyen las aritmticas y lgicas que solo usan registros, las de desplazamiento y las de salto con registro. Cdigo de operacin 000000. I-Type. Incluyen las instrucciones que usan operandos inmediatos como operandos o como etiquetas de salto. En la arquitectura MIPS todas las cargas y almacenamientos de memoria son hechas por el procesador principal, luego las operaciones de carga y almacenamiento de flotantes tambin estn incluidas en este grupo. Todos los cdigos de operacin excepto 000000, 00001x y 0100xx. J-Type. Son los dos saltos directos (j y jal). Estas instrucciones requieren una direccin de memoria en su operando. Cdigo de operacin 00001x. Instrucciones del coprocesador. Los procesadores MIPS tienen dos coprocesadores estndar CP0 maneja varios tipos de excepciones. CP1 es el coprocesador de punto flotante. Cdigos de operacin 0100xx.

35

CODIFICACIN DE INSTRUCCIONES. TIPO-R

36

CODIFICACIN DE INSTRUCCIONES. TIPO-I

37

CODIFICACIN DE INSTRUCCIONES. TIPO-J

CODIFICACIN DE INSTRUCCIONES. COPROCESADOR

38

S-ar putea să vă placă și