Skip to content

Examen: 2023_06_29:GISAM:TELECO

Juan Gonzalez-Gomez edited this page Jul 3, 2023 · 14 revisions

Examen convocatoria extraordinaria: 2023-06-29. GISAM y 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

Contenido

Enunciado

El examen se ha realizado a través de Aula virtual. Consta de dos programas

AVISO

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

Programa 1 (5 ptos)

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)

output-1

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)

Programa 2 (5 Ptos)

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

Alt text

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

Solución del examen

Solución al programa 1

  • 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

Solución al programa 2

  • 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

Evaluación

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...

TEST automáticos

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

Ficheros a descargar:

Ejemplo

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-------

Autores

Licencia

Enlaces

Página principal


Sesiones de Prácticas

P1: Simulador RARs

L1: Práctica 1-1. RARs
L2: Práctica 1-2. Ensamblador
L3: Práctica 1-3. Variables

P2: E/S mapeada. Llamadas al sistema

L4: Pract 2-1. E/S mapeada
L5: Práctica 2-2: Inst. ecall
L6: Prác 2-3: Cadenas

P3: Bucles y Saltos condicionales

L7: Práct 3-1: Bucles y saltos
L8: Práct 3-2: Cadenas II

P4: Subrutinas

L9: Pract 4-1: Subrut. Nivel-1
L10: Pract 4-2: La pila
L11: Pract 4-3: Recursividad

P5: Memoria Dinámica

L12: Pract 5-1. Heap. Listas

VÍDEO DE DESPEDIDA

Ejercicios de examen

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

SOLUCIONES

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

Clone this wiki locally