-
Notifications
You must be signed in to change notification settings - Fork 22
Examen: 2023_06_29:GISAM:TELECO
- Tiempo: Dos horas
- Descripción: Examen final de laboratorio. Grados de ISAM y TELECO
- Fecha: 2023/Junio/29
-
Comentarios:
- Acceso a Internet permitido
- Entrega por Aula Virtual
El examen se ha realizado a través de Aula virtual. Consta de dos programas
- Ficheros a descargar:
Asegúrate que tus programas cumplen con los siguientes criterios. Si no se cumple alguno de ellos la nota será 0 en ese apartado
- Cumplimiento de especificaciones. Se deben cumplir las especificaciones indicadas en el enunciado: nombres de funciones, nombres de archivos, parámetros de las funciones, constantes, funcionalidad, etc. Compruébalo antes de entregar el examen
- Respetar el convenio. Resuelve las preguntas sin violar el convenio del uso de registros (ABI del RISC-V)
- Sin errores en tiempo de ejecución (Runtime errors). Tus programas no deben generar excepciones al ejecutarse
- Sin errores al ensamblar. Los ficheros entregados NO deben dar errores al ensamblarlos. Si una función la has dejado a medio hacer, asegúrate que al menos se ensambla sin errores
Estamos desarrollando una aplicación para la línea de comandos, que se ejecutará en un RV32I en un sistema empotrado. La tenemos que desarrollar en lenguaje ensamblador para ahorrar memoria. Nuestro jefe de proyecto nos ha entregado este programa principal de pruebas (prog1.s), el cual pide un comando al usuario, lo copia a otra zona de memoria y luego lo imprime en la consola para comprobar que se ha copiado correctamente.
Tras su ejecución esta es la salida que obtenemos en la consola (el usuario ha introducido la cadena ls -la
por teclado)
Nuestra misión es separar este programa en dos partes, manteniendo exactamente la misma funcionalidad. Por un lado hay que crear la función strcpy(src, dest)
que tiene dos argumentos de entrada. El primero (src) es la dirección de la cadena fuente y el segundo (dest) la dirección de la cadena destino. La función copia la cadena fuente en la destino y retorna. Esta función sólo realiza eso. No imprime nada en la consola, ni interactúa con el usuario. Sólo copia la cadena
Por otro lado hay que rehacer el programa principal para que use esta nueva función. Este programa principal interactúa con el usuario e imprime la misma salida en la consola, pero debe llamar a la función strcpy
para realizar la copia de la cadena
Se pide:
a) (2.5) Implementa la función strcpy
en el fichero 01_strcpy.s
b) (2.5) Implementa el nuevo programa principal en el fichero 01_main.s.
NOTA: No se te pide que inventes nada. Deberás modificar el código original para adaptarlo a lo pedido. Si el programa no es una adaptación del original, se considerará como violación de espacificaciones
FICHEROS A ENTREGAR: 01_strcpy.s
y 01_main.s
(Tu programa debe funcionar sólo con esos dos ficheros, sin depender de ninguno adicional)
Seguimos con el desarrollo de una aplicación en la línea de comandos, escrita en lenguaje ensamblador para un RV32I. Nuestro jefe de proyecto nos ha proporcionado la función skip(cad, car)
, en el fichero 02_skip.s
Esta función se usa para ignorar los caracteres iniciales de una cadena. El primer argumento (cad) es un puntero a la cadena, y el segundo (car) es el caracter a ignorar. Así, por ejemplo, si le pasamos el puntero a la cadena "***holi" y llamamos a la función skip indicando *
como segundo argumento, la función devolverá el puntero a la parte de la cadena donde NO están los asteriscos iniciales: "holi"
Nuestro jefe de proyecto nos pide crear la nueva funcion skip_spaces(cad)
que simplemente llama a la función skip()
pasando como argumento la misma cadena (cad) pero usando un espacio para el argumento car
. Es decir, su única misión es llamar, a su vez, a la función skip(cad, ' ')
. Otro ingeniero del equipo añadirá en el futuro más funcionalidad. Nuestra misión es simplemente crear el esqueleto.
Además, tenemos que crear un programa principal para comprobar que la función skip_spaces()
funciona correctamente. Este programa debe imprimir el prompt ($
), esperar a que el usuario introduzca una cadena, llamar a la función skip_spaces()
, imprimir el mensaje "Sin espacios iniciales: --" y luego la cadena sin los espacios iniciales. Esto se repite en un bucle hasta que el usuario apriete enter sin introducir nada más. En ese momento se termina el programa
En este pantallazo se muestra un ejemplo de ejecución del programa principal en la que el usuario ha introducido tres veces la cadena "holi"
, con 0, 2 y 4 espacios iniciales, y finalmente aprieta enter sin introducir nada
Comprobamos que en todos los casos, efectivamente, se imprime la cadena "holi" sin los espacios iniciales. Es la prueba de que nuestra función skip_spaces()
funciona correctamente
Se pide:
a) (2.5 ptos) Implementar la función skip_spaces()
en el fichero 02_skip_spaces.s
b) (2.5 ptos) Implementar el programa principal en el fichero 02_main.s
NOTA: Este programa está formado únicamente por tres ficheros: 02_skip.s, 02_skip_spaces.s y 02_main.s. Debe funcionar sin añadir ninguno más
FICHEROS A ENTREGAR: 02_skip_spaces.s
y 02_main.s
- Fichero 01_strcpy.s:
#------------------------------------------------------
#-- Funcion strcpy(src, dest)
#--
#-- Copiar la cadena fuente en la cadena destino
#--
#-- ENTRADAS:
#-- a0 : Src. Puntero a cadena fuente
#-- a1 : Dest. Puntero a cadena destino
#--
#-- DEVUELVE: Nada
#-------------------------------------------------------
.globl strcpy
strcpy:
bucle:
#-- Leer byte
lb t0, 0(a0)
#-- Copiarlo a cadena destino
sb t0, 0(a1)
#-- Si el byte leido es 0, hemos llegado al final. Salir del bucle
beq t0, zero, fin
#-- Incrementar punteros fuente y destino
addi a0, a0, 1
addi a1, a1, 1
#-- Repetir
b bucle
fin:
ret
- Fichero 01_main.s:
#--------------------------------------------------------
#-- Programa de pruebas. Este programa hace lo siguiente:
#--
#-- * Pide al usuario una cadena (que representa un comando)
#-- * Esta cadena se copia a otra zona de memoria (cmd)
#-- * Se imprime la nueva cadena para comprobar que se ha copiado bien
#------------------------------------------------------------------------
#-- Tamaño del buffer de caracteres
.eqv MAX 16
#-- Servicios del sistema operativo
.eqv EXIT 10
.eqv PRINT_STRING 4
.eqv READ_STRING 8
.data
buffer: .space MAX #-- Buffer de entrada
cmd: .space MAX #-- Zona donde copiar el comando introducido
prompt: .string "$ " #-- Prompt a mostrar al usuario
msg: .string "Comando: "
.text
#-- Imprimir el prompt
la a0, prompt
li a7, PRINT_STRING
ecall
#-- Leer comando introducido por el usuario
la a0, buffer
li a1, MAX
li a7, READ_STRING
ecall
#-- Copiar el buffer introducido a la zona de comando
#-- a0: Puntero a buffer (cadena fuente)
#-- a1: Puntero a cmd (cadena destino)
la a1, cmd
jal strcpy
#-- Imprimir mensaje al usuario
la a0, msg
li a7, PRINT_STRING
ecall
#-- Imprimir la cadena copiada
la a0, cmd
li a7, PRINT_STRING
ecall
#-- Terminar
li a7, EXIT
ecall
- Fichero 02_skip_spaces.s:
#-------------------------------------------
#-- Funcion skip_spaces(cad)
#--
#-- Saltar los espacios iniciales de la cadena nada
#-- Se debe implementar llamando a la funcion skip()
#--
#-- ENTRADAS:
#-- a0 (cad): Puntero a la cadena
#--
#-- DEVUELVE:
#-- a0: Direccion de la subcadena que no tiene espacios
#-- iniciales
#--
#----------------------------------------------------------------------
.globl skip_spaces
.text
skip_spaces:
#-- Es una funcion intermedia
#-- Hay que guardar la direccion de retorno en la pila
addi sp,sp,-16
sw ra, 12(sp)
#-- llamar a la funcion skip pasando como argumento un espacio
li a1, ' '
jal skip
#-- Recuperar la direccion de retorno
lw ra, 12(sp)
#-- Recuperar la pila
addi sp,sp,16
ret
- Fichero 02_main.s:
#-- Tamaño del buffer de caracteres
.eqv MAX 16
#-- Servicios del sistema operativo
.eqv EXIT 10
.eqv PRINT_STRING 4
.eqv READ_STRING 8
.data
#-- Prompt a mostrar al usuario
buffer: .space MAX #-- Buffer de entrada
prompt: .string "$ "
msg: .string "Sin espacios iniciales: --"
.text
loop:
#-- Imprimir el prompt
la a0, prompt
li a7, PRINT_STRING
ecall
#-- Leer comando introducido por el usuario
la a0, buffer
li a1, MAX
li a7, READ_STRING
ecall
#--- Saltar los espacios
jal skip_spaces
#-- Leer caracter siguiente
lb t0, 0(a0)
#-- Si es \n se termina
li t1, '\n'
beq t0,t1, fin
#-- a0 contiene la direccion de la cadena sin espacios
mv t1,a0
#-- Imprimir mensaje
la a0, msg
li a7, PRINT_STRING
ecall
#-- Imprimir la cadena sin espacios
mv a0, t1
li a7, PRINT_STRING
ecall
#-- Repetir
b loop
fin:
#-- Terminar
li a7, EXIT
ecall
La evaluación de cada apartado (2.5 ptos) de un programa se hace en dos fases:
-
Funcionalidad (1 ptos): Se comprueba si el programa funciona, y si cumple con las especificaciones (Nombre del fichero correcto, ensablado sin errores, sin errores en tiempo de ejecución, resultado correcto, variables definidas en sus posiciones de memoria especificadas, etc). Esto se hace mediante un script de test, que automatiza el proceso
-
Código (1.5 ptos): Se inspecciona visualmente cómo está hecho el código: código limpio, claro, con comentarios, instrucciones correctas, fallos de programación, etc...
La comprobación de las especificaciones se hace mediante programas de test independientes. Cada apartado se prueba de forma independiente. Si por ejemplo en un apartado me piden que implemente una función, esta se prueba contra un programa principal de prueba (NO el proporcionado por el estudiante). Y al revés, si se pide un programa principal, se prueba contra las funciones correctas (no las proporcionadas por el estudiante). Esto permite determiar si la interfaz implementada es la correcta, así como si se ha violado algún convenio
Para hacer ejecutar los scripts de prueba se deben descomprimir los ficheros test1.zip y test2.zip en el directorio donde están nuestros programas. La estrucutra de directorios será la siguiente:
> Mis programas.s
+-- TEST1
| +-- Scripts de prueba para problema 1
+-- TEST2
+-- Scripts de prueba para problema 2
IMPORTANTE!: Es necesario que el ejecutable con el rars esté dentro de las carpetas TEST1 y TEST2. Bien lo puedes copiar a mano, o bien puedes ejecutar el scritp get_rars.sh
para descargarlo automáticamente
Por ejemplo, supongamos que tenemos los ficheros del programa 1 en la carpeta programa-1
. Para comprobar el apartado a ejecutamos este comando:
obijuan@Hoth:~/Examen/Programa-1/TEST1
$ ./TEST-a.sh
La salida que aparecerá en la pantalla, si el fichero del apartado a es correcto, será similar a esta:
-----Ejecutando TEST-a-1-----
> ✅️ rars1_5.jar existe
> ✅️ 01_strcpy.s existe
> ➡️ PROBANDO: 01_strcpy.s
java -jar rars1_5.jar nc me ic 10000 main_TB.s ../01_strcpy.s
> COMPROBANDO VALORES recibidos
> ✅️ Subcadena 1 OK!
> ✅️ Subcadena 2 OK!
> ✅️ Convenio OK!
> Salida en consola:
Cadena de prueba...
Test
Convenio OK!!
> Ciclos de ejecución: 254
> ✅️ El programa termina llamando a EXIT
------FIN-------
- Katia Leal Algara
- Juan González-Gómez (Obijuan)
L1: Práctica 1-1. RARs
L2: Práctica 1-2. Ensamblador
L3: Práctica 1-3. Variables
L4: Pract 2-1. E/S mapeada
L5: Práctica 2-2: Inst. ecall
L6: Prác 2-3: Cadenas
L7: Práct 3-1: Bucles y saltos
L8: Práct 3-2: Cadenas II
L9: Pract 4-1: Subrut. Nivel-1
L10: Pract 4-2: La pila
L11: Pract 4-3: Recursividad
L12: Pract 5-1. Heap. Listas
Simulacro examen 1
GISAM. Ordinario. 2019-Dic-11
GISAM. Extra. 2020-Jul-03
GISAM. Ordinario. 2021-Ene-21
GISAM. Ordinario. 2022-Ene-10
GISAM. Extra. 2022-Jun-29
GISAM. Parcial 1. 2022-Oct-26
GISAM. Parcial 2. 2022-Nov-30
GISAM. Parcial 3. 2022-Dic-21
GISAM. Parcial 1. 2023-Oct-09
GISAM. Parcial 2. 2023-Nov-11
GISAM. Parcial 3. 2023-Dic-20
GISAM. Extra. 2024-Jun-17
GISAM. Parcial 1. 2024-Oct-14
GISAM. Parcial 2. 2024-Nov-13
GISAM. Parcial 3. 2024-Dic-16
TELECO. Ordinario. 2019-Dic-13
TELECO. Extra. 2020-Jul-07
TELECO. Ordinario. 2021-Ene-21
TELECO. Extra. 2021-Jul-02
TELECO. Ordinario. 2022-Ene-10
TELECO. Extra. 2022-Jun-29
TELECO. Ordinario. 2023-Ene-10
TELECO. Extra. 2023-Jun-29
TELECO. Parcial 1. 2023-Oct-20
TELECO. Parcial 2. 2023-Nov-17
TELECO. Parcial 3. 2023-Dic-22
TELECO. Extra. 2024-Jun-17
TELECO. Parcial 1. 2024-Oct-10
TELECO. Parcial 2. 2024-Nov-21
TELECO. Parcial 3. 2024-Dic-19
Robótica. Ordinario. 2020-Jun-1
Robótica. Extra. 2020-Jul-13
Robótica. Ordinario. 2021-Mayo-20
Robótica. Extra. 2021-Junio-16
Robótica. Parcial 1. 2022-Feb-25
Robótica. Parcial 2. 2022-Abril-1
Robótica. Parcial 3. 2022-Mayo-6
Robótica. Parcial 1. 2023-Feb-27
Robótica. Parcial 2. 2023-Mar-27
Robótica. Parcial 3. 2023-May-08
Robótica. Parcial 1. 2024-Feb-26
Robótica. Parcial 2. 2024-Mar-20
Robótica. Parcial 3. 2024-May-06
Robótica. Extra. 2024-Junio-24
Datos. Parcial 1. 2023-Oct-09
Datos. Parcial 2. 2023-Nov-15
Datos. Parcial 3. 2023-Dic-20
Datos. Parcial 1. 2024-Oct-09
Datos. Parcial 2. 2024-Nov-13
Práctica 1: Sesiones 1,2 y 3
Práctica 2: Sesiones 4, 5 y 6
Práctica 3: Sesiones 7 y 8
Práctica 4: Sesiones 9, 10 y 11
Práctica 5: Sesión 12