Examen: Parcial 3:2025_05_19:Robótica - myTeachingURJC/2019-20-LAB-AO GitHub Wiki
Examen Parcial 3: 2025-05-19. Ingeniería en Robótica Software
- Tiempo: 60 minutos
- Descripción: Examen Parcial 3. Laboratorio. Grado de Ingeniería en Robótica Software
- Fecha: 2025/Mayo/19
- Temario: Sesiones L8, L9 y L10
Contenido
Enunciado
Implementar en lenguaje ensamblador del RISC-V la subrutina cambia_contrasena, en el fichero cambia_contrasena.asm, que pida una nueva contraseña para el usuario
Especificaciones de la funcion
- Nombre: cambia_contrasena
- Descripción: Subrutina que pide al usuario una nueva contraseña
- Fichero: cambia_contrasena.asm
- Restricciones de la contraseña:
- La nueva contraseña no puede ser igual a la anterior
- El tamaño de la contraseña puede ir de 6 a 12 caracteres
- Ha de tener al menos un dígito (0-9),
- Ha de tener al menos una mayúscula (A-Z)
- Ha de tener al menos una minúscula (a-z)
- Ha de tener al menos un carácter especial ( !"#$%&'()*+,-./)
- Argumentos de entrada
- a0: (string) Contraseña antigua
- Argumentos de salida
- a0: (int) 1: Nueva contraseña disponible, 0: Error
- a1: (string): Contraseña nueva
Es decir, ha de retornar la nueva contraseña en un string, siempre que sea correcta. En caso contrario se indicará que se ha producido un error (no es necesario especificar los diferentes tipos de errores que pudieran ocurrir)
Ficheros proporcionados
La subrutina ha de hacer uso de las funciones proporcionadas en los siguientes ficheros, sin realizar ninguna modificación en los mismos
- Ficheros entregados:
- main.asm: Invoca a la subrutina cambia_contrasena, que en caso de retornar una nueva contraseña la escribe en la variable global donde se almacena
- servicios.asm: Constantes definidas con las llamadas al sistema
- inputoutput.asm: Incluye todas las subrutinas para escribir en consola (salida estándar) y leer entradas solicitadas al usuario
- ascii_chars.asm: Incluye funciones de ayuda para determinar si un carácter es de un determinado tipo
- string_operations.asm: Incluye funciones de manejo de cadenas de caracteres (strings)
Recomendación para la implementación
Implementa la subrutina en pequeños pasos asegurando que cada uno de ellos funciona
Posibles pasos:
- Petición de contraseña a usuario y retorno de la misma en la subrutina
- Comparación para comprobar que no es la misma contraseña almacenada
- Obtención de la longitud de la cadena, comprobación de que está en el intervalo esperado. Gestión de error en el caso de que no cumpla las condiciones
- Comprobación de primera restricción respecto a los caracteres: existencia de un carácter especial en la nueva contraseña.
-Definición de un contador para los caracteres especiales
-Iteración, carácter a carácter, sobre la cadena que contiene la contraseña y comprobación si se trata de un
carácter especial. En cuyo caso, el contador se incrementaría
- Si el contador se ha incrementado, la contraseña es válida. En caso contrario, gestión el error.
- Se continúa con el resto de restricciones
Otras consideraciones:
- Es necesario respetar ABI de RISC-V, especialmente con el manejo de los registros
Entrega
- Fichero cambia_contrasena.asm (subrutina cambia_contrasena + subrutinas de apoyo)
Plantilla
- Plantilla proporcionada: Plantilla.zip
Solución
Esta es la solución completa, una vez implementados todos los puntos indicados. Es una de las muchísimas implementaciones que se puede hacer. También se pueden utilizar registros estáticos en vez de variables locales, guardándolos adecuadamente en la pila para no violar el convenio de uso de los registros
- Fichero: cambia_contrasena.asm
#--------------------------------------------------------
#-- cambia_contrasena
#--------------------------------------------------------
#-- Subrutina que pide al usuario una nueva contraseña
#-- La contraseña debe cumplir la siguiente especificación:
#-- - Su longitud debe estar entre 6 y 12 caracteres
#- - Contiene al menos un digito
#- - Contiene al menos una letra mayúscula
#- - Contiene al menos una letra miníscula
#- - Contiene al menos un carácter especial: !"#$%&'()*+,-.
#- - La nueva contraseña no puede ser igual a la anterior
#---------------------------------------------------------------
# ENTRADAS:
# * a0: (string) Contraseña antigua
# SALIDAS:
# * a0: (int) 1 - Nueva contraseña disponible, 0 - Error
# * a1: (string) Contraseña nueva
#----------------------------------------------------------------
# Implementa la subrutina en pequeños pasos asegurando
# que cada uno de ellos funciona
#
# Posibles pasos:
#
# 1. Petición de contraseña a usuario y retorno de
# la misma en la subrutina
# 2. Comparación para comprobar que no es la misma contraseña almacenada
# 3. Obtención de la longitud de la cadena, comprobación de que está
# en el intervalo esperado. Gestión de error en el caso de que
# no cumpla las condiciones
# 4. Comprobación de la primera restricción respecto a
# los caracteres: existencia de un carácter especial en la nueva contraseña
# -Definición de un contador para los caracteres especiales
# -Iteración, carácter a carácter, sobre la cadena que contiene
# la contraseña y comprobación si se trata de un carácter especial.
# En cuyo caso, el contador se incrementaría
# - Si el contador se ha incrementado, la contraseña es válida.
# En caso contrario, gestión el error.
# 5. Se continúa con el resto de restricciones
#
# Otras consideraciones:
# - Es necesario respetar ABI de RISC-V, especialmente con el manejo de los registros
.globl cambia_contrasena
#==========================================================
# SEGMENTO DE DATOS
.data
# TODO: Variables necesarias para la implementación de
# la subrutina cambia_contrasena
new_password_1:
.space 13
#==========================================================
# SEGMENTO DE CÓDIGO
.text
cambia_contrasena:
# TODO: Implementación de la subrutina aquí
#-- En esta implementacion se utilizan variables locales
#-- que se guardan en la pila
#-- Esta es la organizacion:
# Organizacion de la pila
#-------------
# 28: RA
#----
# 24: Direccion Contraseña antigua
#----
# 20: Direccion contraseña nueva
#-----
# 16: Puntero al caracter actual
#-----
# 12: Contador digitos
#-----
# 8: Contador mayúsculas
#------
# 4: Contador minúsculas
# -------
# 0: contador caracteres especiales.
#------------
addi sp, sp, -32
sw ra, 28(sp)
sw a0, 24(sp) #-- Contraseña antigua
# Pedir nueva contraseña
la a0, pwd1_msg
la a1, new_password_1
jal pide_contrasena
# Guardar contraseña introducida en la pila
la a0, new_password_1
sw a0, 20(sp)
#------- Comprobar condiciones
#---- La longitud debe estar entre 6 y 12 caracteres
#-- Obtener longitud de la contraseña del usuario
jal longitudString
#-- Comprobar la longitud minima
li t0, 6
blt a0, t0, cc_no_cumple
#-- Comprobar la longitud maxima
li t1, 12
bgt a0, t1, cc_no_cumple
# Recorrer la cadena comprobando si hay al menos
# un carácter de cada tipo
# Variables temporales en la pila
sw zero, 12(sp) # cuenta dígitos
sw zero, 8(sp) # cuenta mayúsculas
sw zero, 4(sp) # cuenta minúsculas
sw zero, 0(sp) # cuenta caracteres especiales
lw t4, 20(sp) #-- t4: Puntero a contraseña
sw t4, 16(sp)
cc_comprueba_condiciones_contrasena:
#-- Recorrer la cadena
#-- Comprobar si se ha llegado al final de la cadena
lw t5, 16(sp)
lb t6, 0(t5) #-- t6: Caracter actual
beqz t6, cc_fin_agregacion
#-- Si se encuentra \n se termina
li t0, '\n'
beq t6,t0,cc_fin_agregacion
#-- Comprobar si el caracter actual es un digito
mv a0, t6
jal esDigito
#-- Incrementar contador de digitos en la pila
lb t0, 12(sp)
add t0, t0, a0
sw t0, 12(sp)
#-- Obtener caracter actual de la pila
lw t5, 16(sp)
lb t6, 0(t5)
#-- Comprobar si el caracter actual es mayusculas
mv a0, t6
jal esMayuscula
#-- Incrementar contador de digitos en mayusculas
lb t0, 8(sp)
add t0, t0, a0
sw t0, 8(sp)
#-- Obtener el caracter actual de la pila
lw t5, 16(sp)
lb t6, 0(t5)
#-- Comprobar si el caracter actual esta en minusculas
mv a0, t6
jal esMinuscula
#-- Incrementar el contador de minusculas
lb t0, 4(sp)
add t0, t0, a0
sw t0, 4(sp)
#-- Leer caracter actual
lw t5, 16(sp)
lb t6, 0(t5)
#-- Comprobar si es un caracter especial
mv a0, t6
jal esCaracterEspecial
#-- Incrementar contador de caracteres especiales
lb t0, 0(sp)
add t0, t0, a0
sw t0, 0(sp)
#-- Incrementar el puntero de cadena
#-- para apuntar al siguiente caracter
lw t5,16(sp)
addi t5,t5,1
sw t5,16(sp)
#-- Repetir
b cc_comprueba_condiciones_contrasena
#-- Se ha terminado de analizar la cadena
cc_fin_agregacion:
#-- Ahora se comprueba si se cumplen los criterios
# comprueba numero de digitos, mayusculas, minusculas y caracteres especiales
#-- Comprueba que el numero de digitos sea > 0
lw t0, 12(sp)
beqz t0, cc_no_cumple
#-- Comprueba que el numero de mayusculas sea > 0
lw t0, 8(sp)
beqz t0, cc_no_cumple
#-- Comprueba que el numero de minusculas sea > 0
lw t0, 4(sp)
beqz t0, cc_no_cumple
#-- Comprueba que el numero de caracteres especiales sea > 0
lw t0, 0(sp)
beqz t0, cc_no_cumple
#-- Si llega hasta aqui es que la contraseña cumple las
#-- condicones
#-- Ahora se comprueba que es diferente a la almacenada
lw a0, 24(sp)
lw a1, 20(sp)
jal comparaStrings
beqz a0, cc_misma_contrasena
#-- Todo ok
#-- Indicar que contraseña cambiada
li a0, 1
#-- Devolver direccion de la contraseña
lw a1,20(sp)
b cc_fin
cc_no_cumple:
jal contrasena_no_cumple_criterios
li a0, 0
b cc_fin
cc_misma_contrasena:
# Imprimir mensaje indicando que nueva contraseña
# NO es valida por ser igual que la anterior
jal error_misma_contrasena
#-- Indicar que contraseña NO cambiada
li a0, 0
b cc_fin
cc_fin:
lw ra,28(sp) #restaura RA
addi sp, sp, 32
ret
Evaluación
TODO
Autor
- Juan Ignacio Pérez Andrés (Nacho)