Вы находитесь на странице: 1из 63

ICAIdea

Estructura de Computadores
Captulo 3b: Programacin en
ensamblador del MIPS.
Jos Daniel Muoz Fras
Universidad Ponticia Comillas. ETSI ICAI.
Departamento de Electrnica y Automtica
Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 1
ICAIdea
ndice
1. Introduccin.
2. Registros disponibles.
3. Operaciones aritmticas.
4. Acceso a memoria.
5. Codicacin en lenguaje mquina.
6. Toma de decisiones.
7. Llamadas a funciones.
8. Manejo de caracteres.
9. Aritmtica.
Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 2
ICAIdea
Introduccin
En este tema se va a estudiar en detalle la
arquitectura MIPS. Se estudiar:

El juego de instrucciones.

El lenguaje ensamblador y la codicacin de


instrucciones.

Los recursos disponibles.


Cada arquitectura tiene su propio juego de
instrucciones y su propio ensamblador, aunque todos
son similares.
El aprendizaje se apoyar con prcticas de laboratorio.
Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 3
En el tema anterior se han estudiado las caractersticas que debe cumplir un juego de
instrucciones. En este captulo se va a mostrar en detalle el juego de instrucciones de la arqui-
tectura MIPS, as como las tcnicas de programacin en ensamblador en dicha arquitectura.
Como probablemente sabr, cada procesador tiene su propia arquitectura y su propio len-
guaje ensamblador. Por tanto puede parecer una prdida de tiempo aprender un ensamblador
concreto, ya que ste slo servir para programar una arquitectura. No obstante lo anterior no
es cierto por dos razones fundamentales:

La losofa de programacin en ensamblador es idntica para todas las arquitecturas.


En todas ellas, las operaciones que se pueden realizar son muy bsicas y es necesario
bajar al nivel de la mquina.

Aunque cada arquitectura tiene un juego de instrucciones propio, todas las arquitectu-
ras incorporan una serie de instrucciones bsicas con funcionalidades muy parecidas.
Por ejemplo todas las arquitecturas incluyen la instruccin ADD para realizar una su-
ma. Las diferencias estarn en el nmero de operandos que admiten o en el nemnico.
Por tanto, una vez que se ha aprendido a programar en ensamblador con una arquitectura,
programar otra es cuestin del poco tiempo que lleva familiarizarse con ella.
Este tema se basa en el captulo 3 de (Patterson y Hennessy, 2000).
En el laboratorio se usar el simulador SPIM,
1
disponible en:
http://www.cs.wisc.edu/larus/spim.html
1
El nombre SPIM es simplemente MIPS escrito al revs.
ICAIdea
Registros disponibles
MIPS dispone de:

32 registros de 32 bits para enteros

32 registros de 32 bits para coma otante.

Un contador de programa de 32 bits

Dos registros de 32 bits para almacenar los


resultados de multiplicaciones y divisiones.
Existe una convencin software para el uso de los
registros enteros.
Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 4
La primera caracterstica que debe conocer un programador sobre una arquitectura es
qu registros estn disponibles.
En el caso del MIPS, se dispone de un banco de registros para almacenar nmeros enteros
y otro para almacenar nmeros en coma otante. Ambos bancos constan de 32 registros de
32 bits. En el caso del banco de coma otante, los registros se pueden agrupar de dos en dos
para utilizarlos en operaciones con nmeros en doble precisin (64 bits).
Adems de estos bancos, la arquitectura MIPS dene tres registros adicionales: el conta-
dor de programa y dos registros llamados Hi y Lo que se utilizan para almacenar el resultado
de las operaciones de multiplicacin y divisin enteras. En el caso de la multiplicacin, re-
cuerde que el producto de dos nmeros de 32 bits da como resultado un nmero de 64 bits.
De la misma forma, el cociente de dos nmeros de 32 bits da como resultado un cociente de
32 bits y un resto tambin de 32 bits.
Aunque para el procesador todos los registros son iguales, existe una convencin seguida
por todos los programadores para el uso de los registros para enteros, la cual pasamos a
describir a continuacin.
ICAIdea
Registros disponibles
0 zero Constante 0
1 at Reservado para el ensamblador
2 v0 Evaluacin de expresiones
3 v1 y retorno de resultados
4 a0 Argumentos de funciones

7 a3
8 t0 Valores temporales
La invocada puede modicarlos
15 t7 La invocadora debe guardarlos
Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 5
En la tabla de esta transparencia y la siguiente se muestran los registros enteros del
MIPS junto con el uso que se debe hacer de ellos. Como se dijo antes, para el procesador
todos los registros (excepto el 0) son iguales. Sin embargo para hacer ms fcil y eciente
la programacin, existe una convencin de uso de estos registros que se describe en detalle a
continuacin:

El registro zero contiene siempre la constante 0. La utilidad de este registro se


ver ms adelante.

El registro at est reservado para ser usado por el ensamblador.

Los registros v0 y v1 se utilizan para evaluar expresiones y para que las funciones
puedan devolver sus resultados.

Los registros a0 a3 se utilizan para pasarle argumentos a las funciones. Si son


necesarios ms de 4 argumentos (o stos necesitan ms de 32 bits) se recurre a la
pila.

Los registros t0 t7 se utilizan para almacenar valores temporales. Por tanto cual-
quier funcin puede usarlos sin preocuparse de guardar su valor anterior. Ahora bien,
si una funcin necesita algn valor almacenado en estos registros ha de guardarlo en
otro sitio (memoria, registros) antes de llamar a otra funcin (la invocada), pues sta
supondr que dichos registros slo contienen valores intiles para quien la ha llamado
(la invocadora).
ICAIdea
Registros disponibles
16 s0 Salvados por la invocada
La invocada debe guardarlos
23 s7 antes de usarlos
24 t8 Valores temporales
25 t9 Idem ant.
26 k0 Reservados para el
27 k1 sistema operativo
28 gp Puntero al rea global
29 sp Puntero de pila (stack pointer)
30 fp Puntero al bloque de activacin (frame pointer)
31 ra Direccin de retorno (return address)
Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 6

Los registros s0 s7 se utilizan para almacenar variables que deben ser preservadas
entre llamadas a funciones. Por tanto, si alguna funcin necesita usar alguno de estos
registros, ha de guardar antes su valor (por ejemplo en la pila). De esta forma, la
funcin que usa estos registros no ha de preocuparse de guardar sus valores antes de
llamar a otra funcin.

Los registros t8 y t9 se utilizan de la misma manera que los registros t0 t7.

Los registros k0 y k1 estn reservados para el sistema operativo.

El registro gp se utiliza para apuntar al rea de memoria donde estn los datos del
programa. Su utilidad se ver ms adelante.

El registro sp es el puntero de la pila (contiene la direccin del tope de la pila).

El registro fp contiene la direccin de la zona de la pila en la que estn guardados


los argumentos y las variables locales de la funcin que no caben en los registros.
Esta zona se conoce como bloque de activacin. Su utilidad es la de simplicar el
acceso a estas variables cuando es necesario modicar la pila durante la ejecucin de
la funcin (por ejemplo durante la evaluacin de expresiones).

Por ltimo, el registro ra contiene la direccin a la que debe retornar la funcin in-
vocada cuando nalice su labor. El funcionamiento detallado de estos tres ltimos
registros se ver cuando se estudie el mecanismo de llamada a funciones de la arqui-
tectura MIPS.
ICAIdea
Operaciones aritmticas
En las siguientes transparencias se muestran varios
ejemplos en ensamblador MIPS para realizar
operaciones aritmticas.
Se partir de la expresin en C para estudiar cmo se
implanta dicha expresin en ensamblador.
Caractersticas de las operaciones aritmticas MIPS:

Operaciones de 3 direcciones.

Operandos y resultados han de estar en registros.

Un operando puede ser una constante de 16 bits.


Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 7
Para estudiar el ensamblador del MIPS, se van a introducir sus instrucciones principales
a travs de ejemplos. En estos ejemplos se partir de un trozo de cdigo en lenguaje C y se
estudiar como se implanta dicho cdigo en ensamblador.
En primer lugar se van a estudiar algunas de las instrucciones disponibles en la arquitec-
tura MIPS para realizar operaciones aritmticas con nmeros enteros. Todas estas instruccio-
nes, junto con las instrucciones para realizar operaciones lgicas comparten tres caractersti-
cas fundamentales:

Operaciones de 3 direcciones. La primera direccin ser donde se almacene el


resultado y las otras dos los operandos.

Operandos y resultados han de estar en registros. Por tanto antes de realizar


cualquier operacin, si alguno de los datos est en memoria ser necesario cargarlo
en un registro.

Un operando puede ser una constante de 16 bits. En estos casos se realiza la operacin
entre dicha constante y un registro para almacenar el resultado en otro registro.
ICAIdea
Operaciones aritmticas
La expresin en C:
int a, b, c;
c = a + b;
Se traduce en ensamblador (suponiendo la asignacin
de registros: a->s0, b->s1 y c->s2) como:
add $s2, $s0, $s1
Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 8
En este ejemplo, suponemos que las tres variables enteras a, b y c han sido situadas por
el compilador en los registros s0, s1 y s2 respectivamente (en el compilador de C del MIPS
el tipo int es de 32 bits).
La instruccin de suma en el MIPS se representa con el nemnico add. Adems, tal como
se ha dicho anteriormente, las instrucciones aritmticas del MIPS son de tres direcciones.
Esto implica que siempre realizan la operacin entre dos registros, o entre un registro y una
constante de 16 bits, y almacenan su resultado en un registro. En el ensamblador del MIPS se
escribe en primer lugar el registro destino del resultado y a continuacin los dos operandos.
La restriccin de que todas las operaciones aritmticas sean de tres direcciones puede
parecer caprichosa. Sin embargo dicha restriccin est motivada por el deseo de simplicar la
circuitera, ya que si se quisieran implantar instrucciones con distintos nmeros de operandos
se necesitara circuitera especca para cada uno de los casos. Esto se puede resumir en uno
de los principios de diseo hardware:
Principio de diseo 1: la uniformidad simplica el hardware.
Cabe preguntarse cmo se puede realizar la suma de ms de dos variables. En la siguiente
transparencia se ilustra con otro ejemplo.
ICAIdea
Operaciones aritmticas
Cmo se traduce en ensamblador la expresin en C?
int a, b, c, d, e;
a = b + c + d + e;
Suponiendo la asignacin 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
Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 9
Como se puede apreciar, ahora es necesario sumar 4 variables, pero las instrucciones
aritmticas del MIPS slo permiten sumar dos. Para resolver este problema, se realizan tres
sumas parciales:
1. b+c
2. b+c+d
3. b+c+d+e
Dichas sumas parciales se han ido almacenando en el registro asignado a la variable a (s0).
En este ejemplo se ilustran dos cosas nuevas:

Un mismo registro puede ser a la vez fuente y destino. As, en la segunda instruccin
se est sumando s0 (que contiene ya b+c) con d y el resultado se vuelve a guardar en
s0.

El texto que aparece a la derecha del carcter # es un comentario y por tanto es


ignorado por el ensamblador. A diferencia de C no es necesario especicar el nal
del comentario, ya que ste acaba al nal de la lnea. Si se desean ms lneas de
comentario ser necesario usar caracteres # adicionales en cada lnea.
Tambin es necesario destacar que cada lnea puede contener como mucho una instruccin
de ensamblador.
ICAIdea
Operaciones aritmticas
Cmo se traduce en ensamblador la expresin en C?
int a, b, c, d, e;
a = (b + c) - (d + e);
Se realiza la asignacin 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
Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 10
Para evaluar la expresin a = (b + c) - (d + e) es necesario evaluar en primer lugar
las expresiones entre parntesis y a continuacin restar ambos resultados. Para almacenar los
resultados de las expresiones entre parntesis se usan variables temporales, ya que lo ms
probable es que no necesitemos nunca ms dichos resultados. Se han elegido para ello los
registros temporales t0 y t1.
Otra novedad de este ejemplo es la instruccin sub, la cual resta el tercer argumento del
segundo y lo almacena en el primero, es decir:
sub $s0, $t0, $t1
hace que s0 = t0 - t1.
Ejercicio
Modique el programa anterior para evitar el uso de los dos registros temporales. Pista:
Puede usar el registro s0 para ir almacenando los resultados parciales.
ICAIdea
Acceso a memoria
Es necesario acceder a memoria para usar:

Vectores y matrices.

Estructuras de datos.

Variables que no estn en registros.


Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 11
En los ejemplos mostrados hasta ahora se ha supuesto que todas las variables involucra-
das en las operaciones estaban almacenadas en los registros del procesador. Ahora bien, esto
no siempre es as. Todos los lenguajes de programacin soportan tipos de datos complejos
que no pueden ser almacenados dentro de unos cuantos registros de 32 bits. Ejemplos claros
son los vectores, las matrices y las estructuras de datos.
Adems, en muchas ocasiones los programas necesitan manejar ms variables de las que
pueden almacenarse en los registros. En estos casos no queda ms remedio que mantener
algunas variables en memoria y traerlas a los registros temporales cuando necesitemos operar
con ellas.
Por ltimo, antes de poder usar una variable es necesario cargarla en un registro.
En consecuencia, la arquitectura MIPS, al igual que todas las dems, dispone de instruc-
ciones de transferencia de datos que permiten cargar un valor desde la memoria a un registro
y para almacenar un registro en la memoria.
ICAIdea
Acceso a memoria. Organizacin
El bus de datos del MIPS es de 32 bits.
Es posible direccionar cada byte individualmente.
Direccin de palabra =
dir. byte ms signicativo:
Arquitectura big endian
Direccin de palabra =
mltiplo de 4
Restriccin de alineacin
0 1 2 3
4 5 6 7
8 9 A B
Palabra
Dir
0
4
8
Dir. Byte
lsB msB
Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 12
Antes de estudiar en detalle las instrucciones de transferencia de datos del MIPS, es
conveniente ver cmo est estructurada su memoria.
Los procesadores MIPS tienen un bus de datos de 32 bits, por lo que en cada acceso a
memoria se lee una palabra de 32 bits. Como se ha dicho antes, debido entre otras cosas a
que un carcter ocupa un byte, es necesario poder acceder a stos individualmente. Por ello,
aunque la memoria fsica est organizada en palabras de 32 bits, desde el punto de vista lgico
(o del programador), la memoria ha de estar organizada en bytes. Para ello, tal como puede
apreciarse en la gura, cada palabra est dividida en 4 bytes, cada uno con su direccin
para poder acceder a l individualmente. Las direcciones de palabra en este caso coinciden
con la del byte ms signicativo. Se dice entonces que la arquitectura es big endian. Otros
ejemplos de arquitecturas big endian son: IBM 360/370, Motorola 68k y Sparc. Existe otra
alternativa, seguida fundamentalmente por la arquitectura IA-32 en la que la direccin de
palabra coincide con el byte menos signicativo. En este caso se dice que la arquitectura es
little endian.
El que una arquitectura sea big endian o little endian es ms o menos transparente al
programador. Slo cuando ste tiene que examinar la memoria en busca de nmeros de ms de
8 bits ha de tener en cuenta su organizacin. Ahora bien, este tema es crtico si se intercambian
datos entre dos arquitecturas con distintas endianess.
Por ltimo, cabe destacar que en la arquitectura MIPS las direcciones de palabra deben
de ser siempre mltiplos de 4. Esto es lo que se conoce como restriccin de alineacin.
Existen arquitecturas que no tienen esta restriccin, aunque en estos casos, los accesos a
palabras alineadas son mucho ms rpidos que a palabras desalineadas.
ICAIdea
Acceso a memoria. Ejemplos
Cmo se traduce en ensamblador la expresin en C?
int a, b, V[40];
a = b + V[8];
Se realiza la asignacin 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 operacin
Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 13
En este ejemplo, es necesario acceder a un elemento de un vector. Obviamente el vector
no cabe en los registros del procesador, por lo que es necesario mantenerlo en la memoria.
Ahora bien, lo que s se puede guardar en los registros internos es la direccin del primer ele-
mento del vector (lo que en C se denota por el nombre del vector). En este ejemplo se supone
que se guarda dicha direccin en el registro s2. Por tanto, para acceder a la octava palabra del
vector, basta con sumar a la direccin de comienzo del vector el desplazamiento necesario. La
instruccin de carga de MIPS, denominada lw (de load word), hace precisamente esto: toma
la direccin de un registro base y le suma un desplazamiento,
1
cargando entonces la palabra que
hay en la direccin calculada en el registro destino. El formato de la instruccin es por tanto:
lw Reg_Dest, Despl(Reg_Base)
Hay que tener en cuenta que, segn se ha discutido antes, las direcciones de palabra
aumentan de 4 en 4, por lo que la octava palabra de un vector estar 8 pal 4Byte/pal =
32Bytes por encima de la base del vector. Por tanto, para cargar V[8] en el registgro t0, si la
direccin base del vector V est almacenada en el registro s2, basta con hacer:
lw $t0, 32($s2)
La instruccin complementaria a lw se denomina sw (de store word). Su funcionamiento
es similar al de lw, salvo que en lugar de traer una palabra de la memoria y almacenarla en
un registro; toma la palabra almacenada en el registro y la almacena en la memoria, concre-
tamente en la direccin Reg_Base + Despl. En la siguiente transparencia se ilustra su uso
mediante otro ejemplo.
1
El desplazamiento puede ser positivo o negativo.
ICAIdea
Acceso a memoria. Ejemplos
Cmo se traduce en ensamblador la expresin en C?
int b, V[40];
V[12] = b + V[8];
Se realiza la asignacin de registros: b->s1, V->s2.
lw $t0, 32($s2) # t0 se carga con V[8]
add $t0, $s1, $t0 # se realiza la operacin
sw $t0, 48($s2) # t0 se guarda en V[12]
Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 14
Como se puede apreciar las dos primeras lneas son prcticamente iguales a las del ejem-
plo anterior: tan solo vara el registro destino de la suma, que ahora es el registro temporal
t0, en donde se almacena el resultado de la suma antes de escribirlo en la memoria. De es-
ta escritura en memoria se encarga la instruccin sw, la cual tiene el mismo formato que la
instruccin lw:
sw Reg_Orig, Despl(Reg_Base)
En donde Reg_Orig es el registro cuyo valor se desea guardar y el resto de argumentos
tienen el mismo signicado que antes. Al igual que antes hay que convertir la direccin de
palabra del vector a direccin de byte (12 pal 4Byte/pal =32Bytes) para obtener el despla-
zamiento correcto.
En la mayora de los programas, el acceso a vectores se realiza utilizando un ndice
variable. En la siguiente transparencia se muestra un ejemplo para ilustrar este tipo de accesos.
ICAIdea
Acceso a memoria. Ejemplos
Cmo se traduce en ensamblador la expresin en C?
int a, b, V[40], i;
a = b + V[i];
Se realiza la asignacin 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 operacin
Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 15
En este ejemplo, al ser el ndice variable, no podemos multiplicarlo nosotros a mano
como hemos hecho en los ejemplos anteriores cuando el ndice era constante. No obstante el
MIPS tiene instrucciones que nos permiten hacer dicha multiplicacin fcilmente. Sin embar-
go, como no hemos visto an la instruccin de multiplicacin, realizaremos la multiplicacin
por 4 mediante dos sumas: En primer lugar calcularemos i +i = 2i y luego 2i +2i = 4i. De
esto se encargan las dos primeras instrucciones de ensamblador, guardando 4i en el registro
t1. Ahora bien, este valor no puede ser usado como desplazamiento en una instruccin de
carga o almacenamiento del MIPS, ya que estas instrucciones slo admiten un desplazamien-
to constante. No obstante la suma del desplazamiento con el registro base se puede realizar
mediante otra instruccin add para as calcular la direccin de V[i]. De esto se encarga la
tercera instruccin del programa, almacenando dicha direccin en el registro t1. En este mo-
mento ya se puede cargar el valor del elemento del vector V[i] mediante la instruccin lw.
Ntese que, como el registro t1 ya contiene la direccin de V[i], se ha utilizado un desplaza-
miento de 0 en la instruccin de carga. Una vez cargado el elemento del vector en el registro
t0 ya solo hace falta realizar la operacin de suma, de lo que se encarga la ltima instruccin.
Ejercicio
1. Traduzca a ensamblador el siguiente cdigo en C:
int a, b, V[40], i;
V[i+1] = b + V[i];
V[i-1] = a + V[i];
ICAIdea
Codicacin en lenguaje mquina
Dentro del ordenador slo hay 0s y 1s.
Las instrucciones han de codicarse en binario.
Por ejemplo:
add $t0, $s1, $s2
Se traduce en una secuencia de 32 1s y 0s:
000000 10001 10010 01000 00000 100000
La representacin binaria est dividida en campos
para simplicar su decodicacin en el hardware.
Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 16
Los programas se escriben en lenguaje ensamblador, pero no hay que olvidar que es-
te lenguaje no es ms que una representacin ms amigable de la nica representacin que
entiende el procesador: el lenguaje mquina. As, antes de poder ejecutar un programa es ne-
cesario traducir cada instruccin de lenguaje ensamblador en su instruccin correspondiente
de lenguaje mquina. Este proceso no es muy complicado, segn se ver ms adelante, ya
que para simplicar el hardware esta representacin binaria se divide en campos dentro de
los cuales se codica cada una de las partes de la instruccin: cdigo de operacin, regis-
tros. . .
En las siguientes transparencias se muestra en detalle cmo es la codicacin de instruc-
ciones en la arquitectura MIPS.
ICAIdea
Codicacin en lenguaje mquina
InstrucioMichaelG.WPg15ComputerAchiExample
0 17 8 0 18 32
Fuente 1
Fuente 1
Fuente 2
Fuente 2
Destino
Destino
Operacin
Operacin
no usado
10010 000000 00000 01000 10001 100000
Tipo R
6 bits 5 bits 5 bits 5 bits 6 bits 5 bits
shamt rs rt rd funct op
add $t0, $s1, $s2
Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 17
En la transparencia se muestra la codicacin de la instruccin:
add $t0, $s1, $s2
Como se dijo en el tema anterior, las instrucciones aritmticas del MIPS que operan slo
con registros se codican en el formato tipo R. Dicho formato comienza con el campo del
cdigo de operacin (op) de 6 bits, que en el caso de las instrucciones del tipo R es siempre
0. A continuacin viene un campo de 5 bits (rs) en donde se codica el nmero del primer
registro fuente. En este caso el registro fuente es s1, que segn se vio en la pgina 6 es el
registro nmero 17. En el siguiente campo (rt) se codica el nmero del otro registro fuente,
que en este caso es nmero 18 (s2). En el siguiente campo (rd), tambin de 5 bits, se codica
el registro destino, 8 en este caso (t0, segn se puede ver en la pgina 5). El siguiente campo
(shamt) no se usa en esta instruccin y por tanto se deja a 0. El ltimo campo (funct) es una
extensin del cdigo de operacin. Este ltimo campo especica qu instruccin particular
de todas las del tipo R se ha de ejecutar. La operacin suma se codica con el nmero 32.
Ntese que el orden de los registros fuente y destino es distinto en lenguaje ensam-
blador que en lenguaje mquina.
Las instrucciones de carga y almacenamiento necesitan especicar dos registros y una
constante. En una primera aproximacin al problema podra pensarse en utilizar uno de los
campos reservados para registros (por ejemplo el rt) para almacenar la constante en lugar del
nmero de registro). No obstante con 5 bits slo se pueden representar nmeros en el rango
0 a 32 o -16 a 15 si se trabaja en complemento a 2. Obviamente los vectores y las estructuras
de datos usados en los programas suelen ser mayores de 32 bytes, por lo que esta solucin no
es muy ecaz. Es preciso por tanto usar otro formato de instruccin para las instrucciones de
carga y almacenamiento que permita especicar una constante con un mayor nmero de bits.
ICAIdea
Codicacin en lenguaje mquina
InstrucioMichaelG.WPg15ComputerAchiExample
35 32 8 18
Despl.
Fuente 1
R. Base Destino
Destino
Operacin
Operacin
01000 100011 0000000000010000 10010
op rs rt Inmediato Tipo I
6 bits 5 bits 5 bits 16 bits
lw $t0, 32($s2)
Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 18
En la transparencia se muestra la codicacin de la instruccin: lw $t0, 32($s2)
Como esta instruccin necesita una constante para especicar el desplazamiento, ha de
codicarse con el formato tipo I. Como se puede apreciar en la gura, dicho formato es muy
similar al formato de las instrucciones de tipo R. La nica diferencia consiste en que los tres
ltimos campos del tipo R (rd, shamt y funct) se han unido en un slo campo de 16 bits
(Inmediato). El hecho de que los formatos sean similares simplica la decodicacin de las
distintas instrucciones.
El signicado de los dos primeros campos es igual al de las instrucciones de tipo R: el
primer campo de 6 bits especica el cdigo de operacin (35 para la instruccin lw) y el
segundo campo especica el nmero del registro base para el acceso a memoria (18 en este
ejemplo, que se corresponde con el registro s2). El tercer campo especica un registro, pero
al contrario que en las instrucciones de tipo R, este registro es el destino de la operacin.
En este ejemplo, el valor ledo de la memoria (en la direccin (s2) + 32 ) se escribe en el
registro nmero 8 (t0).
Como se puede apreciar, la solucin adoptada va contra el primer principio de diseo (la
uniformidad simplica el hardware), ya que en lugar de tener un formato de instruccin jo
se tienen formatos distintos en funcin del tipo de instruccin. Esto conduce a otro principio
de diseo hardware:
Principio de diseo 2: un buen diseo necesita buenas soluciones de compromiso.
Obviamente, la solucin adoptada en este caso complica el hardware al tener que decidir
entre distintos modos de decodicacin en funcin del tipo de instruccin (lo cual, recuerde,
viene marcado por el valor del cdigo de operacin). No obstante, con el n de simplicar
la circuitera al mximo, los distintos formatos se han mantenido lo ms parecidos posibles.
En este caso, segn se ha comentado antes, los tres primeros campos son iguales a los de las
instrucciones de tipo R.
1
8
-
2
ICAIdea
Codicacin en lenguaje mquina. Ej.
Cmo es el cdigo mquina de la expresin en C?
int a, V[400];
V[300] = V[300] + a;
Si se realiza la asignacin de registros: a->s0, V->s1.
Inmediato
op rs st rd shamt funct
lw $t0, 1200($s1) 35 17 8 1200
add $t0, $t0, $s0 0 8 16 8 0 32
sw $t0, 1200($s1) 43 17 8 1200
Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 19
En la transparencia se muestra la traduccin a cdigo mquina de una sentencia sencilla
en C:
int a, V[400];
V[300] = V[300] + a;
La primera instruccin contiene un 35 como cdigo de operacin (lw) seguido de un 17
para identicar el registro base (s1), un 8 para indicar el registro destino (t0) y un 1200 para
seleccionar un desplazamiento de 300 palabras (300 pal 4Byte/pal =1200Bytes).
De la misma manera, la instruccin siguiente (add) se codica con un 0 en el campo
de cdigo de operacin y un 32 en el ltimo campo (funct). El segundo y tercer campo
identican los registros fuente (t0 y s0) y el cuarto campo indica el registro destino (t0). El
penltimo campo no se usa en esta instruccin y por eso se deja a 0.
Por ltimo, ntese que la tercera instruccin es similar a la primera: se guarda el conte-
nido del registro en la posicin de memoria en lugar de leerlo. Por tanto, lo nico que vara
es el cdigo de operacin (43 en lugar de 35), siendo el resto de campos idnticos a los de la
primera instruccin.
En la siguiente transparencia se muestra la codicacin en binario, que es la que ve
realmente el procesador.
ICAIdea
Codicacin en lenguaje mquina. Ej.
La codicacin en binario es:
Inmediato
op rs st rd shamt funct
100011 10001 01000 0000 0100 1011 0000
000000 01000 10000 01000 00000 100000
101011 10001 01000 0000 0100 1011 0000
La nica diferencia entre la 1
a
y la 3
a
instruccin es el
tercer bit.
Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 20
En la transparencia se muestra la codicacin de las instrucciones en binario, que es el
formato en el que las ve el procesador. No obstante esta notacin es muy oscura para los
programadores, por lo que no se usa en la prctica. Se ha usado aqu simplemente con nes
ilustrativos.
Ntese que para simplicar la decodicacin, instrucciones similares se codican de
forma similar. En este caso la diferencia entre la 1
a
y la 3
a
instruccin consiste solamente en
el tercer bit empezando por la izquierda (bit 29 de la palabra).
Por ltimo, es necesario resaltar que las instrucciones de un programa no son ms que
una secuencia de nmeros. As, el cdigo anterior no son ms que tres nmeros binarios de
32 bits. En concreto:
240386168
17842208
2921858224
Por tanto las instrucciones se pueden almacenar en la memoria al igual que los datos.
Esta es una de las ideas fundamentales de la informtica y es precisamente lo que hace que
los ordenadores sean unas mquinas tremendamente exibles: basta con cambiar el programa
para que un ordenador pase a realizar una tarea totalmente distinta.
ICAIdea
Toma de decisiones
La toma de decisiones es lo que distingue a un
ordenador de una calculadora.
Permite ejecutar distintas instrucciones en funcin de
datos de entrada o resultados de clculos.
En MIPS se incluyen 2 instrucciones para toma de
decisiones:

beq reg1, reg2, L1

bne reg1, reg2, L1


Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 21
La posibilidad de tomar decisiones en funcin de los datos de entrada o del resultado de
un clculo es lo que distingue a un ordenador de una simple calculadora. Por ello todos los
procesadores incluyen instrucciones que permitan ejecutar una serie de instrucciones u otras
en funcin de un resultado lgico. Esta toma de decisiones se representa en los lenguajes de
programacin mediante la sentencia if.
La arquitectura MIPS incluye dos instrucciones que permiten tomar decisiones en fun-
cin de los valores almacenados en dos de sus registros:

beq reg1, reg2, L1. Esta instruccin compara los contenidos de los registros
reg1 y reg2. Si son iguales, el programa salta a la instruccin etiquetada con L1. Si
son distintos, el programa contina en la instruccin siguiente (a beq). El nemnico
beq viene de branch if equal.

bne reg1, reg2, L1. Al igual que la instruccin anterior, esta instruccin compara
los contenidos de los registros reg1 y reg2. Si son distintos, el programa salta a la
instruccin etiquetada con L1. Si son iguales, el programa contina en la instruccin
siguiente. El nemnico bne viene de branch if not equal.
Debido a su modo de funcionamiento, este tipo de instrucciones se conocen como saltos
condicionales.
El equivalente en C de ambas instrucciones es, respectivamente:

if(i==j) goto L1;

if(i!=j) goto L1;


En donde se ha supuesto que las variables i y j estn almacenadas en los registros Reg1
y Reg2.
ICAIdea
Toma de decisiones. Ejemplo
Cmo se traduce en ensamblador la expresin 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
Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 22
En el fragmento de cdigo C mostrado, se realiza un salto a la instruccin etiquetada
con L1 slo si las variables i y j son iguales. Por tanto, la instruccin b = b + c slo se
ejecutar si i!=j y la instruccin a = b - c se ejecutar siempre. Ntese que este ejemplo
es muy articial, ya que slo persigue ilustrar las instrucciones de salto condicional de la
arquitectura MIPS. De hecho, la mayora de los programadores evita el uso de sentencias
goto en sus programas. En el siguiente ejemplo se mostrar cmo codicar la sentencia
if-then-else, que es la que se usa normalmente.
La traduccin a ensamblador es directa. La sentencia if se traduce por:
beq $s3, $s4, L1 # Si i==j ir a L1
En donde la etiqueta L1, al igual que en C, identica la instruccin a la que es necesario
saltar si la condicin es cierta. La siguiente sentencia tambin equivale a una sola instruccin:
add $s1, $s1, $s2 # se ejecuta si i!=j
La ltima sentencia en C tambin se traduce por una sola instruccin en ensamblador,
slo que ahora es necesario incluir la etiqueta de forma que la instruccin de salto condicional
pueda saltar a ella cuando la comparacin sea cierta. Para ello basta con aadir el nombre de
la etiqueta terminado con el carcter : delante de la instruccin:
L1: sub $s0, $s1, $s2 # se ejecuta siempre
De este modo el ensamblador hace corresponder la etiqueta L1 con la direccin de la
instruccin sub $s0, $s1, $s2. Cuando ste traduzca la primera instruccin a lenguaje
mquina, la etiqueta L1 ser sustituida por la direccin de la tercera instruccin. Por tanto el
ensamblador est liberando al programador de otra tarea muy tediosa y propensa a errores: el
clculo de las direcciones de salto.
2
2
-
2
ICAIdea
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:
Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 23
En la transparencia se muestra cmo se traduce una sentencia if-else a ensamblador
MIPS. En primer lugar, al igual que en el ejemplo anterior, la sentencia if se traduce por una
instruccin de salto condicional. Sin embargo, ahora se comprueba la condicin contraria
para saltar al bloque else si la condicin del if es falsa:
bne $s3, $s4, SiNo # Si i!=j ir a SiNo
La siguiente sentencia de C, al tener todos sus operandos situados en registros se traduce
por una sola instruccin de ensamblador:
add $s0, $s1, $s2 # se evita si i!=j
Una vez ejecutada esta instruccin, es necesario que el programa contine despus de la
sentencia if. Para ello es necesario introducir una nueva instruccin del ensamblador MIPS:
el salto incondicional. Esta instruccin se identica mediante el nemnico j (de jump). Su
formato es simplemente j Etiqueta. En este caso:
j Fin # Salta a Fin
Esta instruccin hace que el procesador salte siempre a la instruccin marcada por la
etiqueta Fin. A continuacin se sita el resultado de traducir la sentencia del else del pro-
grama en C. Al igual que antes, esta sentencia se traduce a una sola instruccin aritmtica. No
obstante, es necesario preceder dicha instruccin por la etiqueta SiNo, ya que esta instruccin
es el destino del salto de la comaracin:
SiNo: sub $s0, $s1, $s2 # se ejecuta si i!=j
Por ltimo, es necesario incluir la etiqueta Fin, que es el destino del salto incondicional
al nal de la sentencia if. Dicha etiqueta representar la direccin de la instruccin siguien-
te, que no se ha mostrado en la transparencia para simplicar. Por ejemplo, si la siguiente
instruccin del programa en ensamblador fuese add $t0, $t0, $t1, entonces el nal del
programa anterior sera:
Fin:
add $t0, $t0, $t1
Ntese que no es necesario que la etiqueta est en la misma lnea que la instruccin.
nicamente ha de escribirse antes de ella.
Ejercicios
1. Traduzca a ensamblador el ejemplo mostrado en la transparencia usando la instruc-
cin beq para realizar la comparacin entre i y j.
2. Traduzca a ensamblador el siguiente cdigo en C:
int a, b, c, i, j;
if(i == j){
a = b + c;
}
ICAIdea
Toma de decisiones. Bucles
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
Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 24
Al igual que se hizo con el ejemplo del if, esta forma de escribir un bucle en C no
es la ms comn. Es ms, no es nada recomendable su uso. Sin embargo, su traduccin
a ensamblador es directa y por ello se ha usado en este primer ejemplo. En la siguiente
transparencia se mostrar cmo se traduce un bucle while a ensamblador MIPS.
El programa en C repite las dos primeras instrucciones mientras i!=k. La primera ins-
truccin contiene un acceso a un vector. Por lo tanto es necesario multiplicar por 4 el ndice
i (s2), de lo que se encargan las dos primeras instrucciones. La tercera instruccin calcula la
direccin del elemento del vector y por ltimo la cuarta lo carga en el registro t0. La siguien-
te instruccin calcula a = a + V[i] y la sexta i = i + j. La ltima instruccin saltar al
principio del bucle si se cumple la condicin i!=k. En caso contrario el programa continuar
en la instruccin que sigue a bne, terminndose as el bucle.
Ejercicio
Modique el programa anterior para evitar el clculo de 4*i en cada iteracin del bucle.
Cuantas instrucciones se repiten ahora en cada iteracin? Suponiendo que todas las instruc-
ciones tardan lo mismo en ejecutarse, Cual ser la mejora en el tiempo de ejecucin de un
programa que repita este bucle 10 veces?
ICAIdea
Toma de decisiones. Bucles
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:
Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 25
En esta transparencia se muestra la traduccin a ensamblador de un bucle while en C.
Como se puede apreciar, aunque este bucle es ms fcil de usar que el anterior, su traduccin
a ensamblador es un poco ms compleja. Afortunadamente este trabajo extra de traduccin
lo realiza normalmente el compilador.
Las 4 primeras instrucciones son las mismas que en el ejemplo anterior, ya que lo primero
que hay que hacer es cargar el valor V[i] desde la memoria al registro t0. Una vez cargado
dicho valor, se puede evaluar la condicin del bucle while. Esto se realiza en la 5
a
instruccin.
En ella se compara el valor de V[i] (t0) con el valor de k (s4). Si son distintos se salta a la
etiqueta Fin, terminndose as el bucle. Si son iguales, se continuar ejecutando la siguiente
instruccin para realizar la suma i = i+j, es decir, se ejecuta el cuerpo del bucle. Una vez
realizada la suma se salta al principio del bucle mediante un salto incondicional. Ntese que
en la instruccin de comparacin se ha cambiado la condicin que aparece en el cdigo C
para conseguir un cdigo ms compacto.
Ejercicio
Traduzca el bucle while anterior a ensamblador MIPS pero utilizando la instruccin beq
en lugar de la instruccin bne.
ICAIdea
Toma de decisiones. Menor que

Las comparaciones ms habituales en los


programas son la igualdad y la desigualdad.

Es necesario tambin saber si una variable es


menor que otra. Para ello MIPS dene la
instruccin slt (set on less than).

Por ejemplo: la instruccin 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.
Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 26
Aunque las comparaciones ms habituales en los programas son la igualdad y la desi-
gualdad, en muchas ocasiones es necesario saber si el valor de una variable es menor que otra.
Por ejemplo en un bucle for que recorre un vector es muy frecuente comparar si el ndice
es menor que la dimensin del vector. Para realizar este tipo de comparaciones, la arquitec-
tura MIPS dene la instruccin slt (de set on less than). Dicha instruccin consta de tres
argumentos, un registro destino y dos registros fuente:
slt destino, fuente1, fuente2
Su funcionamiento consiste en comparar si el contenido del registro fuente1 es menor
que el del registro fuente2. En caso armativo escribe un 1 en el registro destino y en caso
negativo escribe un 0.
En la siguiente transparencia se muestra un ejemplo del uso de esta instruccin para
traducir una sentencia if a ensamblador.
Ejercicio
Los compiladores del MIPS utilizan las instrucciones slt, bne, beq y el valor cero (al-
macenado en el registro zero) para realizar todas las comparaciones posibles (==, !=, <,
>, <= y >=). Escriba las secuencias de instrucciones MIPS que permiten evaluar dichas con-
diciones entre los registros s0 y s1 y saltar a la etiqueta Fin si el resultado de la comparacin
es cierto. Por ejemplo, para evaluar la condicin s0 > s1 se escribira:
slt $t0, $s1, Ss0
bne $t0, $zero, Fin
ICAIdea
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 # evala i < j
bne $t0, $zero, Fin # si i<j salta
add $s0, $s1, $s2 # a = b + c
Fin:
Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 27
En el ejemplo mostrado se ha traducido una sentencia if a ensamblador. Como se puede
apreciar, para conseguir un cdigo ms compacto se ha invertido la condicin del if, es decir,
en lugar de evaluar la condicin i >= j, se ha evaluado la contraria (i < j) para saltarse el
cuerpo del if si dicha condicin contraria es cierta.
En este caso la evaluacin de la condicin y el salto se realizan en dos pasos. En primer
lugar con la instruccin:
slt $t0, $s3, $s4 # evala i < j
Se evala la condicin i < j y se actualiza el valor del registro t0 con el resultado de la
comparacin. A continuacin, mediante una instruccin de salto condicional se salta al nal
del if si el resultado de la comparacin anterior ha sido cierto:
bne $t0, $zero, Fin # si i<j salta
Puede parecer extrao a primera vista que la arquitectura MIPS no incluya una instruc-
cin llamada blt (branch on less than). La razn de no incluir dicha instruccin es debido
a que, siguiendo la losofa RISC, no es conveniente implantar instrucciones complicadas o
que requieran ms de un ciclo de reloj para ejecutarse. Por ello, debido a que comparar si
dos valores son menores toma ms tiempo que comparar si son iguales, resulta que no es
posible implantar la instruccin blt de forma que se ejecute en un ciclo de reloj y por ello
los diseadores del MIPS optaron por implantar dos instrucciones ms simples y rpidas.
ICAIdea
Llamadas a funciones
Las funciones permiten programas estructurados,
reutilizar cdigo, etc.
Dos aspectos importantes:

Tienen un interfaz bien denido: Parmetros de


entrada y resultados de salida.

Realizan su trabajo sin interferir con la funcin


que las llama.
Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 28
En cualquier programa, salvo que ste sea extremadamente simple, es necesario usar
funciones. El uso de funciones presenta numerosas ventajas, entre las que destacan la mejora
de la legibilidad del programa, la posibilidad de reutilizar cdigo, el facilitar la programacin
al permitir dividir un problema complejo en varios subproblemas ms fciles de abordar,
etc.
Aunque ya debe de estar familiarizado con el uso de funciones en lenguajes de alto nivel,
conviene recalcar dos aspectos de su uso:

Constan de un interfaz bien denido con el resto del programa. Reciben una serie de
argumentos con los que realiza su tarea y devuelven el resultado de sta a quien la
ha llamado.

Son capaces de realizar su tarea sin interferir con el resto del programa. Esto se con-
sigue mediante un espacio de trabajo propio aislado del resto del programa. As, las
variables que utiliza son locales a la funcin y no son accesibles desde fuera de ella.
De la misma forma, la funcin no puede acceder a las variables locales de las dems
funciones.
ICAIdea
Llamadas a funciones
Para poder ejecutar una funcin es necesario:
1. Situar los parmetros donde la funcin llamada
pueda leerlos. a0-a3, pila
2. Transferir el control a la funcin llamada.
3. Reservar espacio para las variables locales.
t0-t9, pila.
4. Realizar la tarea necesaria.
5. Situar el resultado donde la funcin llamante
pueda leerlos. v0-v1, pila
6. Devolver el control a la funcin llamante.
Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 29
En la transparencia se muestran los distintos pasos que es necesario realizar en la llamada
a una funcin.
Tanto el envo de argumentos (paso 1) como la reserva de espacio para las variables
locales (paso 3) y la recepcin de los resultados (paso 5) son tarea del programador (o del
compilador si se programa en un lenguaje de alto nivel). Ahora bien, todo ello se realiza
siguiendo una convencin software para que todas las funciones puedan interactuar sin pro-
blemas, independientemente de su autor y del lenguaje en que hayan sido escritas. En el caso
del MIPS, con el objetivo de conseguir mejores prestaciones, se reservan 4 registros (a0-a3)
para enviar argumentos a la funcin y 2 registros (v0-v1) para que la funcin devuelva su
resultado. Si se necesita enviar a la funcin un nmero mayor de argumentos o datos que no
puedan ser almacenados en registros, entonces es necesario recurrir a la pila. De la misma
forma, si la funcin ha de devolver algn dato que no quepa en los registros (v0-v1), como
por ejemplo una estructura de datos, ser necesario recurrir a la pila. Las variables locales se
pueden almacenar en los registros reservados para valores temporales (t0-t9) o en la pila. En
caso necesario se pueden usar tambin los registros (s0-s7), aunque antes de escribir nada
en ellos ser necesario guardar su valor en la pila y restaurarlos justo antes de devolver el
control a la funcin llamante, pues dicha funcin supone que la funcin llamada dejar estos
registros intactos. En otras arquitecturas (p. ej. IA-32) debido al escaso nmero de registros
disponible (8) no se reservan registros para el paso de argumentos ni para valores temporales,
siendo entonces necesario un uso intensivo de la pila.
El ltimo aspecto de la llamada a una funcin (paso 6) es la continuacin de la ejecucin
de la funcin llamante justo en la instruccin siguiente a la usada para realizar la llamada a la
funcin (paso 2). Para ello es necesario guardar la direccin de dicha instruccin siguiente en
algn sitio, lo cual necesita que el procesador incluya hardware especco para dicha tarea.
En la siguiente transparencia se discute la solucin adoptada por los arquitectos del MIPS.
2
9
-
2
ICAIdea
Llamadas a funciones. Instruccin jal

Al transferir el control a la funcin es necesario


guardar la direccin de retorno.

En el MIPS esta tarea la realiza la instruccin jal


(jump and link)

Formato: jal Dir_de_la_funcin

Funcionamiento:

Guarda la direccin de retorno (PC+4) en el


registro ra.

Salta a la direccin Dir_de_la_funcin.


Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 30
La instruccin jal (del ingls jump and link, saltar y enlazar) permite saltar a la direc-
cin de su argumento (jump) y a la vez almacenar la direccin de la instruccin de retorno
(link), que ser la instruccin que est situada a continuacin de jal. Dicha direccin ser
obviamente PC+4. El lugar elegido por los arquitectos del MIPS para almacenar la direccin
de retorno es un registro reservado para este n, denominado ra (del ingls return address,
direccin de retorno). Esto permite que la ejecucin de la instruccin se realice en un so-
lo ciclo de reloj. Las arquitecturas CISC guardan la direccin de retorno en la pila, aunque
esto conlleva un tiempo de ejecucin mayor, pues hace falta hacer un acceso adicional a la
memoria para guardar la direccin de retorno.
Por ejemplo, si se desea saltar a la funcin llamada fun bastar con escribir:
jal fun
Adems de esto, es necesario que la primera instruccin de la funcin tenga como eti-
queta fun:
fun: add $t0, $a0, $a1
...
ICAIdea
Llamadas a funciones. Instruccin jr

Para volver de una funcin es necesario saltar a


la direccin almacenada en ra

En el MIPS esta tarea se realiza con la


instruccin jr (jump register).

Formato: jr registro

Funcionamiento: Salta a la direccin almacenada


en el registro.
Por tanto, el retorno de la funcin se realiza con:
jr $ra
Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 31
Por ltimo, una vez nalizada su tarea, la funcin ha de colocar el resultado en los
registros v0-v1 o la pila y devolver el control a la funcin que la ha llamado. Como la llamada
a la funcin mediante la instruccin jal guarda la direccin de la instruccin que le sigue
en el registro ra, basta con saltar a la direccin almacenada en dicho registro. Para ello,
el MIPS dispone de una instruccin que permite saltar incondicionalmente a la direccin
almacenada en un registro, llamada jr (del ingles jump register, saltar registro). Por tanto, la
ltima instruccin de la funcin ser precisamente:
jr $ra
Resumiendo, la funcin llamante coloca los argumentos en los registros a0-a3 y me-
diante la instruccin jal fun llama a la funcin fun. Dicha funcin realiza su tarea y
deposita sus resultados en los registros v0-v1 para a continuacin devolver el control a la
funcin llamante mediante la instruccin jr $ra. En la siguiente transparencia se muestra
un ejemplo para aclarar el proceso.
ICAIdea
Llamadas 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
Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 32
En la transparencia se muestra un ejemplo de traduccin a ensamblador de una funcin
muy simple escrita en C. Como se puede apreciar en primer lugar, dicha funcin no llama
a ninguna otra. A este tipo de funciones se les denomina funciones hoja. Adems, dicha
funcin slo necesita 4 argumentos, por lo que no es necesario recurrir a la pila. De la misma
forma, como la funcin devuelve un valor entero, basta con un slo registro para ello (v0).
Como se puede observar, la funcin slo necesita almacenar dos valores en variables
locales (los resultados parciales de sus clculos), por lo que basta con usar dos de los 10
registros temporales disponibles (t0 y t1).
Una vez terminados sus clculos, la funcin ha de copiar el resultado obtenido al registro
v0 para devolverlo a la funcin llamante. En MIPS no existe una instruccin especca para
mover datos entre registros, aunque dicho movimiento se puede realizar sumndole cero al
registro origen y usando el registro destino como resultado de la suma. As, lo que en otras
arquitecturas se escribira como:
move $v0, $t0
En MIPS se escribe como:
add $v0, $t0, $zero
Ejercicio
La codicacin de la funcin anterior dista bastante de ser la ptima, tanto en uso de
registros como en nmero de instrucciones. Escriba otra versin de la funcin ms eciente.
ICAIdea
Llamadas a funciones. La pila

En algunas arquitecturas existen instrucciones


explcitas para el manejo de la pila (push y pop).

El MIPS no tiene soporte explcito de la pila sino


una convencin software:

Se reserva el registro sp (stack pointer) para


apuntar al tope de la pila.

La pila crece hacia abajo.


Contenido ra
Contenido a0 sp
sp sp
Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 33
Como se ha comentado antes, el uso de la pila es imprescindible en la llamada a las
funciones. Esto es debido a que slo es necesario conocer el orden en que se han almacenado
los datos, no su posicin absoluta y adems puede crecer indenidamente; permitindose
as el anidamiento de varias funciones sin que los datos de stas intereran entre s.
Aunque muchos procesadores incluyen instrucciones especcas para el manejo de la
pila (push y pop), el MIPS no dispone de ellas. No obstante existe una convencin software
para implantar una pila:

Se reserva el registro sp (del ingls stack pointer, puntero de pila) para apuntar al
tope de la pila. Es responsabilidad del programador el manejo de este registro, es
decir, si se introduce o se retira un dato en la pila, habr que modicar el sp para que
contine apuntando al tope de la pila.

La pila crece desde posiciones altas de memoria hacia posiciones bajas. No hay
ninguna razn para hacerlo as salvo por los precedentes histricos. En consecuencia
el tope de la pila ser la direccin ms baja de sta.
En la gura de la transparencia se ilustra la evolucin de la pila cuando se llama a una
funcin que necesita guardar dos registros (ra y a0) en la pila. Como se puede apreciar en
primer lugar (gura izquierda) el registro sp estar apuntando al ltimo dato introducido en
la pila (no mostrado por simplicar). Cuando se llama a la funcin, sta necesita guardar
en la pila dos registros, por lo que el sp se decrementa en dos palabras (8 bytes) y en el
espacio creado se copiar el contenido de los dos registros (ra y a0) (gura central). Una vez
nalizada la funcin, la pila ha de quedar como estaba, tal como se muestra en la gura de la
derecha.
ICAIdea
Llamadas a funciones. Anidamientos
En el ejemplo anterior se mostr una funcin hoja.
Lamentablemente hay funciones que llaman a otras
funciones.
En estos casos es necesario:

Guardar la direccin de retorno ra

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


necesiten despus.
Obviamente estos registros se guardan en la pila.
Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 34
En el ejemplo mostrado anteriormente, la funcin era una funcin hoja, es decir, la
funcin no llamaba a ninguna otra funcin. Desgraciadamente, no todas las funciones son
funciones hoja, por lo que el mecanismo de llamada se complica un poco en estos casos.
En concreto, la funcin llamante ha de guardar los registros que la funcin llamada pueda
modicar:

El primer registro que se modica es el registro de la direccin de retorno ra, ya que


en cuanto se ejecute la instruccin jal dicho registro se sobreescribir con la nueva
direccin de retorno. Por tanto, antes de llamar a una funcin es necesario
guardar el valor de ra en la pila.

Si la funcin necesita algn argumento, este ha de copiarse en los registros a0-a3.


Por tanto, si la funcin llamante ha de usar algn valor de estos registros despus de
la llamada a la funcin, ha de guardar stos en la pila. Ntese que aunque no se
necesite usar alguno de los registros a0-a3 para pasar argumentos a la funcin, sta
puede llamar a otra funcin que necesite ese registro como argumento. Por tanto,
siempre se guardarn los registros a0-a3 cuyos valores sean necesarios
despus de la llamada a una funcin.

Si la funcin llamante necesita usar algn valor almacenado en los registros tempo-
rales t0-t9 despus de la llamada a la funcin, tambin tendr que guardarlos en la
pila antes de llamarla.
El ejemplo ms complicado de funcin no hoja es una funcin recursiva. En la siguiente
transparencia se muestra una funcin para calcular el factorial de forma recursiva. Aunque
este es el peor ejemplo de uso de la recursividad, pues es mucho ms eciente resolverlo con
un bucle, su simplicidad justica su uso en este caso.
ICAIdea
Llamadas 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):
Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 35
ICAIdea
Llamadas 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: addi $sp, $sp, -8 # Reserva 2 palabras en pila
sw $ra, 4($sp) # guarda ra y
sw $a0, 0($sp) # n en pila
addi $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
mul $v0, $a0, $v0 # devuelve
jr $ra # n * fact(n-1)
Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 36
Al igual que el programa en C, lo primero que realiza la funcin es comprobar si su
argumento n (a0) es menor que 1 para en caso armativo devolver un 1. Para realizar la
comparacin se ha usado una versin de la instruccin slt denominada slti (del ingls set
on less than inmediate). El funcionamiento es idntico a la instruccin slt salvo que en lugar
de comparar dos registros, compara un registro con una constante. Por tanto la instruccin:
slti $t0, $a0, 1 # n<1 ?
Compara el registro a0 con la constante 1 y pondr a uno t0 si (a0) <1.
La siguiente instruccin saltar a la etiqueta L1 si el resultado de la comparacin anterior
fue falso, es decir, si n >= 1. En caso contrario (n<1) se ejecutarn las instrucciones:
addi $v0, $zero, 1 # devuelve 1
jr $ra
que devuelven 1 a la funcin llamante. Para ello se ha utilizado una nueva instruccin
denominada addi que suma una constante a un registro y almacena el resultado en un tercer
registro. En este caso dicha instruccin suma 0 + 1 y almacena el resultado en v0. El control
se devuelve a continuacin mediante la instruccin jr. Ntese que en este caso particular la
funcin fact se comporta como una funcin hoja, ya que no llama a ms funciones. Por tanto
no ha sido necesario en este caso guardar ningn registro en la pila.
Si n >= 1, entonces es necesario llamar recursivamente a la funcin fact, aunque antes
de ello es necesario guardar en la pila los registros que se vayan a necesitar ms tarde. Estos
registros son el ra y el a0. El primero es necesario para preservar la direccin de retorno y el
segundo para poder usar el valor de n al calcular n * fact(n-1). Para guardar los registros,
lo primero que se hace es reservar sitio en la pila, moviendo el puntero 8 bytes (2 palabras)
ms abajo. A continuacin se guarda ra en la segunda palabra y a0 en el tope de la pila:
L1: addi $sp, $sp, -8 # Reserva 2 palabras en pila
sw $ra, 4($sp) # guarda ra y
sw $a0, 0($sp) # n en pila
La estructura de la pila en este instante ser la mostrada en la gura de la transparen-
cia 33. Una vez salvados los dos registros, se pasa a llamar a la funcin fact. Para ello, se
sita en el registro a0 el valor n-1, lo cual se hace restando 1 a dicho registro, ya que ste
contena el valor de n. Una vez hecho esto ya se puede llamar a la funcin fact mediante la
instruccin jal:
addi $a0, $a0, -1 # a0=n-1
jal fact
Cuando dicha funcin devuelva el control, en el registro v0 estar almacenado el valor de
(n-1)!. Por tanto, lo nico que hay que hacer es restaurar los registros que se almacenaron
en la pila y calcular n*(n-1)! para devolverlo. La restauracin de registros es el proceso
inverso al realizado para guardarlos:
lw $a0, 0($sp) # restaura n
lw $ra, 4($sp) # y ra
addi $sp, $sp, 8 # ajusta sp
Como se puede apreciar, despus de la ejecucin de estas instrucciones la pila se quedar
como estaba antes de llamar a la funcin. Lo nico que resta por hacer es calcular n*(n-1)!
y devolver el control a la funcin llamante, lo cual se realiza mediante:
mult $v0, $a0, $v0 # devuelve
jr $ra # n * fact(n-1)
Ejercicio
Escriba un programa en ensamblador del MIPS para calcular el factorial de 7. Utilice
para ello la funcin fact desarrollada anteriormente.
3
6
-
3
ICAIdea
Llamadas a funciones. Bloque de activacin
La pila crece y decrece durante la ejecucin de la
funcin para:

Almacenar variables locales.

Evaluar expresiones.

Guardar registros.
El segmento de la pila que contiene todos los datos de
una funcin se denomina bloque de activacin
Algunos programas usan el registro fp para apuntar al
principio del bloque de activacin.
Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 37
Durante la ejecucin de la funcin la pila puede crecer y decrecer. Por ejemplo si se
declara una estructura como variable local, sta tendr que almacenarse en la pila, para lo
que ser necesario decrementar el sp en el nmero de palabras que ocupe dicha estructura.
Adems algunos programas necesitan usar la pila para evaluar expresiones matemticas com-
plejas. Por si esto fuera poco, algunos lenguajes como C++ permiten crear variables locales
en cualquier punto de la funcin, por lo que la pila puede crecer en cualquier momento. Esto
hace que si se usa el registro sp para acceder a las variables almacenadas en la pila, ser ne-
cesario utilizar desplazamientos distintos a lo largo de la funcin, dicultndose la escritura
del programa.
Por tanto, es conveniente tener una referencia a las variables almacenadas en la pila
que no vare durante la ejecucin de la funcin. Algunos programas MIPS usan el registro
fp para almacenar la primera palabra del bloque de la pila usado por la funcin, al que se
denomina bloque de activacin. Por ello al registro fp se le conoce como puntero al bloque
de activacin (frame pointer). Dicho registro se carga con el valor del sp al iniciar la funcin
y no vara hasta que sta termine. Por tanto, los accesos a las variables almacenadas en la
pila pueden referirse al fp y dichas referencias no tendrn que cambiarse cada vez que se
introduzca o elimine algn dato de la pila.
Ejercicio
El uso del puntero al bloque de activacin facilita adems la restauracin del puntero de
pila al nal de la ejecucin de la funcin. Escriba las instrucciones necesarias para guardar
el principio del bloque de activacin en fp al principio de la funcin y para restaurar el sp al
nalizar la funcin.
ICAIdea
Llamadas a funciones. Paso de arg. por pila
Si hay ms de 4 parmetros o alguno de stos no
cabe en registros se pasan por la pila.
Convencin software: se sitan por encima del bloque
de activacin.
sp
fp
sp
fp
sp
fp
Bloque
Activacin
Bloque
Activacin
Argumentos
Bloque
Activacin
Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 38
Segn se ha dicho anteriormente, hay ocasiones en las cuales los 4 registros reservados
para el paso de argumentos entre funciones (a0-a3) no son sucientes:

Si hay ms de 4 argumentos. En este caso los 4 primeros se pasan en los registros y


los restantes en la pila.

Si algn o algunos argumentos no caben en un registro. En este caso los argumentos


que no quepan se pasan por la pila.
En estos casos, los argumentos se sitan justo encima del bloque de activacin de la fun-
cin llamada (o visto de otra manera, al nal del bloque de activacin de la funcin llamante).
Para acceder a ellos, lo ms conveniente es usar el puntero al bloque de actuvacin fp.
Ejercicios
1. Escriba la siguiente funcin en C en ensamblador MIPS:
int suma(int a, int b, int c, int d, int e, int f){
return a+b+c+d+e+f;
}
2. Escriba la secuencia de intrucciones de ensamblador MIPS para sumar los valores
almacenados en los 6 registros s0-s5 mediante una llamada a la funcin suma. El
resultado se guardar en el registro s6.
ICAIdea
Manejo de caracteres
Los caracteres se codican en ASCII.
Un carcter 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 signicativos del
registro destino. Ej. lb $t0, 0($s0).

sb (store byte). Almacena los 8 bits menos


signicativos del registro origen en la memoria.
Ej. sb $t0, 0($s0).
Los caracteres pueden estar en cualquier posicin de
memoria.
Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 39
La mayora de las aplicaciones informticas necesitan procesar caracteres. Existen varios
mtodos de codicacin, aunque el ms extendido es el ASCII, en el cual un carcter ocupa
un byte.
El MIPS dispone de dos instrucciones para cargar y almacenar bytes: lb y sb. El fun-
cionamiento de ambas instrucciones es anlogo a lw y sw, excepto que slo leen un byte de
la memoria y lo almacenan en los 8 bits menos signicativos del registro destino. Adems el
byte puede estar situado en cualquier posicin de memoria.
ICAIdea
Manejo de caracteres. Ejemplo
El siguiente ejemplo muestra la funcin strcpy de C:
void strcpy(char dest[], char orig[])
{
int i;
i = 0;
/*Copia y comprueba final*/
while( (dest[i] = orig[i]) != NULL){
i++;
}
}
Cul es la traduccin a ensamblador MIPS?
Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 40
En la transparencia se muestra una implementacin de la funcin strcpy de la librera
estndar de C. Dicha funcin copia una cadena orgen (orig) en otra cadena destino (dest).
Ambas cadenas siguen la convencin de C para indicar su nal mediante el carcter nulo
(NULL).
La funcin copia el caracter i de la cadena orgen en la posicin i de la cadena destino
y despes comprueba si ste es distinto de NULL. Si no lo es incrementa el ndice y contina
el bucle. Cuando el carcter copiado sea el terminador nulo de la cadena, el bucle terminar,
aunque despus de copiar el NULL a la cadena de destino, con lo que sta ser correcta.
En la siguiente transparencia se muestra el cdigo en ensamblador MIPS para imple-
mentar esta misma funcin.
ICAIdea
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
Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 41
La primera instruccin smplemente pone a cero el registro t0, que va a ser usado para
almacenar el ndice i. Ntese que dicha operacin se hace almacenando el resultado de sumar
0+0.
La siguiente instruccin calcula la direccin del carcter de la cadena origen que se va a
copiar. Para ello se suma el ndice i a la base de la cadena, que segn puede desprenderse del
cdigo en C, estar almacenado en el registro a1, pues es el segundo argumento de la funcin.
Una vez calculada la direccin, se puede usar la instruccin lb para cargar el carcter en el
registro t2, que es lo que se hace en la tercera instruccin.
A continuacin se calcula la direccin en la que hay que almacenar el carcter, que ser
el resultado de sumar el ndice i a la base de la cadena destino (almacenada en a0) y se
almacena el carcter en dicha direccin mediante la instruccin sb
Por ltimo se incrementa el ndice y se salta al principio del bucle si el carcter es distinto
de cero (recuerde que en C NULL es un 0). Si se encuentra el terminador nulo de la cadena, no
se producir el salto y se devuelve el control mediante la instruccin jr.
Ejercicios
1. Por qu no hace falta multiplicar por 4 el ndice de la cadena?
2. La codicacin en ensamblador no reeja exctamente el cdigo C de la funcin.
Por qu? Codique una funcin que reeje exctamente el cdigo C y compare
su eciencia con la mostrada en la transparencia. Indique para ello el nmero de
instrucciones ejecutadas en cada versin de la funcin si se copia una cadena de 80
caracteres.
ICAIdea
Aritmtica. Nmeros 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 nmero sin signo (rango 0 2


n
1).

Un nmero con signo en complemento a 2 (rango


2
n1
2
n1
1).
Tanto las instrucciones aritmticas como las de carga
y comparacin han de distinguir si sus operandos son
con o sin signo.
Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 42
El procesador es una mquina capaz de procesar ristras de dgitos binarios. En el caso
del MIPS, ste puede trabajar con ristras de 8, 16 y 32 bits. El signicado de dichas ristras
de bits es totalmente indiferente para el procesador,
1
siendo responsabilidad del programador
su interpretacin.
Cuando se trabaja con nmeros enteros, stos pueden considerarse como nmeros sin
signo, con lo cual podremos representar nmeros en el rango de 0 a 2
n
1. o bien como
nmeros codicados en complemento a dos (rango de 2
n1
a 2
n1
1). Ahora bien, la
forma de operar con ambos tipos de nmeros es distinta, por lo que se usan instrucciones
distintas segn el tipo de datos utilizados. As, las instrucciones aritmticas, de carga y de
comparacin son distintas segn operen con datos sin signo o con signo.
En el caso de los lenguajes de alto nivel como C, al declarar una variable se informa al
sistema del tipo de sta. As, para crear un entero con signo se declara como int y sin signo
como unsigned int. Es entonces tarea del compilador elegir las operaciones necesarias
para operar correctamente con los datos. En cambio, cuando se programa en ensamblador,
esta tarea recae en el programador.
1
Salvo en el caso en que dihas ristras de bits sean parte de un programa.
ICAIdea
Aritmtica. Nmeros con y sin signo
Cuando se carga un nmero con signo de 16 u 8 bits
en un registro de 32, es necesario extender el bit de
signo. Ej:

-1 en 8 bits es 11111111

-1 en 16 bits es 11111111 11111111

-1 en 32 bits es 11111111 11111111 11111111


11111111
Esta extensin es necesaria porque los circuitos
aritmticos operan slo con nmeros de 32 bits.
Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 43
ICAIdea
Aritmtica. Nmeros con y sin signo
Cuando se carga un nmero sin signo de 16 u 8 bits
en un registro de 32, no hay que extender el bit de
signo. Ej:

255 en 8 bits es 11111111

255 en 32 bits es 00000000 00000000 00000000


11111111
Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 44
ICAIdea
Aritmtica. Nmeros con y sin signo
Las instrucciones de carga vistas hasta ahora cargan
nmeros 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 direccin par.

lw carga una palabra. No tiene sentido extender


el signo, pues no hay ms bits.
Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 45
Debido a que internamente el MIPS siempre realiza las operaciones con 32 bits, cuando
se carga un dato de 8 o 16 bits en un registro, es necesario que la cantidad representada por
los 32 bits sea la misma que la representada por los 8 o los 16 bits que se han cargado. Si
las cantidades almacenadas en 8 o 16 bits son sin signo, basta con copiar esos 8 o 16 bits en
los 8 o 16 bits menos signicativos del registro de 32 bits. Ahora bien, si los nmeros de 8
o 16 bits son con signo, es necesario copiar el bit de signo en los bits superiores del registro
de 32 bits para que se mantenga el signo del nmero. As, si tenemos almacenado en una
variable de 8 bits con signo el valor 11111110 (-2), al copiar dicha variable en un registro de
32 bits, habr que copiar el bit de signo en los bits 9 a 31 para que el nmero almacenado
en el registro sea tambin un -2. En cambio, si tenemos almacenado un nmero sin signo,
por ejemplo 11111110 (254), al copiar este nmero en un registro de 32 bits no habr que
extender el bit signo para que se almacene el 254 correctamente en el registro de 32 bits.
Las instruciones de carga vistas hasta ahora (lb y lw) trabajan con nmeros con signo.
En el caso de lw no tiene sentido hacer ninguna distincin, pues carga un nmero de 32 bits
en un registro de 32 bits y por tanto no hay que hacer extensin de signo.
Adems de estas dos instrucciones de carga existe una tercera lh que carga media palabra
(16 bits) en los 16 bits menos signicativos de un registro, extendiendo el bit de signo. Por
ejemplo, para cargar en t0 una media palabra cuya direccin est almacenada en el registro
s0, basta con ejecutar la instruccin:
lh $t0, 0($s0)
Las medias palabras han de estar alineadas en posiciones de memoria mltiplos de 2.
ICAIdea
Aritmtica. Nmeros con y sin signo
Las instrucciones de carga para nmeros 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 ms bits.
Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 46
Las instrucciones para cargar nmeros sin signo son iguales que las correspondientes
para nmeros con signo, salvo que su nemnico termina en u (de unsigned).
Aunque no se menciona en la transparencia, la media palabra a cargar con lhu ha de
estar almacenada en una direccin par.
Al igual que antes, no tiene sentido distinguir entre nmeros con signo o sin signo para
la carga de palabras de 32 bits, pues no hay que extender ningn bit de signo.
ICAIdea
Aritmtica. Nmeros con y sin signo
Las instrucciones de comparacin son distintas para
nmeros con signo o sin signo:

slt compara dos nmeros con signo.

sltu compara dos nmeros 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
Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 47
La comparacin entre dos nmeros depende de si stos son con signo o sin signo. Por
tanto el MIPS dispone de versiones de las instrucciones de comparacin para ambos tipos de
datos.
Al igual que antes, las instrucciones estudiadas hasta ahora comparan nmeros con signo.
Para comparar nmeros sin signo el formato de las instrucciones es el mismo salvo que el
nemnico termina en una u (de unsigned).
ICAIdea
Aritmtica. Nmeros con y sin signo
Ejemplo:

s0 = 11111111 11111111 11111111 11111111

s1 = 00000000 00000000 00000000 00000001


Cuanto valen t0 y t1 despus de ejecutar las
instrucciones?
slt $t0, $s0, $s1 # Con signo
sltu $t1, $s0, $s1 # Sin signo
Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 48
En el ejemplo, el registro s0 vale -1 si se interpreta como un nmero en complemento a
2 4.294.967.295 si se interpreta como un nmero sin signo. El registro s1, en cambio, vale
1 independientemente de cmo se interprete.
En la primera instruccin se realiza la comparacin con signo. Por tanto, como 1 < 1,
t0 se pondr a 1.
En cambio, en la segunda instruccin se realiza la comparacin sin signo, por lo que
como 4,294,967,295 > 1, t1 se pondr a 0.
ICAIdea
Aritmtica. Suma y resta
En las instrucciones de suma y resta puede ser
necesario saber si ha existido un desbordamiento.

En los nmeros sin signo, utilizados para


aritmtica de direcciones, se ignora.

En los nmeros con signo, dependiendo de la


aplicacin, puede ser necesario detectarlo.
Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 49
Al realizar una suma o una resta de dos nmeros de 32 bits, el resultado puede necesitar
33 bits si ambos nmeros son demasiado grandes. Como el resultado se almacena en un
registro de 32 bits, el bit ms signicativo se pierde. En estos casos se dice que se ha producido
un desbordamiento (overow en ingls).
El uso fundamental de los nmeros sin signo es la realizacin de operaciones con di-
recciones, en las cuales no se suele detectar el desbordamiento. En cambio, los nmeros con
signo suelen usarse en operaciones matemticas, en las que, dependiendo de la aplicacin,
puede ser necesario detectar si se ha producido un desbordamiento.
La mayora de los procesadores disponen de dos bits en el registro de estado para indicar
si se ha producido un desbordamiento:

El bit de accarreo (carry en ingls), el cual se pone a 1 cuando se produce un


desbordamiento en la suma sin signo.

El bit de desbordamiento (overow), el cual se pone a 1 cuando se produce un des-


bordamiento en la suma con signo.
En estos procesadores se incluyen adems instrucciones de salto condicional que saltan si
alguno de estos bits est a 1. Por tanto, para detectar un desbordamiento basta con ejecutar la
instruccin de salto condicional justo despus de la operacin aritmtica cuyo desbordamien-
to queremos comprobar. De esta forma el programa puede ejecutar una serie de isntrucciones
u otras en funcin de si se ha producido o no un desbordamiento. En el MIPS, segn se
muestra en la siguiente transparencia, la solucin adoptada es radicalmente distinta.
ICAIdea
Aritmtica. Suma y resta
MIPS dispone de dos tipos de instrucciones para la
suma y la resta en funcin del tratamiento del
desbordamiento.

add, addi, sub, generan una excepcin si se


produce un desbordamiento.

addu, addiu, subu no generan excepciones en


caso de desbordamiento.
Las instrucciones de suma se han estudiado antes. La
instruccin sub $t0, $s0, $s1 resta s0-s1 y
almacena el resultado en t0.
Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 50
El MIPS dispone de dos tipos de instrucciones aritmticas: unas que tienen en cuenta el
desbordamiento y otras que lo ignoran.
Las instrucciones add, addi y sub generan una excepcin si se produce un desborda-
miento. Una excepcin es una llamada a una funcin no planicada, es decir, que slo ocurre
cuando se da una situacin excepcional, como es un desbordamiento en este caso. As, cuan-
do al ejecutar alguna de estas instrucciones se produce un desbordamiento, la direccin de
la instruccin que ha provocado el desbordamiento se sita en un registro especial y la eje-
cucin del programa salta a una direcin predenida en la que se encontrar una rutina de
atencin de la excepcin. Esta rutina podr infomar al usuario del error y abortar el programa
o intentar tomar medidas correctoras y continuar el programa despus de la instruccin que
caus el desbordamiento.
Por otro lado, las instrucciones addu, addiu y subu realizan las mismas operaciones que
sus versiones con signo salvo que no generan una excepcin si se produce un desbordamiento.
El formato de la instruccin de resta es sub dest, orig1, orig2. Esta instruccin
resta el contenido de los registros orig1-orig2 y deposita el resultado en el registro dest.
Ntese que no existe la instruccin subi. Esto es debido a que la instruccin addi suma a
un registro una constante de 16 bits con signo, por lo que para restar una constante basta
con sumar dicha constante cambiada de signo. Conviene destacar que tanto las instrucciones
addi como addiu extienden siempre el signo de su constante de 16 bits antes de realizar la
operacin. Como se ha dicho antes la nica diferencia entre las operaciones sin signo y las
con signo es que las primeras no generan excepciones y las segundas s.
Como se ha dicho antes, otras arquitecturas poseen instrucciones de salto condicional
en funcin de si se ha producido o no un desbordamiento. Lamentablemente el MIPS no
dispone de dicha instruccin, por lo que si queremos detectar el desbordamiento sin utilizar
excepciones, es necesario realizarlo mediante una secuencia de instrucciones, tal como se
muestra a continuacin
5
0
-
2
ICAIdea
Aritmtica. 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 tambin?
bne $t3, $zero, Desb # Si sign(suma)!= sign(op)
# => desbordamiento
Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 51
Claramente la comprobacin del desbordamiento en el MIPS es realmente compleja.
Afortunadamente en la mayora de los casos no es necesario realizar dicha comprobacin de
forma explcita. Por ejemplo en C no se tienen en cuenta nunca los desbordamientos para
obtener programas ms ecientes, aun a costa de que se produzcan resultados errneos. Otros
lenguajes como Fortran o Ada si precisan que se detecten los desbordamientos, pues en las
aplicaciones escritas en dichos lenguajes prima mucho ms la abilidad de los programas
que su velocidad de ejecucin. No obstante, en estos lenguajes se suele utilizar una rutina de
excepcin para atender las excepciones numricas, por lo que la aproximacin seguida por el
MIPS es apropiada en estos casos.
El programa mostrado en la transparencia se basa en vericar en primer lugar si los sig-
nos de los dos sumandos son distintos, en cuyo caso nunca se producir un desbordamiento.
Para ello realiza una or exclusiva bit a bit de ambos sumandos con la instruccin MIPS xor.
El bit de signo del resultado de la XOR ser 1 si los signos de ambos sumandos son distintos
y 0 si son iguales. Por tanto, si los signos son distintos, en t3 tendremos un nmero negativo,
por lo que mediante la instruccin de salto condicional se saltar a la etiqueta nodesb. Si am-
bos nmeros tienen el mismo signo, se puede producir un desbordamiento, en cuyo caso el
resultado tendr distinto signo que los operandos. El resto del programa es similar al anterior,
slo que ahora se comprueba si los signos del resultado y de los sumandos son distintos, en
cuyo caso se salta a la etiqueta Desb para ejecutar el tratamiento del desbordamiento.
Como se ha comentado antes, en las sumas sin signo no suele ser necesario comprobar
el desbordamiento. Por ello el MIPS no generar ninguna excepcin en este caso. Si se ne-
cesita detectar un desbordamiento, la nica manera es usando la secuencia de instrucciones
mostradas en la siguiente transparencia.
ICAIdea
Aritmtica. 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
Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 52
En este caso el programa es ms corto, aunque ms difcil de entender.
En primer lugar se invierten todos los bits de t1. Para ello se utiliza la operacin nor que
calcula una OR negada bit a bit. Esta inversin es equivalente a calcular el complemento a 2 -
1 (recuerde que el complemento a 2 se calcula invirtiendo todos los bits y sumando 1). Como
el complemento a 2 de t1 es 2
32
-t1, el resultado de la operacin anterior ser 2
32
-t1-1. Si se
compara este resultado con t2, tenemos que:
2
32
t11 < t2 2
32
1 < t1+t2 (1)
Por tanto, si el resultado de la comparacin es cierto, el resultado de t1+t2 ser mayor de
2
32
1 y por tanto se necesitarn ms de 32 bits para representarlo. En consecuencia, al no
caber el resultado en 32 bits se habr producido un desbordamiento.
ICAIdea
Aritmtica. Multiplicacin
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
repeticin del bit de signo en mult.
Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 53
En el caso de la multiplicacin, el hardware es ligeramente distinto segn se multipli-
quen nmeros con signo o nmeros sin signo (de Miguel Anasagasti, 2000). Debido a esto, el
MIPS dispone de dos instrucciones para multiplicar: mult para nmeros con signo y multu
para nmeros sin signo. Ambas instrucciones multiplican el contenido de dos registros y al-
macenan el resultado en un registro de 64 bits. Como el producto de dos nmeros de 32 bits
nunca ser mayor de 64 bits, no se producir nunca ningn desbordamiento, por lo que ambas
instrucciones de multiplicacin no generan excepciones.
El registro de 64 bits en donde se almacena el resultado es accesible en sus dos mitades
(hi y lo) mediante dos instrucciones especiales. La instruccin mfhi (del ingls move from
high) traslada los 32 bits ms signicativos a un registro destino. De la misma forma, mflo
(del ingls move from low) traslada los 32 bits menos signicativos del resultado a un registro
destino. Por ejemplo, la instruccin mflo $s0 traslada los 32 bits menos signicativos del
resultado al registro s0.
Cuando se est evaluando una expresin aritmtica, interesa que todas las variables ten-
gan el mismo tamao. Por tanto, despus de realizar una multiplicacin, interesa almacenar
el resultado en 32 bits en lugar de 64 para proseguir operando con el. Si se necesitan ms
de 32 bits para almacenar el resultado, se habr producido un desbordamiento de 32 bits.
El MIPS no tiene ningn mecanismo hardware para detectarlo, siendo responsabilidad del
programador su deteccin. En el caso de multiplicaciones sin signo basta con comprobar que
el registro hi est a cero. En el caso de nmeros con signo, el registro hi ha de ser todo ceros
si lo es positivo o todo unos si lo es negativo.
Ejercicio
Escriba la secuencia de instrucciones para multiplicar sin signo s0 por s1 y almacenar
el resultado en s2. Si se produce un desbordamiento de 32 bits se pondr t0 a uno y si no se
dejar a cero. Repita el ejercicio para nmeros con signo.
ICAIdea
Aritmtica. Divisin
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 divisin por cero.
Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 54
Al igual que en la multiplicacin, son necesarias dos instrucciones para la divisin: div
para nmeros con signo y divu para nmeros sin signo. En ambos casos el resultado se
almacena en el mismo registro de 64 bits utilizado para la multiplicacin. En la parte alta
(hi) se almacena el resto y en la parte baja (lo) se almacena el cociente.
Conviene destacar que el MIPS no detecta la divisin por cero. Adems el resultado ob-
tenido en este caso es inpredecible. Por tanto es tarea del programador el evitar las divisiones
por cero para evitar sorpresas desagradables.
Ejercicio
Escriba una secuencia de instrucciones para dividir s0 entre s1 y almacenar el cociente
en el registro s2 y el resto en el registro s3. Si el divisor vale cero no se realizar la divisin
y se pondr a uno el registro t0. En caso contrario, despus de realizar la divisin se dejar
t0 a cero. Los nmeros almacenados en s0 y s1 son nmeros con signo.
ICAIdea
Aritmtica. Ej: (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
Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 55
En la transparencia se muestra el cdigo para implementar una funcin que calcule la
expresin (a0+a1)*a2/a3 (variables con signo). El resultado se devolver en v0 y en v1 se
devolver un 0 si no se ha producido ningn error en el clculo de la expresin o un 1 si se
produce desbordamiento en la multiplicacin o una divisin por cero.
En primer lugar se comprueba que a3 no sea cero. Si lo es, se salta al nal de la funcin,
desde donde se pone v1 a 1 para indicar el error y se retorna de la funcin.
Si a3 no es cero, se comienza a evaluar la expresin. En primer lugar se realiza la suma.
Si ocurriese un desbordamiento se producira una excepcin, desde donde se podra tratar el
error. Como an no se han estudiado las excepciones, se deja la implementacin de la rutina
de atencin a la excepcin para ms adelante. A continuacin se realiza la multiplicacin,
dejando el resultado en los registros t0 y t1. Como se pretende continuar la evaluacin de
la expresin usando nmeros de 32 bits, el resultado ha de poderse almacenar en t0, por lo
que t1 tendr que valer 0 si el resultado es positivo o 0xffffffff si el resultado es negativo.
Esta comprobacin se realiza en las instrucciones 6 a 11. En la instruccin 6 se comprueba el
signo del resultado. Si es positivo se ejecutar la instruccin 8 que saltar a la etiqueta Error
si t1 no vale cero. Si el resultado es negativo, en la instruccin 10 se comprueba si t1 vale
0xffffffff. Como las instrucciones de comparacin extienden el signo de la constante de 16
bits, comparar con -1 es comparar con 0xffffffff. Como la comparacin se realiza sin signo,
si t1 es distinto de 0xffffffff se producir el salto en la instruccin 11 para ir a la etiqueta
Error.
Si no hay desbordamiento en la multiplicacin, se procede a realizar la divisin y a
devolver el control a quien ha llamado a la funcin, aunque previamente se deposita el
resultado en v0 y un 0 en v1 para indicar que la evaluacin de la expresin se ha realizado
con xito.
Ejercicio
Modique la funcin anterior para comprobar explcitamente el desbordamiento de la
suma utilizando el algoritmo mostrado en la pgina 51
5
5
-
2
ICAIdea
Aritmtica y lgica
Aparte de la +,-,* y /, el MIPS dispone de una serie de
operaciones lgicas y aritmticas 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


Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 56
Aparte de las operaciones aritmticas estudiadas hasta ahora, en muchos programas es
necesario realizar operaciones lgicas a nivel de bit.
El MIPS incluye las instrucciones lgicas mostradas en la transparencia. Todas ellas
realizan una operacin lgica bit a bit entre los dos registros origen y depositan su resultado
en el registro destino. Se incluyen las dos operaciones lgicas fundamentales, AND y OR, as
como la XOR. Se incluye adems la operacin NOR, que realiza la misma operacin que una
OR salvo que se niega el resultado. Esta instruccin permite realizar la operacin fundamental
NOT. Cmo?
Las operaciones AND, OR y XOR disponen de versiones en las cuales el segundo ope-
rando es una constante de 16 bits. Como el registro con el que se opera es de 32 bits, los
16 bits superiores de la constante se ponen a 0 antes de realizar la operacin lgica. Recuer-
de que este comportamiento es distinto del ofrecido en las constantes de las operaciones de
suma, resta y comparacin, en las cuales se extiende el signo.
ICAIdea
Aritmtica y lgica
Por ltimo, el MIPS dispone de una serie de
instrucciones de desplazamiento de bits.

Despl. lgico a izq.: sll rd, ro, desp

Despl. lgico a izq. var.: sllv rd, ro, rdes

Despl. lgico a der.: srl rd, ro, desp

Despl. lgico a der. var.: srlv rd, ro, rdes

Despl. aritmtico a der.: sra rd, ro, desp

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


Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 57
El MIPS dispone de varias instrucciones de desplazamiento de bits. Estas instrucciones
pueden desplazar un registro origen el nmero de bits especicado en la constante desp o en
el registro rdes para los desplazamientos variables. El resultado se almacena en el registro
destino.
Cuando se desplaza a la izquierda se rellenan los bits vacantes con ceros. Por ejemplo
si se desplaza 01000111 a la izquierda tres posiciones, el resultado ser 00111000.
1
En cambio,
cuando se desplaza a la derecha caben dos posibilidades: rellenar con ceros (desplazamiento
lgico) o rellenar con el bit de signo (desplazamiento aritmtico). Por ejemplo, si se desea
desplazar el valor 10010011 dos bits a la derecha, si se realiza un desplazamiento lgico, el
resultado ser 00100100, pero si se realiza un desplazamiento aritmtico, el resultado ser
11100100.
Las instrucciones de desplazamiento tienen dos usos fundamentales. Los desplazamien-
tos lgicos se usan para manipular bits. Por ejemplo si se desean extraer los 16 bits ms
signicativos de un registro de 32 bits (s0) y almacenarlos en s1 se puede ejecutar la ins-
truccin srl $s1, $s0, 16. En este tipo de operaciones no es necesario extender el bit de
signo, por lo que se usan las instrucciones de desplazamiento lgico.
El otro uso de las instrucciones de desplazamiento es para realizar multiplicaciones y
divisiones por potencias de dos. Cada bit que se desplaza un nmero binario a la izquierda es
equivalente a multiplicar por 2. De la misma forma, cada bit que se desplaza a la derecha es
equivalente a dividir por 2, aunque en este caso si el nmero es negativo es necesario introdu-
cir unos por la izquierda para que se mantenga el signo. Por tanto, cuando se desee desplazar
1
Se han usado en el ejemplo nmeros de 8 bits para simplicar. El MIPS desplaza siempre
valores de 32 bits.
a la derecha para dividir por potencias de dos, ser necesario utilizar desplazamientos arit-
mticos. Conviene resaltar que en estas operaciones el MIPS no comprueba si se producen
desbordamientos.
5
7
-
2
ICAIdea
Aritmtica y lgica. 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:
Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 58
El cdigo C mostrado en la transparencia es el mismo que se utiliz en la pgina 25. Al
igual que antes, es necesario multiplicar por 4 el ndice del vector para acceder a cada uno de
los elementos. En el programa en ensamblador de la pgina 25 se utilizaron dos instrucciones
de suma para realizar dicha multiplicacin. Otra alternativa sera usar una instruccin de
multiplicacin, aunque en este caso se necesitaran tres instrucciones:
addi $t0, $zero, 4
multu $s2, $t0
mflo $t0
Obviamente no es la solucin ms apropiada. No obstante, si se tiene en cuenta que 4 es
una potencia de 2, podemos realizar la multiplicacin por 4 mediante desplazamientos. Como
4 = 2
2
, para multiplicar por 4 basta con desplazar 2 bits a la izquierda, que es lo que se ha
hecho en la primera instruccin del programa en ensamblador.
Ejercicio
En muchas ocasiones es ms eciente implantar una multiplicacin por una constan-
te como una serie de desplazamientos y sumas. Escriba una secuencia de instrucciones en
ensamblador que multipliquen el registro s0 por 5 y depositen el resultado en t0.
ICAIdea
Carga de constantes
Hasta ahora se ha visto cmo 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 pseudoinstruccin li hace el mismo trabajo:
li $s0, 0x12345678
Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 59
Aunque la mayora de las constantes usadas en los programas son menores de 16 bits,
en ciertas ocasiones es necesario usar constantes de 32 bits. Para ello, el MIPS dispone de
una instruccin de carga especial que toma una constante de 16 bits y la sita en los 16 bits
ms signicativos del registro destino, dejando los 16 bits menos signicativos a cero. Dicha
instruccin se denomina lui (del ingls load upper inmediate). Para cargar los bits menos
signicativos del registro se usa la instruccin ori, que realiza una OR bit a bit del registro
destino con una constante de 16 bits extendida con ceros en su parte superior. As, en el
ejemplo de la transparencia se realizar una OR entre:
0x12340000
0x00005678
Cuyo resultado es 0x12345678.
Como el lenguaje nativo del MIPS es un poco limitado, dada su naturaleza RISC, los en-
sambladores del MIPS disponen de una serie de pseudoinstrucciones para facilitarle la vida
a los programadores. Dichas pseudoinstrucciones no son ms que una especie de abrevia-
turas de varias instrucciones del MIPS. Una pseudoinstruccin muy til es la li (de load
inmediate), que carga una constante, independientemente de su tamao, en un registro. Cuan-
do el ensamblador encuentra esta pseudoinstruccin evala el tamao de la constante y si sta
es menor de 16 bits genera la instruccin ori rd, const. Si la constante es mayor de 16
bits, entonces genera la combinacin lui+ori vista en la transparencia.
Ejercicio
Utilizando el simulador SPIM, indique cual es la traduccin a instrucciones MIPS de la
pseudoinstruccin li para las siguientes constantes: 1, -1 y 0x10007. Se realiza siempre la
traduccin ptima?
ICAIdea
Para saber ms
En este tema slo se han mostrado algunas de las
instrucciones disponibles en el MIPS.
Un listado completo se encuentra en el apndice A de
(Patterson y Hennessy, 2000), disponible on-line en la
pgina del SPIM.
Los manuales completos de la arquitectura MIPS
(MIPS Technologies, 2002) se encuentran tambin
disponibles on-line en la pgina de MIPS
Technologies (accesible desde la pgina web de la
asignatura).
Estructura de Computadores Captulo 3b: Programacin en ensamblador del MIPS. p. 60
Referencias
de Miguel Anasagasti, P. (2000). Fundamentos de los computadores. Paraninfo-Thomson
learning.
MIPS Technologies (2002). MIPS32
TM
Architecture For Programmers. MIPS Technologies,
Mountain View, CA, 1 edition.
Patterson, D. A. y Hennessy, J. L. (2000). Estructura y diseo de computadores. Intercie
circuitera/programacin. Revert.

Вам также может понравиться