Está en la página 1de 84

Arquitectura de

Computadoras

Lenguaje Ensamblador
Lenguaje Ensamblador

• Introducción.
• Ventajas e inconvenientes del lenguaje
ensamblador.

• Funcionamiento del ensamblador.


• El montador de enlaces (o linker).
• Utilidades de los ensambladores.
• Lenguaje ensamblador del procesador MIPS R2000
2 Arquitectura de Computadoras
Ventajas e inconvenientes
del lenguaje ensamblador
• Ventajas del lenguaje ensamblador
• Útil cuando es crítico alguno de los siguientes factores:

• Tiempo de ejecución del programa.

• Tamaño del programa.

• El programador puede seleccionar instrucciones


específicas de la arquitectura para realizar una
determinada operación.

3 Arquitectura de Computadoras
Ventajas e inconvenientes
del lenguaje ensamblador
• Inconvenientes del lenguaje ensamblador
• Los programas son específicamente inherentes a la
máquina.
• Son de mayor tamaño que los programas equivalentes
escritos en lenguaje de alto nivel. Menor productividad
del desarrollo software.
• Los programas son difíciles de leer, escribir y pueden
contener más errores.
• Soluciones híbridas para aprovechar la fortaleza de
cada lenguaje
• La mayor parte del programa se escribe en alto nivel.
• Las secciones críticas en lenguaje ensamblador.
4 Arquitectura de Computadoras
Funcionamiento del
Ensamblador
• Un ensamblador traduce un archivo con sentencias
en lenguaje ensamblador a un archivo de
instrucciones máquina y datos binarios.

• Traducción en dos pasadas:


• Primera pasada:
Calcula las posiciones de memoria que corresponden a
los nombres simbólicos que aparecen en el programa
para que sean conocidas cuando de traduzcan las
instrucciones. Crea tabla de símbolos.

5 Arquitectura de Computadoras
Funcionamiento del
Ensamblador
• Segunda pasada:
• Traduce cada sentencia del lenguaje ensamblador al
combinar los equivalentes numéricos de los códigos de
operación, especificadores de registros y rótulos de la
tabla de símbolos en una instrucción legal.

• Rótulos o etiquetas
• Externos o globales: Pueden ser referenciados desde
otro archivo distinto de aquél en el que se define (hay
que declararlos como tales).

• Internos o locales: Sólo puede ser referenciado en el


archivo en el que se define (locales por defecto).
6 Arquitectura de Computadoras
El montador de enlaces
(linker)
• El ensamblador procesa cada archivo de un
programa de forma individual. Solamente se
conocen las direcciones de los rótulos locales.

• Necesidad de otra herramienta: El montador de


enlaces (o linker).

• Combina una colección de archivos objetos y librerías


(opcional) en otro archivo ejecutable al resolver los
rótulos externos.

• El ensamblador asiste al montador suministrándole una


tabla de símbolos o rótulos y referencias no resueltas.

7 Arquitectura de Computadoras
El montador de enlaces
(linker)

8 Arquitectura de Computadoras
Utilidades de los
Ensambladores
• Los ensambladores proporcionan diversas
características (utilidades) que facilitan al
programador la escritura de los programas.

• Utilidades:
• Directivas para organizar datos en memoria.

• Permite al programador describir los datos de una manera


más concisa y natural que la representación binaria: decimal,
ASCII, hexadecimal,...

9 Arquitectura de Computadoras
Utilidades de los
Ensambladores
• Utilidades:
• Macros
• Permiten nombrar una secuencia de instrucciones
frecuentemente utilizada. No confundir con procedimiento o
subrutina.
• Pseudoinstrucciones
• Son proporcionadas por algunos lenguajes ensambladores y
no forman parte del repertorio de instrucciones del
procesador. El ensamblador las sintetiza a partir de
instrucciones puras del procesador.

• Utilización de símbolos
• Muy útil en instrucciones de control de flujo o para hacer
referencia a los datos.

10 Arquitectura de Computadoras
Lenguaje Ensamblador
MIPS R2000
• Componentes de un procesador MIPS
• Modos de direccionamiento
• Sintaxis del ensamblador
• Directivas del ensamblador soportadas por el
simulador SPIM.

• Formato de las instrucciones.

11 Arquitectura de Computadoras
Lenguaje Ensamblador
MIPS R2000
• Repertorio de instrucciones
• Aritméticas

• Lógicas

• Transferencia de datos

• Movimiento de datos

• Comparación

• Salto y bifurcación

• Ejemplo de programa en ensamblador


12 Arquitectura de Computadoras
Componentes de
Procesador MIPS
• Componentes
• CPU
• Dos coprocesadores: 0 y 1.
• CPU: 32 registros de propósito general
• $0: Siempre contiene 0
• $1-$31: Propósito general
• C0: 4 registros
• BadVAddr (reg. Nº 8), Status (reg. Nº 12)
• Cause (reg. Nº 13), EPC (reg. Nº 14)
• C1: 32 registros para punto flotante
• 16 registros simple precisión
$f0, $f2, …. $f30 (32 bits)
• 16 registros doble precisión (64 bits
$f0-$f1, $f2-$f3, …. $f30-$f31

13 Arquitectura de Computadoras
Uso de Memoria en MIPS

14 Arquitectura de Computadoras
Modos de
Direccionamiento

15 Arquitectura de Computadoras
Sintaxis del Ensamblador
• Líneas de comentarios
• Todo lo que haya a partir del simbolo # hasta el final de
línea se ignora.

• Directivas
• Secuencia de caracteres, (_) y (.) que no empiezan por
un número.

• Etiquetas
• Se declaran colocándolas al principio de línea y
terminadas en (:).

16 Arquitectura de Computadoras
Sintaxis del Ensamblador
• Número decimales y hexadecimales
• Números en base 10 por defecto.

• Hexadecimales o en base 16 precedidos por 0x.

• Cadenas o strings
• Las cadenas están encerradas entre dos comillas (“).

• Caracteres especiales:

• \n Nueva línea

• \t Tab

• \” Comillas
17 Arquitectura de Computadoras
Ejemplo de Sintaxis
############################################################################
# Sintaxis del ensamblador #
############################################################################

# Comienzo del segmento de datos

.data 0x10000000
init: .word 0x10,25,0x11223344 # declaración de 3 variables tipo word (4 bytes)

string: .asciiz “Soy una cadena \n” # declaración de una cadena

# Comienzo del segmento de código


.text 0x400000
.globl main # declaramos la etiqueta “main” como global
main: lw $t0,-8($s0) # comentario
addi $t0,$t0,1 # comentario

18 Arquitectura de Computadoras
Directivas del
Ensamblador
SPIM de las directivas del
• SPIM soporta un subconjunto
ensamblador MIPS

19 Arquitectura de Computadoras
Formato de Instrucciones
• Solo tres formatos

20 Arquitectura de Computadoras
Instrucciones Aritméticas

21 Arquitectura de Computadoras
Instrucciones Lógicas

22 Arquitectura de Computadoras
Instrucciones de
Transferencias de Datos

23 Arquitectura de Computadoras
Instrucciones de
Movimiento de datos

24 Arquitectura de Computadoras
Instrucciones de
Comparación

25 Arquitectura de Computadoras
Instrucciones de Salto y
Bifurcación

26 Arquitectura de Computadoras
Operaciones Aritméticas
• En las siguientes transparencias se muestran varios
ejemplos en ensamblador MIPS para realizar
operaciones aritméticas.

• Se partirá de la expresión en C para estudiar cómo


se implanta dicha expresión en ensamblador.

• Características de las operaciones aritméticas


MIPS:

• Operaciones de 3 direcciones.

• Operandos y resultados han de estar en registros.

• Un operando puede ser una constante de 16 bits.


27 Arquitectura de Computadoras
Operaciones Aritméticas

• La expresión en C:
• int a, b, c;
c = a + b;

• Se traduce en ensamblador (suponiendo la


asignación de registros: a→s0, b→s1 y c→s2)
como:

• add $s2, $s0, $s1

28 Arquitectura de Computadoras
Operaciones Aritméticas
• ¿Cómo se traduce en ensamblador la expresión en
C?

• int a, b, c, d, e;
a = b + c + d + e;

• Suponiendo la asignación de registros: a→s0,


b→s1, c→s2, d→s3 y e→s4, se necesitan ahora
tres instrucciones:

• add $s0, $s1, $s2 # a contiene b+c


add $s0, $s0, $s3 # ahora a vale b+c+d
add $s0, $s0, $s4 # y por fin a es b+c+d+e

29 Arquitectura de Computadoras
Operaciones Aritméticas
• ¿Cómo se traduce en ensamblador la expresión en
C?

• int a, b, c, d, e;
a = (b + c) - (d + e);

• Se realiza la asignación de registros: a→s0, b→s1,


c→s2, d→s3 y e→s4.

• add $t0, $s1, $s2 # se usa t0 para b+c


add $t1, $s3, $s4 # se usa t1 para d+e
sub $s0, $t0, $t1 # s0 vale ahora t0-t1

30 Arquitectura de Computadoras
Acceso a Memoria

• Es necesario acceder a memoria para usar:


• Vectores y matrices.

• Estructuras de datos.

• Variables que no están en registros.

31 Arquitectura de Computadoras
Acceso a Memoria:
Organización
• El bus de datos del MIPS es de 32 bits.
Es posible direccionar cada byte individualmente.

• Dirección de palabra = msB lsB

dir. byte más significativo: 8 8 9 A B


Arquitectura big endian
Dir.
4 4 5 6 7
• Dirección de palabra = Palabras

múltiplo de 4 0 0 1 2 3
Restricción de alineación
Dir. Bytes

32 Arquitectura de Computadoras
Acceso a Memoria:
Ejemplos
• ¿Cómo se traduce en ensamblador la expresión en
C?

• int a, b, V[40];
a = b + V[8];

• Se realiza la asignación de registros: a→s0, b→s1,


V→s2.

• lw $t0, 32($s2) # t0 se carga con V[8]


add $s0, $s1, $t0 # se realiza la operación

33 Arquitectura de Computadoras
Acceso Memoria:
Ejemplos
• ¿Cómo se traduce en ensamblador la expresión en
C?

• int a, b, V[40], i;
a = b + V[i];

• Se realiza la asignación de registros: a→s0, b→s1,


V→s2, i→s3.

• add $t1, $s3, $s3 # t1 = 2*i


add $t1, $t1, $t1 # t1 = 4*i
add $t1, $t1, $s2 # t1 = dir. de V[i]
lw $t0, 0($t1) # t0 se carga con V[i]
add $s0, $s1, $t0 # se realiza la operación

34 Arquitectura de Computadoras
Codificación en Lenguaje
de Máquina
• Dentro del ordenador sólo hay 0’s y 1’s.
Las instrucciones han de codificarse en binario.

• Por ejemplo:
add $t0, $s1, $s2
Se traduce en una secuencia de 32 1’s y 0’s:
000000 10001 10010 01000 00000 100000

• La representación binaria está dividida en campos


para simplificar su decodificación en el hardware.

35 Arquitectura de Computadoras
Codificación en Lenguaje
de Máquina

36 Arquitectura de Computadoras
Codificación en Lenguaje
de Máquina

37 Arquitectura de Computadoras
Codificación en Lenguaje
de Máquina
• ¿Cómo es el código máquina de la expresión en C?
int a, V[400];
V[300] = V[300] + a;

• Si se realiza la asignación de registros: a->s0, V-


>s1.

38 Arquitectura de Computadoras
Codificación en Lenguaje
de Máquina
• La codificación en binario es:

• La única diferencia entre la 1a y la 3a instrucción es


el tercer bit.

39 Arquitectura de Computadoras
Toma de Decisiones

• La toma de decisiones es lo que distingue a un


ordenador de una calculadora.

• Permite ejecutar distintas instrucciones en función


de datos de entrada o resultados de cálculos.

• En MIPS se incluyen 2 instrucciones para toma de


decisiones:

• beq reg1, reg2, L1

• bne reg1, reg2, L1

40 Arquitectura de Computadoras
Toma de Decisiones:
Ejemplo
• ¿Cómo se traduce en ensamblador la expresión en
C?
int a, b, c, i, j;
if(i == j) goto L1;
b = b + c;
L1: a = b - c;

• Si las variables a-j se asignan a los registros s0-s4.


beq $s3, $s4, L1 # Si i==j ir a L1
add $s1, $s1, $s2 # se ejecuta si i!=j
L1: sub $s0, $s1, $s2 # se ejecuta siempre

41 Arquitectura de Computadoras
Toma de Decisiones:
Ejemplo
• int a, b, c, i, j;
if(i == j){
a = b + c;
}else{
a = b - c;
}

• Se traduce en (a-j se asignan a los registros s0-s4):


bne $s3, $s4, SiNo # Si i!=j ir a SiNo
add $s0, $s1, $s2 # se evita si i!=j
j Fin # Salta a Fin
SiNo: sub $s0, $s1, $s2 # se ejecuta si i!=j
Fin:
42 Arquitectura de Computadoras
Toma de Decisiones:
Lazos
• int a, V[100], i, j, k;
Bucle: a = a + V[i];
i = i + j;
if( i != k) goto Bucle;

• Se traduce en (a-k se asignan a los registros s0-s4):


Bucle: add $t1, $s2, $s2 # t1 = 2i
add $t1, $t1, $t1 # t1 = 4i
add $t1, $t1, $s1 # t1 = dir. de V[i]
lw $t0, 0($t1) # t0 = V[i]
add $s0, $s0, $t0 # a = a + V[i]
add $s2, $s2, $s3 #i=i+j
bne $s2, $s4, Bucle # si i!=k salta
43 Arquitectura de Computadoras
Toma de Decisiones:
Lazos
• int a, V[100], i, j, k;
while(V[i] == k){
i = i + j;
}

• Se traduce en (a-k se asignan a los registros s0-s4):


Bucle: add $t1, $s2, $s2 # t1 = 2i
add $t1, $t1, $t1 # t1 = 4i
add $t1, $t1, $s1 # t1 = dir. de V[i]
lw $t0, 0($t1) # t0 = V[i]
bne $t0, $s4, Fin # si i!=k salta
add $s2, $s2, $s3 # i = i +j
j Bucle
Fin:

44 Arquitectura de Computadoras
Toma de Decisiones:
Menor que
• Las comparaciones más habituales en los
programas son la igualdad y la desigualdad.

• Es necesario también saber si una variable es


menor que otra. Para ello MIPS define la
instrucción slt (set on less than).

• Por ejemplo: la instrucción slt $t0, $s3, $s4


Pone a 1 t0 si s3 es menor que s4. Si no t0 se
pone a 0.

• Combinando slt, bne, beq y el registro zero se


pueden realizar todas las comparaciones.

45 Arquitectura de Computadoras
Toma de Decisiones:
Ejemplo
• int a, b, c, i, j;
if(i >= j){
a = b + c;
}

• Se traduce en (a-j se asignan a los registros s0-s4):


slt $t0, $s3, $s4 # evalúa i < j
bne $t0, $zero, Fin # si i<j salta
add $s0, $s1, $s2 #a=b+c
Fin:

46 Arquitectura de Computadoras
Llamada a Funciones

• Las funciones permiten programas estructurados,


reutilizar código, etc.

• Dos aspectos importantes:


• Tienen un interfaz bien definido: Parámetros de
entrada y resultados de salida.

• Realizan su trabajo sin interferir con la función


que las llama.

47 Arquitectura de Computadoras
Llamada a Funciones
• Para poder ejecutar una función es necesario:
1. Situar los parámetros donde la función llamada
pueda leerlos. a0-a3, pila
2. Transferir el control a la función llamada.
3. Reservar espacio para las variables locales.
t0-t9, pila.
4. Realizar la tarea necesaria.
5. Situar el resultado donde la función llamante
pueda leerlos. v0-v1, pila
6. Devolver el control a la función llamante.
Estructura
48 Arquitectura de Computadoras
Llamada a Funciones:
Instrucción jal
• Al transferir el control a la función es necesario
guardar la dirección de retorno.

• En el MIPS esta tarea la realiza la instrucción jal


(jump and link)

• Formato: jal Dir_de_la_función


• Funcionamiento:
• Guarda la dirección de retorno (PC+4) en el
registro ra.

• Salta a la dirección Dir_de_la_función.

49 Arquitectura de Computadoras
Llamada a Funciones:
Instrucción jr
• Para volver de una función es necesario saltar a
la dirección almacenada en ra

• En el MIPS esta tarea se realiza con la


instrucción jr (jump register).

• Formato: jr registro
• Funcionamiento: Salta a la dirección almacenada
en el registro.

• Por tanto, el retorno de la función se realiza con:


jr $ra

50 Arquitectura de Computadoras
Llamada a Funciones:
Ejemplo
• int funHoja(int g, int h, int i, int j)
{
int f;
f = (g + h) - (i + j);
return f;
}

• Se traduce en (g-j se pasan en los registros a0-a3):


funHoja: add $t0, $a0, $a1 # t0 = g + h
add $t1, $a2, $a3 # t1 = i + j
sub $t0, $t0, $t1 # t0 = (g+h) - (i+j)
add $v0, $t0, $zero # v0 = t0
jr $ra
51 Arquitectura de Computadoras
Llamada a Funciones:
Anidamientos
• En el ejemplo anterior se mostró una función hoja.
• Lamentablemente hay funciones que llaman a otras
funciones.

• En estos casos es necesario:


• Guardar la dirección de retorno ra

• Guardar los registros (a0-a3 y t0-t9) que se necesiten


después.

• Obviamente estos registros se guardan en la pila.


52 Arquitectura de Computadoras
Llamada a Funciones:
Ejemplo
• int fact(int n)
{
if (n < 1){
return 1;
}else{
return n * fact(n-1);
}
}

• Se traduce en (n se pasa en el registro a0):


53 Arquitectura de Computadoras
Llamada a Funciones:
Ejemplo
• fact: slti $t0, $a0, 1 # n<1 ?
beq $t0, $zero, L1 # Si n>=1, a L1
addi $v0, $zero, 1 # devuelve 1
jr $ra
L1: subi $sp, $sp, 8 # Reserva 2 palabras en pila
sw $ra, 4($sp) # guarda ra y
sw $a0, 0($sp) # n en pila
subi $a0, $a0, 1 # a0=n-1
jal fact
lw $a0, 0($sp) # restaura n
lw $ra, 4($sp) # y ra
addi $sp, $sp, 8 # ajusta sp
mult $v0, $a0, $v0 # devuelve
jr $ra # n * fact(n-1)

54 Arquitectura de Computadoras
Llamada a Funciones:
Bloque de Activación
• La pila crece y decrece durante la ejecución de la
función para:

• Almacenar variables locales.

• Evaluar expresiones.

• Guardar registros.

• El segmento de la pila que contiene todos los datos


de una función se denomina bloque de activación

• Algunos programas usan el registro fp para apuntar


al principio del bloque de activación.

55 Arquitectura de Computadoras
Llamada a Funciones: Paso
de Argumentos por la Pila
• Si hay más de 4 parámetros o alguno de éstos no
cabe en registros se pasan por la pila.

• Convención software: se sitúan por encima del


bloque de activación.

56 Arquitectura de Computadoras
Manejo de Caracteres
• Los caracteres se codifican en ASCII.
• Un carácter ASCII ocupa 1 byte.
• El MIPS dispone de dos instrucciones para cargar y
almacenar bytes:
• lb (load byte). Lee un byte de la memoria y lo
almacena en los 8 bits menos significativos del
registro destino. Ej. lb $t0, 0($s0).
• sb (store byte). Almacena los 8 bits menos
significativos del registro origen en la memoria.
Ej. sb $t0, 0($s0).
• Los caracteres pueden estar en cualquier posición
de memoria.
57 Arquitectura de Computadoras
Manejo de Caracteres:
Ejemplo
• El siguiente ejemplo muestra la función strcpy de
C:
void strcpy(char dest[], char orig[])
{
int i;
i = 0;
/*Copia y comprueba final*/
while( (dest[i] = orig[i]) != NULL){
i++;
}
}

• ¿Cuál es la traducción a ensamblador MIPS?


58 Arquitectura de Computadoras
Manejo de Caracteres:
Ejemplo
• strcpy:
add $t0, $zero, $zero # i = 0
L1: add $t1, $t0, $a1 # t1=dir(orig[i])
lb $t2, 0($t1) # t2 = orig[i]
add $t3, $t0, $a0 # t3=dir(dest[i])
sb $t2, 0($t3) # dest[i] = t2
add $t0, $t0, 1 # i++
bne $t2, $zero, L1
jr $ra

59 Arquitectura de Computadoras
Aritmética: Números con y
sin Signo
• El MIPS trabaja con “ristras” de 8, 16 o 32 bits.
• Estas ristras de bits pueden representar, entre otras
cosas:

• Un número sin signo (rango 0 a 2n - 1).

• Un número con signo en complemento a 2 (rango -2n-1


a 2n-1 - 1).

• Tanto las instrucciones aritméticas como las de


carga y comparación han de distinguir si sus
operandos son con o sin signo.

60 Arquitectura de Computadoras
Aritmética: Números con y
sin Signo
• Cuando se carga un número con signo de 16 u 8
bits en un registro de 32, es necesario extender el
bit designo. Ej:

• -1 en 8 bits es 11111111

• -1 en 16 bits es 11111111 11111111

• -1 en 32 bits es 11111111 11111111 11111111


11111111

• Esta extensión es necesaria porque los circuitos


aritméticos operan sólo con números de 32 bits.

61 Arquitectura de Computadoras
Aritmética: Números con y
sin Signo
• Las instrucciones de carga vistas hasta ahora cargan
números con signo:

• lb carga un byte extendiendo el signo.

• lh carga una media palabra (16 bits) extendiendo el


signo. La media palabra ha de estar en una dirección
par.

• lw carga una palabra. No tiene sentido extender el


signo, pues no hay más bits.

62 Arquitectura de Computadoras
Aritmética: Números con y
sin Signo

• Las instrucciones de carga para números sin signo


son:

• lbu carga un byte sin extender el signo.

• lhu carga una media palabra (16 bits) sin extender el


signo.

• lw carga una palabra. No tiene sentido extender


el signo, pues no hay más bits.

63 Arquitectura de Computadoras
Aritmética: Números con y
sin Signo
• Las instrucciones de comparación son distintas para
números con signo o sin signo:

• slt compara dos números con signo.

• sltu compara dos números sin signo.

• slti Compara un registro con una constante.


Ambas con signo.

• sltiu Compara un registro con una constante.


Ambas sin signo.

• Ej: slti $t0, $s0, -7


64 Arquitectura de Computadoras
Aritmética: Números con y
sin Signo
• Ejemplo:
• s0 = 11111111 11111111 11111111 11111111

• s1 = 00000000 00000000 00000000 00000001

• ¿Cuanto valen t0 y t1 después de ejecutar las


instrucciones?
slt $t0, $s0, $s1 # Con signo
sltu $t1, $s0, $s1 # Sin signo

65 Arquitectura de Computadoras
Aritmética: Suma y Resta

• En las instrucciones de suma y resta puede ser


necesario saber si ha existido un desbordamiento.

• En los números sin signo, utilizados para aritmética de


direcciones, se ignora.

• En los números con signo, dependiendo de la


aplicación, puede ser necesario detectarlo.

66 Arquitectura de Computadoras
Aritmética: Suma y Resta
• MIPS dispone de dos tipos de instrucciones para la
suma y la resta en función del tratamiento del
desbordamiento.

• add, addi, sub, generan una excepción si se produce un


desbordamiento.

• addu, addiu, subu no generan excepciones en caso de


desbordamiento.

• Las instrucciones de suma se han estudiado antes.


La instrucción sub $t0, $s0, $s1 resta s0-s1 y
almacena el resultado en t0.

67 Arquitectura de Computadoras
Aritmética: Suma y Resta

• addu $t0, $t1, $t2 # suma sin desbordamiento


xor $t3, $t1, $t2 # signos distintos?
slt $t3, $t3, $zero #si t3<0 signos distintos
bne $t3, $zero, NoDesb # si signos distintos
# => no desb.
xor $t3, $t0, $t1 # si signos iguales
slt $t3, $t3, $zero # ¿suma también?
bne $t3, $zero, Desb # Si sign(suma)!= sign(op)
# => desbordamiento

68 Arquitectura de Computadoras
Aritmética: Suma y Resta

• addu $t0, $t1, $t2 # suma sin desbordamiento


nor $t3, $t1, $zero # t3 = not(t1) =
# C2(t1) - 1 = 2^32 -t1-1
sltu $t3, $t3, $t2 # 2^32 -t1-1 < t2 =>
# 2^32 -1 < t1 + t2 =>
# desbordamiento.
bne $t3, $zero, Desb

69 Arquitectura de Computadoras
Aritmética: Multiplicación
• El MIPS dispone de dos instrucciones para
multiplicar: mult (con signo) o multu (sin signo).

• El resultado se almacena en un registro de 64 bits,


accesible en su mitad superior hi y en su mitad
inferior lo mediante las instrucciones mfhi y mflo.

• Ej: mult $s0, $s1 multiplica s0 por s1


• Estas instrucciones no detectan desbordamientos.
El resultado cabrá en 32 bits si hi vale 0 en multu o
la repetición del bit de signo en mult.

70 Arquitectura de Computadoras
Aritmética: División

• El MIPS dispone de dos instrucciones para dividir:


div (con signo) o divu (sin signo).

• El cociente se almacena en lo y el resto en hi.


• Ej: div $s0, $s1 divide s0 entre s1
• Estas instrucciones no detectan división por cero.

71 Arquitectura de Computadoras
Aritmética Ejemplo:
(a0+a1)*a2/a3
1 func: beq $a3, $zero, Error
2 add $t0, $a0, $a1
3 mult $t0, $a2
4 mflo $t0
5 mfhi $t1
6 slt $t2, $t0, $zero #res<0?
7 bne $t2, $zero, Nega
8 bne $t1, $zero, Error #res>0
9 j L1
10 Nega: sltiu $t2, $t1, -1 # -1=0xffff
11 bne $t2, $zero, Error
12 L1: div $t0, $a3
13 mflo $v0
14 add $v1, $zero, $zero
15 jr $ra
16 Error: addi $v1, $zero, 1
17 jr $ra

72 Arquitectura de Computadoras
Aritmética y Lógica
• Aparte de la +,-,* y /, el MIPS dispone de una serie
de operaciones lógicas y aritméticas adicionales:

• and dest, orig1, orig2

• andi dest, orig1, const

• or dest, orig1, orig2

• ori dest, orig1, const

• xor dest, orig1, orig2

• xori dest, orig1, const

• nor dest, orig1, orig2


73 Arquitectura de Computadoras
Aritmética y Lógica
• Por último, el MIPS dispone de una serie de
instrucciones de desplazamiento de bits.

• Despl. lógico a izq.: sll rd, ro, desp

• Despl. lógico a izq. var.: sllv rd, ro, rdes

• Despl. lógico a der.: srl rd, ro, desp

• Despl. lógico a der. var.: srlv rd, ro, rdes

• Despl. aritmético a der.: sra rd, ro, desp

• Despl. arit. a der. var.: srav rd, ro, rdes

74 Arquitectura de Computadoras
Aritmética y Lógica:
Ejemplo
• int a, V[100], i, j, k;
while(V[i] == k){
i = i + j;
}

• Se traduce en (a-k se asignan a los registros s0-s4):


Bucle: sll $t1, $s2, 2 # t1 = 4i
add $t1, $t1, $s1 # t1 = dir. de V[i]
lw $t0, 0($t1) # t0 = V[i]
bne $t0, $s4, Fin # si i!=k salta
add $s2, $s2, $s3 #i=i+j
j Bucle
Fin:
75 Arquitectura de Computadoras
Carga de Constantes

• Hasta ahora se ha visto cómo cargar una constante


de 16 bits en un registro.

• Para cargar un valor de 32 bits (p. ej. 0x12345678)


son necesarias dos instrucciones:

• lui $s0, 0x1234

• ori $s0, $s0, 0x5678

• La pseudoinstrucción li hace el mismo trabajo:


li $s0, 0x12345678

76 Arquitectura de Computadoras
Ejemplo1 (Repita para)
# for (i=0; i<N ; i++)
#{
# x=x+i;
#}
.data
i: .word 0
N: .word 19,35,23
x: .word -2
.text
.globl main
main: lw $t0, i($zero) # i <- $t0
lw $t1, N($zero) # N <- $t1
lw $t2, x($zero) # x <- $t2
OtraLabel: # Emulación for
bge $t0, $t1, Salto # i<N
add $t2, $t2, $t0 # cuerpo del ciclo for
addi $t0, $t0, 1 # i++
j OtraLabel # loop para volver a evaluar {}
Salto: j Salto

77 Arquitectura de Computadoras
Ejemplo 2 (Caso de)
# switch a
# case a0: x=x+a0;
# break;
# case a1: x=x+a1;
# break;
# case a2: x=x+a2;
# break;
# default: x=a0+a1+a2;
# break;

.data
a: .byte 10
a0: .half 1
a1: .half 2
a2: .half 3
x: .word -1

.text
.globl main

78 Arquitectura de Computadoras
Ejemplo 2 (Caso de)
main:
lb $t0,a($zero) # $t0 <- a
lh $t1,a0($zero) # $t1 <- a0
lh $t2,a1($zero) # $t2 <- a1
lh $t3,a2($zero) # $t3 <- a2
lw $t4,x($zero) # $t4 <- x
beq $t0, $t1, Casea0
beq $t0, $t2, Casea1
beq $t0, $t3, Casea2
j Casedf

Casea0:
add $t4,$t4,$t1 # x=x+a0
j EndCase
Casea1:
add $t4,$t4,$t2 # x=x+a1
j EndCase:

79 Arquitectura de Computadoras
Ejemplo 2 (Caso de)

Casea2:
add $t4,$t4,$t3 # x=x+a2
j EndCase
Casedf:
add $t4,$t1,$t2 # x=a0+a1
add $t4,$t4,$t3 # x= x+a3
j EndCase
EndCase:
li $v0, 10 # Procedimiento estándar de término programa
syscall

li $v0, 1
move $a0,$t4
syscall

80 Arquitectura de Computadoras
Ejemplo 3 (contar letras de
una cadena)
.data
frase: .asciiz "123456789012345678901234567890"
letras: .byte 0
i: .byte 0
msg1: .asciiz "Ingrese un texto: "
msg2: .asciiz "La frase: "
msg3: .asciiz "Tiene "
msg4: .asciiz " letras a."

.text
.globl main

main:
# Rutina para imprimir msg1
la $a0, msg1 #Doy la dirección donde parte el string a imprimir
li $v0, 4 #almaceno un 4 en $v0 que es la llamada para
#imprimir un string
syscall #hago la llamada

81 Arquitectura de Computadoras
Ejemplo 3 (contar letras de
una cadena)
# Rutina para leer frase desde consola
li $v0, 8 #carga el syscal para leer un String
li $a1,29 #leer maximo 29 caracteres
la $a0,frase
syscall
lb $t2,i($zero) #guarda i en $t2 e inicializa
add $t2,$zero,$zero
lb $t1,letras($zero) #guarda letras en $t2 e inicializa
add $t1,$zero,$zero
addi $t4,$zero,97 #almacena en $t4 ascii de a
addi $t5,$zero,65 #almacena en $t4 ascii de A
loop: lb $t3,frase($t2) #lee i-esima letra
beq $t3,$t4,Era_a #compara la letra leida con a y A
beq $t3,$t5,Era_A
beq $t3,$zero, Salir #compara con 0 para saber si termino
j imasmas
Era_a: addi $t1,$t1,1 #incrementa cantidad de letras
j imasmas
Era_A: addi $t1,$t1,1 #incrementa cantidad de letras
j imasmas
imasmas: addi $t2,$t2,1 #incrementa posicion del indice
j loop #al string leido

82 Arquitectura de Computadoras
Ejemplo 3 (contar letras de
Salir:
una cadena)
# Rutina para imprimir msg2
la $a0, msg2 #Doy la dirección donde parte el string a imprimir
li $v0, 4 #almaceno un 4 en $v0 que es la llamada para imprimir un string
syscall #hago la llamada
# Rutina para imprimir frase
la $a0, frase #Doy la dirección donde parte el string a imprimir
li $v0, 4 #almaceno un 4 en $v0 que es la llamada para imprimir un string
syscall #hago la llamada
# Rutina para imprimir msg3
la $a0, msg3 #Doy la dirección donde parte el string a imprimir
li $v0, 4 #almaceno un 4 en $v0 que es la llamada para imprimir un string
syscall #hago la llamada
# Rutina para imprimir un entero
move $a0, $t1 #Doy la dirección donde parte el string a imprimir
li $v0, 1 #almaceno un 4 en $v0 que es la llamada para imprimir un string
syscall #hago la llamada
# Rutina para imprimir msg4
la $a0, msg4 #Doy la dirección donde parte el string a imprimir
li $v0, 4 #almaceno un 4 en $v0 que es la llamada para imprimir un string
syscall #hago la llamada
li $v0, 10
syscall

83 Arquitectura de Computadoras
Más Información
• En este tema sólo se han mostrado algunas de las
instrucciones disponibles en el MIPS.

• Un listado completo se encuentra en el apéndice A


de (Patterson y Hennessy, 2000), disponible on-line
en la página del SPIM.
http://www.cs.wisc.edu/~larus/spim.html

• Los manuales completos de la arquitectura MIPS


(MIPS Technologies, 2002) se encuentran también
disponibles on-line en la página de MIPS
Technologies. http://www.mips.com/

84 Arquitectura de Computadoras

También podría gustarte