mips_ejemplos_v1

Anuncio
EJEMPLOS DE USO DEL SIMULADOR MIPS
Antes de empezar
La siguiente tabla muestra material complementario que puede ser revisado para comprender
mejor los ejemplos tratados en la presente guía:
Documento
MARS Tutorial
SYSCALL
MIPS_Green_Sheet
firstProgs
shapesCode
MIPS_3000_Assembly_Pro
gramming_Part2
FirstProgram
R3000
MIPS-asm
Descripcion
Documento que explica cómo hacer uso del simulador MARS.
Documento que contiene todas las llamadas a sistema
implementadas en el simulador.
Tabla que contiene un resumen de las instrucciones del MIPS.
Archivo con algunos ejemplos de codificación de programas en el
MIPS
Archivo con algunos ejemplos de codificación de funciones en el
MIPS
Diapositivas que resumen muy bien las instrucciones más
frecuentemente usadas en los programas
Diapositivas que muestran los pasos a seguir para hacer un
programa en el mips.
Diapositivas que hablan de manera resumida sobre el procesador
mips R3000.
Tutorial excelente con diferentes ejemplos del mips.
Ejemplos
1. Hacer un programa que solicite dos números enteros por teclado y realice la suma de estos.
Solución:
La solución a este problema se realiza en el archivo ejemplo1.asm adjunto con el presente
documento. La siguiente figura muestra el programa en ejecución:
Si analiza el programa anterior notara que en este caso se suelen hacer llamadas al sistema, esto
con el fin de permitir la interacción del programa con el usuario. Para realizar llamadas al sistema
se emplea la instrucción syscall. Cuando se realiza una llamada al sistema se suspende la ejecución
del programa y se transfiere el control al sistema operativo, luego el sistema operativo mira el
contenido del registro $v0 para determinar cuál llamada del sistema se está haciendo y procede a
ejecutar las instrucciones asociadas a esta. Las llamadas de sistema de simulador, no son llamadas
reales pues no transfieren el control a un sistema operativo UNIX por ejemplo, en el caso, el
control es trasferido a un sistema operativo simulado muy simple que es parte del simulador.
En este caso, se hace uso de 3 diferentes llamadas a sistema, tal y como se muestra a
continuación:

Llamada a sistema para imprimir una cadena de caracteres: esta corresponde a la llamada a
sistema número 4, se pasa como argumento de entrada la cadena de caracteres a imprimir:

Llamada a sistema para imprimir un numero entero: Corresponde a la llamada número 1, se
pasa como argumento el entero a imprimir:

Llamada a sistema para imprimir un solicitar un numero entero por teclado: Corresponde a
la llamada número 5, no tiene argumentos de entrada; retorna en el registro $v0 el entero
ingresado por teclado:
Cuando una función retorna algo, suele ser muy común llevar este valor retornado a otro
registro ya que en posteriores llamados a funciones el registro $v0 será sobrescrito.

Llamada a sistema terminar el programa: Esta llamada es análogo a la función exit presente
en lenguajes de alto nivel, corresponde a la llamada número 10, se invoca para terminar el
programa:
V
Si observa la invocación a las llamadas a sistema notara algo y es que todas se llaman de manera
similar. Para esto, se siguen básicamente los siguientes pasos:

Pasar lo parámetros a la función: Esto se hace moviendo valores a los registros del mips para
el paso de funciones ($a0, $a1, $a2, $a3). Es necesario conocer como se invoca la función para
pasar los valores apropiados.
V

Llamar la función: Esto se hace cargando en el registro $v0, el valor asociado a la llamada del
sistema y posteriormente invocándola con la instrucción syscall.
V

Capturar el valor retornado por la función: Aquellas funciones que retornan algo, suelen
hacerlo en los registros $v0 y $v1, por eso suele ser de bastante utilidad llevar los valores
contenidos en estos registros a otros registros ($t0,…,$t9,$s0,…,$s7) ya que en posteriores
llamados a otras funciones los valores de los registros $v0 y $v1 serán sobrescritos.
V
La siguiente figura muestra las principales llamadas a sistema empleadas:
2. Hacer un programa que solicite dos números enteros por teclado y realice la suma de estos.
Solución:
La solución a este problema se realiza en el archivo ejemplo2.asm adjunto con el presente
documento. La siguiente figura muestra el programa en ejecución:
Observe que en este caso para solicitar una cadena de caracteres, el programa anterior hace
uso de la llamada a sistema número 8 a la cual se le pasan como argumentos la cadena a la
cual se llevara lo que se meta por teclado ($a0) y el número máximo de caracteres a leer ($a1).
La siguiente figura muestra la sección de código en la cual se hace esto:
Para declarar arreglos en el Mips se suele usar la directiva .space seguida del número de bytes
que contendrá el arreglo. Para el caso anterior se declaró un arreglo llamado nombre y se la
asigno un tamaño de 50 bytes.
La siguiente figura muestra las principales directivas empleadas:
3. Hacer un programa muestre el mensaje el ciclo se repite hasta que el usuario presione la tecla
q.
Solución:
La solución a este problema se realiza en el archivo ejemplo3.asm adjunto con el presente
documento. La siguiente figura muestra el programa en ejecución:
Para hacer que el programa repita de manera reiterada la solicito para el ingreso de datos se
debe implementar un ciclo, esto se hace por medio de instrucciones de salto ya sea
condicional o incondicional.
A continuación se resalta la parte que implementa el ciclo en el programa anterior:
Ciclo
Instrucción de salto condicional
Instrucción de salto incondicional
4. Modifique el programa anterior de manera que retorne la suma de varios números positivos
hasta que el usuario meta un número negativo.
Solución:
La solución a este problema se realiza en el archivo ejemplo4.asm adjunto con el presente
documento. La siguiente figura muestra el programa en ejecución:
No hay diferencia sustancial respecto al programa anterior, básicamente la estructura es la
misma.
5. Hacer un programa que permita realizar la suma de los elementos de un vector
(A[]={1,2,3,4,5,6,7}) de 7 elementos el cual se encuentra en memoria. El resultado debe ser
llevado a una variable y almacenado en memoria
Solución:
La solución a este problema se realiza en el archivo ejemplo5.asm adjunto con el presente
documento. La siguiente figura muestra el programa en ejecución:
Para resaltar del programa anterior, cada vez que se declara una variable a esta se asocia un
espacio en memoria, la figura anterior las direcciones de memoria y los contenidos del arreglo
A y las variables suma e i. Recuerde que la mayoría de las operaciones se hacen en los
registros del procesador ($t0,$s0,…) por lo tanto para poder acceder a estos lugares de
memoria es necesario usar las instrucciones de transferencia de datos entre memoria y
procesador; esto con el fin de leer, en cuyo caso se usan las operaciones load; o escribir, para
lo que se usa las operaciones store.
Otra cosa de vital importancia es que para acceder a cada uno de los elementos del arreglo se
deben realizar operaciones para cargar cada uno de los elementos de la matriz a un registro
del procesador para realizar diferentes operaciones. A continuación se resalta la porción de
código en la cual se hace dicha tarea:
Note que el acceso al vector se hace de manera indirecta. En este caso, para almacenar el
contenido de los registros en las diferentes variables (las cuales se encuentran en memoria) se
hace uso de la instrucción store tal y como se muestra a continuación:
6. Mejorar el problema anterior, de modo que el usuario pueda meter ingresar los 6 elementos
del vector por teclado, luego visualizar el contenido del vector y finalmente mostrar el
contenido de la suma
Solución:
La solución a este problema se realiza en el archivo ejemplo6.asm adjunto con el presente
documento. La siguiente figura muestra el programa en ejecución:
7. Mejorar el problema anterior de tal manera que se pueda que sume los elementos de un
vector de tamaño cualquiera.
Solución:
La solución a este problema se realiza en el archivo ejemplo7.asm adjunto con el presente
documento. La siguiente figura muestra el programa en ejecución:
Este ejemplo a diferencia del anterior se caracteriza por que hace uso de estructuras
dinámicas, es decir variables que se declaran en tiempo de ejecución no de compilación, por
dicha razón, no hay ninguna declaración de la variable asociada al vector en la sección de
datos.
Para declarar variables en tiempo de ejecución los lenguajes de programación suelen hacer
uso de alguna función. En el caso del lenguaje C esta función es malloc o sus variantes. Esta
función lo que hace es reservar en memoria un número de bytes consecutivos y devuelve
como parámetro un apuntador que contiene la dirección inicial de la cantidad de datos
reservados.
En el ensamblador del mips existe una llamada al sistema la cual hace esta tarea y
corresponde a la llamada número 9. La siguiente tabla muestra un ejemplo comparativo de
como se reserva dinámicamente memoria en C y en ensamblador.
int *p; // Apuntador al cual se va a
// llevar la dirección de
// memoria obtenida
// dinámicamente.
p = malloc(4*sizeof(int));
// Declaración de un
// array de 4 enteros (reserva
// de 16 bytes de memoria).
# En $t0 se llevara la dirección
# retornada por la función, este será
# análogo al apuntador p
li $a0,16
li $v0,9
syscall
move $t0,$v0
Cuando se usa la función del sistema para la asignación dinámica de memoria las variables
declaradas se almacenan en el heap. La siguiente grafica muestra el efecto en memoria al
llamar esta función:
Para este caso se usó la llamada del sistema para declarar el vector al cual se llevaran los
datos. Note que el valor devuelto por la llamada del sistema es la dirección base de la región
asignada (0x1004000 para este caso), este valor es llevado en nuestro ejemplo al registro $s0
con el fin de poder acceder a dicha región para lectura y escritura.
8. Realice el programa del problema 6 pero impleméntelo haciendo uso de las siguientes
funciones:
 meterVector: Esta función deberá al usuario permitir ingresar cada uno de los elementos
del vector.
 mostrarVector: Esta función deberá mostrar el vector en pantalla.
 sumarElementos: Esta función debe devolver la suma de los elementos del vector.
Solución:
La solución a este problema se realiza en el archivo ejemplo8.asm adjunto con el presente
documento. La siguiente figura muestra el programa en ejecución:
El código de las funciones se muestra a continuación:
Si observa el código del ejemplo notara que las funciones se definen después del main, similar
a como se suele hacer en muchos lenguajes de programación.
Como se puede notar se hace uso de labels para dar nombres a las funciones. Así mismo note
el empleo de la instrucción jr $ra, la cual es necesaria para retornar al programa principal
después de que se invoca la función. A continuación se muestra el programa principal y la
forma como se invocan en este las diferentes funciones:
Invocación de la
función
Note que para invocar la función, se deben primero llevar los valores a los argumentos de
entrada y posteriormente haciendo uso de la instrucción jal se invoca la función.
9. Realice el mismo problema anterior, pero en esta ocasión divídalo en dos archivos lo cuales
serán:
 Ejemplo9.asm: Este archivo contendrá la función principal (main).
 Funciones.asm: Este archivo contendrá la implementación de las funciones empleadas.
Solución:
Para solucionar este problema lo primero que se debe hacer es crear una nueva carpeta para
nuestro caso la carpeta se llama ejemplo 9. Luego en el editor se crean los dos archivos
(ejemplo9.asm y funciones.asm). Una vez se codifica el código de estos se procede a
ensamblar los códigos. Antes de hacer esto debemos asegurarnos que la opción para
ensamblar todos los archivos que hay en el directorio este habilitada; la siguiente figura
muestra esto:
Para que una función pueda ser vista en otro archivo diferente a aquel en el cual se
implementó se debe hacer uso de la directiva .globl. La siguiente figura muestra trozo del
archivo funciones.asm en la cual se hace uso de esta directiva.
Note que este archivo contiene solo la implementación de las funciones. En lo que respecta al
código del archivo ejemplo9.asm, en este, se implementa la función main y se hacen los
llamados a las funciones declaradas en el archivo funciones.
.globl también puede ser empleado con el fin de lograr que una variable pueda ser vista por
todos los archivos, recuerde, esta directiva se debe usar en el archivo en el cual se realizó la
declaración de la variable o la función. La siguiente figura muestra el uso de esta directiva con
variables, en este ejemplo estas variables tuvieron que ser declaradas globales ya que son
accedidas por las funciones las cuales se encuentran en un archivo diferente:
La siguiente figura muestra el programa en ejecución:
Para poder ensamblara el programa se debe estar parado en el archivo que contiene la
función principal (ejemplo9.asm) para que el programa pueda ejecutar apropiadamente.
10. Hacer las siguientes funciones usando lenguaje ensamblador del mips:
 mostrarElemento: Esta función muestra devuelve un elemento de la matriz ubicado en la
posición i, j.
 sumarFila: Esta función devuelve la suma de los elementos de una fila seleccionada.
 sumarColumna: Esta función devuelve la suma de los elementos de una columna dada.
 sumarElementos: Esta función retorna la suma de todos los elementos de la matriz.
Pruebe las funciones sobre la siguiente matriz de 3x4.
Solución:
A continuación se muestra el resultado de la ejecución del programa.
Para realizar el presente programa; se creó una nueva carpeta y en esta se crearon dos
archivos, funciones.asm y ejemplo10.asm, a continuación se muestra como se declara una
matriz y como esta se guarda en memoria:
Si observa la gráfica anterior notara que una matriz es almacenada en memoria llevando fila
por fila; conocer como se almacena una matriz es de vital importancia para poder acceder a
cada uno de los elementos de esta.
A continuación se muestra el código de la función sumarElementos:
Push del stack
Pop del stack
Como la función sumar elementos invoca a la función sumarFila es necesario guardar el
contexto de esta en el stack para que el programa no pierda el hilo de la ejecución y esto se
hace por medio de operaciones push y pop sobre el stack.
11. El siguiente programa muestra cuando se ejecuta crea un nuevo archivo llamado testout.txt
con la siguiente frase: The quick brown fox jumps over the lazy dog.
Solucion:
El código ejemplo11.asm contiene el programa que realizar esta tarea.
Referencias
http://www.arcos.inf.uc3m.es/~ec/dokuwiki/doku.php?id=ejemplos
https://docs.google.com/viewer?url=http%3A%2F%2Fdac.escet.urjc.es%2Fdocencia%2FETCSuperior%2Fteoria-cuat1%2FTema8b.pdf
http://www.arcos.inf.uc3m.es/~ec/dokuwiki/doku.php?id=ejemplos
https://www.soe.ucsc.edu/classes/cmpe012/Winter05/labs/Lab7.htm
http://www.utdallas.edu/~herman.harrison/mips/samples_webct/samples_webct.html
http://www.johnloomis.org/ece533/notes/spim/SPIMQuickReference.html
http://www.scss.tcd.ie/John.Waldron/itral/cahome.html
http://www.neuro.gatech.edu/groups/butera/Courses/2030/
http://courses.missouristate.edu/KenVollmar/Mars/Help/SyscallHelp.html
http://www.utdallas.edu/~hxh017200/cs3340/Spr11/cs3340_001.html
http://www.cs.sunysb.edu/~cse320/example.html
http://www.cs.ucsb.edu/~pconrad/ccs/cs1a/09F/lectures/1124/
http://www.cse.hcmut.edu.vn/~anhvu/teaching/2010/BTKT-KTMT/MIPS%20Green%20Card.pdf
http://www.cs.sunysb.edu/~cse320/
Descargar