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:

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

Entrega

  • Fichero cambia_contrasena.asm (subrutina cambia_contrasena + subrutinas de apoyo)

Plantilla

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)

Licencia

Enlaces