Pr´actica 1: introducci ´on al simulador SPIM
1.
Motivaci´
on
Seguro que a estas alturas de la carrera sabe ya manejar un ordenador perfectamente. Incluso debe saber c´omo programarlos en un lenguaje de alto nivel como es C. Sin embargo, hasta ahora no ha visto c´omo funciona en realidad un ordenador por dentro, ya que los lenguajes de alto nivel abstraen la realidad de la m´aquina para que sea m´as f´acil trabajar con ellas. En esta pr´actica va a aprender que ahora en lugar de variables como en C, lo que tiene a su disposici´on son registros y posiciones de memoria. Adem´as veremos que estas variables tienen un rango limitado, por lo que se pueden cometer errores si no se anda con cuidado. Por ´ultimo veremos c´omo se usa el sistema operativo para realizar la entrada y salida del programa. As´ı se dar´a cuenta de que algo tan f´acil en C como es llamar a la funci´on
printf()en la realidad es un proceso bastante complejo.
2.
Objetivos
Esta pr´actica tiene varios objetivos principales:
Introducir al alumno en el manejo del simulador SPIM. En el laboratorio se va a manejar la versi´on para X Window System sobre Linux, denominada xspim.
Exponer los errores que se pueden producir en las operaciones aritm´eticas debidos al tama˜no finito de la ALU y de los registros internos del procesador.
Ilustrar el mecanismo de llamadas al sistema para solicitar servicios al sistema operativo.
3.
Tiempo de laboratorio
1 sesi´on
4.
Trabajo previo
Leer detenidamente el enunciado de la pr´actica y la documentaci´on del simulador SPIM.
5.
Memoria
Se entregar´an al finalizar la pr´actica los c´odigos fuente de los programas dise˜nados y las respuestas a las cuestiones formuladas.
6.
Arranque del simulador en Linux
Arrancar el ordenador seleccionando en el men´u de arranque la opci´on Linux2.4. Hay que estar atento, pues pasa-dos 10 segunpasa-dos se arranca Windows autom´aticamente. Cuando aparezca la ventana de login, introduzca su nombre de usuario y su clave. A continuaci´on ya puede abrir una ventana de comandos (mediante el men´uPrograms ->Sistema ->Terminal UNIX de GNOME) y arrancar el simulador mediante el comando:
Figura 1: xspim
xspimes el nombre del simulador y la opci´on-geometry 640x740+0+0especifica el tama˜no de la ventana y su posici´on. Es necesario especificar el tama˜no debido a que el tama˜no por defecto no cabe en la pantalla. El car´acter&se utiliza para ejecutar el programa en background de forma que se quede libre el terminal para introducir m´as comandos. En la pantalla aparecer´a una ventana como la mostrada en la figura 1. Como puede observar, la ventana se divide en 5 zonas:
En la primera zona, situada en la parte superior de la ventana, se muestran los registros del procesador.
En la segunda zona se han situado una serie de “botones” que permiten controlar el funcionamiento del simula-dor.
En la tercera zona se muestra el segmento de texto, que es la parte de la memoria en la que se sit´uan los programas. ´Este a su vez tiene dos partes, el programa de usuario y el programa de sistema (KERNEL). Adem´as, esta zona se divide en 4 columnas: en la primera columna se muestra la direcci´on de memoria, en la segunda su contenido en hexadecimal, en la tercera el c´odigo en ensamblador y en la cuarta el c´odigo tal como est´a escrito en el archivo fuente (el n´umero que precede la instrucci´on es el n´umero de l´ınea dentro de dicho archivo fuente). En la cuarta zona se muestra el segmento de datos, que a su vez se divide enDATA (datos del programa de usuario),STACK(pila) yKERNEL DATA(datos del sistema).
Por ´ultimo, la quinta zona muestra los mensajes del simulador.
Todas las zonas anteriores muestran s´olo una parte de la informaci´on que contienen. Para visualizar el resto, basta con pulsar con el rat´on sobre la zona deseada y a continuaci´on se pueden usar las teclas de avance y retroceso de p´agina para visualizar el resto de informaci´on de cada zona. Por ejemplo, si pulsa con el rat´on en la zona de registros y pulsa a continuaci´on la tecla de avance de p´agina, aparecer´an en la pantalla los registros de coma flotante de precisi´on simple.
A la derecha de las l´ıneas que dividen cada zona aparecen unos cuadrados negros. ´Estos permiten variar el tama˜no de las zonas arrastrando con el rat´on. No obstante, la zona de registros tiene un tama˜no m´ınimo y la de botones es fija.
7.
Arranque del programa en Windows
Una vez abierta la sesi´on, hay que ejecutar el archivo e:\spim.bat. Para ello, lo m´as f´acil es usar la opci´on ejecutar del men´u inicio. El funcionamiento de la versi´on de Windows es similar a la de Linux mostrada en el apartado anterior. Para m´as detalles puede consultar el manual del programa, disponible en la p´agina web del laboratorio.
8.
Introducci´
on de un programa
Arranque su editor de texto favorito (por ejemploxemacsen Linux onotepaden Windows) y teclee el siguiente programa en ensamblador:
# Programa simple para sumar dos variables
.data # zona de datos
datos: .word 2, 3 # las dos palabras que se suman
.text # zona de programas
.globl main # la etiqueta main ha de ser global
main: la $t0, datos # t0 apunta a la zona de datos. lw $t1, 0($t0)
lw $t2, 4($t0) # t1 y t2 contienen los datos a comparar.
add $t1, $t1, $t2
salida: jr $ra # Salimos de la rutina main().
Las palabras que comienzan con un punto:.data,.word,.texty.globl son directivas del ensamblador. Se utilizan para dar ´ordenes al ensamblador acerca de c´omo ha de generar el c´odigo. Los significados de cada una de las directivas utilizadas en este programa son:
.data: Indica al ensamblador que los siguientes elementos han de situarse en el segmento de datos. Se puede indicar opcionalmente una direcci´on para que coloque los elementos a partir de dicha direcci´on. Si no se indica nada se colocan a partir de la direcci´on 0x10010000.
.word: Guarda los valores que siguen a la directiva en palabras sucesivas de memoria.
.text: Indica al ensamblador que los siguientes elementos han de situarse en el segmento de texto (programas) del usuario.
.globl: Declara la etiqueta que le sigue como global, de forma que puede referirse desde otros archivos. Adem´as, en este programa se ha usado una instrucci´on que no se ha estudiado a´un en clase:la. En realidad se trata de una pseudoinstrucci´on que carga la direcci´on de la etiqueta (en lugar del dato que contiene la etiqueta) en el registro destino.
Cuando termine de introducir el programa guardelo en disco utilizando como extensi´on del nombre un.s
Carga del programa
Para cargar el programa, pulse sobre el bot´onloaden la versi´on de Linux o seleccione el men´uFile->Openen la versi´on de Windows. En la ventana que aparece seleccione el archivo con el c´odigo en ensamblador (Windows) o teclee su nombre completo (Linux). Como puede observar, el programa se carga a partir de la direcci´on0x00400020, pues de la0x00400000a la0x0040001Cest´a el c´odigo de arranque.
Ejecuci´on del programa
Una vez cargado, podemos pasar a ejecutarlo. Para ello en la versi´on Linux pulse sobre el bot´on run. En la de Windows puede usar el men´uSimulator->Go o pulsar la tecla F5. Aparecer´a una ventana en la que se puede seleccionar la direcci´on de arranque y los argumentos del programa. Pulseok para ejecutar el programa desde la direcci´on0x00400000, que es donde comienza el c´odigo de arranque que se encarga de saltar a la etiquetamainde nuestro programa mediante la instrucci´onjal. Compruebe si el resultado de la ejecuci´on es correcto.
Ejecuci´on paso a paso
Ejecute el programa paso a paso utilizando la ordenstep comenzando desde la direcci´on0x00400000. En la versi´on de Windows la ejecuci´on paso a paso se realiza pulsando la teclaF10. Adem´as, en Windows es necesario volver a cargar el programa de nuevo mediante el men´usimulator->Reload cada vez que se desee realizar una nueva ejecuci´on paso a paso.
¿Qu´e instrucci´on ha generado la pseudoinstrucci ´onla? ¿Por qu´e?
Puntos de ruptura (breakpoints)
Aunque la ejecuci´on paso a paso es muy ´util para depurar los programas, cuando ´estos tienen un tama˜no conside-rable puede llevarnos bastante tiempo ir ejecutando todo el programa hasta llegar a la zona en la que est´a el problema. Para evitar esto los puntos de ruptura permiten ejecutar el programa a su velocidad normal hasta que se llega a una instrucci´on determinada en la que se detiene la ejecuci´on y se devuelve el control al usuario de forma que ´este pueda inspeccionar los valores de las variables, ejecutar el resto del programa paso a paso, etc.
Mediante la opci´on breakpoints (men´usimulator->breakpoints en Windows) coloque un punto de ruptura en la primera instrucci´on del programa. Ejecute desde la direcci´on0x00400000(C´odigo de arranque). Verifique que el programa se detiene en la primera direcci´on del programa. Continue ejecutando el programa paso a paso.
Modificaci´on de datos
Mediante la opci´onset value(men´uSimulator->Set Valueen Windows) modifique la memoria para que el programa sume 7 + 4. Ejecute el programa y compruebe el resultado.
Para ver qu´e ocurre si no tenemos en cuenta que el rango de los registros es limitado, repita esta operaci´on para sumar 2.147.483.647 + 7. ¿Ocurre alg ´un error al ejecutar el programa? En caso afirmativo modifique el programa para que no se produzca el error. ¿Da el programa ahora un resultado correcto?
Ejecute ahora el programa paso a paso hasta la instrucci´on anterior a la suma. Modifique el valor de los registros
t1yt2mediante la opci´onset valuepara que se sume 1+2. Contin´ue la ejecuci´on del programa y compruebe el resultado.
9.
Llamadas al sistema
En la asignatura de sistemas operativos, estudiar´an que una de las misiones de ´estos es el facilitar el uso del hardware por parte de los programadores de aplicaciones. Para ello, todos los sistemas operativos disponen de un mecanismo para que los programas de aplicaci´on puedan solicitarle servicios. Estos servicios pueden ser tan simples como leer un dato del teclado o tan complejos como enviar una serie de datos por la Red. El simulador SPIM simula una serie de llamadas al sistema operativo mediante la instrucci´on syscall. Estas llamadas permiten, entre otras cosas, la entrada de datos por teclado y la salida de datos por un terminal.
Para realizar una llamada al sistema hay que colocar en el registrov0 un c´odigo que identifica el servicio que se desea y en los registrosa0–a3los argumentos necesarios. A continuaci´on se ejecuta la instrucci´onsyscallpara realizar la llamada. Si la llamada al sistema devuelve alg´un valor, ´este se deposita en el registrov0. En la figura A.17 del ap´endice A de (Patterson y Hennessy, 2000) se muestra un listado completo de los servicios soportados por SPIM. En esta pr´actica s´olo nos interesan tres:
Servicio C´odigo de llamada Argumentos Resultado
print int 1 a0= entero
print string 4 a0= dir cadena
read int 5 entero env0
Hasta ahora se han introducido los datos como constantes del programa y se ha dejado el resultado en un registro. Obviamente este modo de trabajo no es muy conveniente. Modifique el programa anterior para que lea dos enteros desde el teclado e imprima su suma en el terminal. Antes de cargarlo en el simulador es necesario borrar la memoria mediante el comandoclear ->Memory & Registers.
¿Qu´e ocurre al sumar 2.147.483.647 + 7?
Impresi´on de cadenas de caracteres
El interfaz actual, aunque mejor que la primera versi´on, deja bastante que desear. Ser´ıa conveniente poder impri-mir alg´un mensaje al usuario para que sepa lo que tiene que hacer. Para ello se puede utilizar la llamada al sistema
print stringque permite imprimir la cadena de caracteres cuya direcci´on est´a almacenada ena0. Las cadenas han de situarse previamente en el ´area de datos mediante la directiva.asciiz. As´ı, si se escribe dentro del ´area de datos:
cad1: .asciiz "Introduzca un entero "
El compilador crear´a un espacio en memoria y lo inicializar´a con la cadena de caracteres terminada con un\0. Modifique el programa anterior para hacerlo m´as “educado”. Un ejemplo de funcionamiento del programa se muestra a continuaci´on:
Introduzca un entero 4 Introduzca un entero 5 El resultado es 9
10.
Final de la pr´
actica
Una vez finalizada la pr´actica, cierre la sesi´on (Desktop ->Log Outen Linux).
El informe de la pr´actica ha de contener los listados de los programas realizados y las respuestas razonadas a las preguntas formuladas a lo largo de la pr´actica.
Referencias
Patterson, D. A. y Hennessy, J. L. (2000). Estructura y dise ˜no de computadores. Interficie circuiter´ıa/programaci ´on. Revert´e.