Examen: Parcial 3:2025_01_17:Datos - myTeachingURJC/2019-20-LAB-AO GitHub Wiki

Examen Parcial 2: 2024-11-13. Ciencia e Ingeniería de Datos

  • Tiempo: 50 minutos
  • Descripción: Examen Parcial 1. Laboratorio. Grado de Ciencia e Ingeniería de Datos
  • Fecha: 2024/Octubre/9
  • Temario: Sesiones L5, L6, L7 y L8

Contenido

Enunciado

Hacer un programa en RARS que escriba figuras geométricas en la pantalla utilizando como carácter de relleno el asterisco (*). Para ello, previamente preguntará al usuario qué figura escribir y sus dimensiones. Tras escribir la figura, volverá a repetir el proceso hasta que el usuario decida terminar, momento en el cual el programa informará del número de caracteres de relleno usados para todas las figuras mostradas y finalizará el programa.

Las figuras tendrán como dimensión máxima 10 y como mínima 0 (en cuyo caso, no imprimiría nada).

Ejemplo de ejecución:

¿Figura
a dibujar (0: rectángulo, 1: cuadrado, 2: triángulo, 3: terminar)?
1

¿Lado?
3

***

***

***

¿Figura
a dibujar (0: rectángulo, 1: cuadrado, 2: triángulo, 3: terminar)?
0

¿Ancho?
11

¿Ancho?
5

¿Alto?
2

*****

*****

¿Figura
a dibujar (0: rectángulo, 1: cuadrado, 2: triángulo, 3: terminar)?
8

¿Figura
a dibujar (0: rectángulo, 1: cuadrado, 2: triángulo, 3: terminar)?
2

¿Altura?
4

   *

  ***

 *****

*******

¿Figura
a dibujar (0: rectángulo, 1: cuadrado, 2: triángulo, 3: terminar)?
3

Total
caracteres figuras: 35

--
program is finished running (0) --

Nótese que cuando se introduce un valor inválido, el programa vuelve a repetir la pregunta hasta que se introduce uno válido.

El ejercicio se debe solucionar estructurándolo en subrutinas/funciones. Como mínimo, se deberán implementar linea, que permita escribir un carácter determinado un número dado de veces en pantalla (se sugiere que tenga un parámetro que controle si se realizará salto de línea al final), y rectangulo, cuadrado y triangulo, que escriban en pantalla (realizando las llamadas pertinentes a linea) la figura correspondiente y devuelvan el número de caracteres de relleno escritos. En la solución debe aprovecharse que el cuadrado es un caso especial de rectángulo. Se recomienda implementar también leeDato, que muestre una pregunta por pantalla y devuelva el entero respuesta del usuario (repetirá la pregunta hasta que el valor introducido esté entre 0 y un máximo dado).

Para construir el triángulo, nótese que el número de blancos al principio de línea va descendiendo en 1 y el número de caracteres de relleno va aumentando en 2. Por otro lado, hay varias formas de calcular el número de caracteres del cuerpo del triángulo. La siguiente “descomposición” le puede servir de ayuda para encontrar una de ellas:

NOTAS:

  • Por si le es de utilidad, se adjuntan algunos ASCII:
  • => 42 [espacio] => 32 [salto de línea] => 10
  • Recuerde que debe respetar la ABI RISC-V (Application Binary Interface for RISC-V).

  • Todo el código entregado debe ensamblar sin errores. En caso contrario, la calificación será 0.

  • Entrega todos los archivos pedidos comprimidos en un archivo .zip

Programa (5 ptos)

Solución al programa

figuras.asm

#  Programa: figuras.asm
# Propósito: Dibuja figuras en pantalla con un carácter de relleno
#     Autor: Javier Macías del Campo
#     Fecha: 22/12/2024

	.include "servicios.asm"

	.eqv CHAR 42           # ascii de * (carácter de relleno)
	.eqv MAX_DIM 10        # dimensión máxima de las figuras
	.eqv MAX_MENU 3        # opción mayor del menú

	.data			
							
	# cadenas interfaz con usuario		
menuTxt:  .string "¿Figura a dibujar (0: rectángulo, 1: cuadrado, 2: triángulo, 3: terminar)? "
anchoTxt: .string "¿Ancho? "
altoTxt:  .string "¿Alto? "
ladoTxt:  .string "¿Lado? "
alturaTxt:.string "¿Altura? "
totalTxt: .string "Total caracteres figuras: "

	.text

        li s0, CHAR   # carácter relleno
        li s1, 0      # total caracteres rellenos

	# bucle menú
bucle: 	la a0, menuTxt
	li a1, MAX_MENU		
	jal leeDato
	
	li t0, 0           
	bne a0, t0, eti1   # comprobamos si opción 0 (rectángulo)
	
	la a0, anchoTxt
	li a1, MAX_DIM
	jal leeDato
	mv s2, a0
	
	la a0, altoTxt
	li a1, MAX_DIM
	jal leeDato
	
	mv a1, a0
	mv a0, s2
	mv a2, s0
	jal rectangulo
	add s1, s1, a0
	b bucle
	
	
eti1:   li t0, 1
	bne a0, t0, eti2   # comprobamos si opción 1 (cuadrado)
	
	la a0, ladoTxt
	li a1, MAX_DIM
	jal leeDato
	
	mv a1, s0
	jal cuadrado
	add s1, s1, a0
	b bucle
	
eti2: 	li t0, 2
	bne a0, t0, eti3   # comprobamos si opción 2 (triángulo)
	
	la a0, alturaTxt
	li a1, MAX_DIM
	jal leeDato
	
	mv a1, s0
	jal triangulo
	add s1, s1, a0
	b bucle

eti3:	la a0, totalTxt    # opción 3
	li a7, PRINT_STRING
	ecall
	
	# escribimos el resultado
	mv a0, s1
	li a7, PRINT_INT
	ecall

        # terminamos
        li a7, EXIT
	ecall

leeDato.asm

# Subrutina: leeDato
#   Fichero: leeDato.asm
# Propósito: Muestra una pregunta y devuelve el entero respuesta del usuario. Repite la
#            pregunta hasta que el valor dado está entre 0 y el máximo dado.
#   Entrada: a0: texto pregunta, a1: valor máx. entero respuesta permisible
#    Salida: a0: valor entero dado por el usuario
#     Autor: Javier Macías del Campo
#     Fecha: 22/12/2024

	.include "servicios.asm"

	.globl leeDato
	
	.text
	
leeDato:
				
	mv t0, a0
	mv t1, a1
	
bucle:	mv a0, t0
	li a7, PRINT_STRING
	ecall
	
	li a7, READ_INT
	ecall
	
	bgt a0, t1, bucle
	bltz a0, bucle
	
	ret

linea.asm

# Subrutina: linea
#   Fichero: linea.asm
# Propósito: Dibuja una línea con un carácter dado
#   Entrada: a0: largo (nº caracteres línea), a1: carácter de la línea,
#            a2: 0=> sin salto de línea al final, 1=> salto de línea al final
#    Salida: (ninguna)
#     Autor: Javier Macías del Campo
#     Fecha: 22/12/2024

	.include "servicios.asm"

	.globl linea

	.eqv SALTO_LINEA 10   #ascii salto línea
	
	.text

linea:	

	mv t0, a0	# t0: nº caracteres línea
	mv a0, a1       # a0: carácter a imprimir (printChar no modifica a0)
	beqz t0, finLi

	# dibujamos la línea
bucle:	li a7, PRINT_CHAR
	ecall
	addi t0, t0, -1
	bnez t0, bucle
	
finLi:	# hacemos salto de línea si procede
	beqz a2, fin        #salto línea si a2=1
	li a0, SALTO_LINEA
	li a7, PRINT_CHAR
	ecall
	
fin:	ret

rectangulo.asm

# Subrutina: rectangulo
#   Fichero: rectangulo.asm
# Propósito: Dibuja un rectángulo en pantalla con un carácter dado
#   Entrada: a0: ancho, a1: alto, a2: carácter de relleno
#    Salida: Número de caracteres impresos ("área")
#     Autor: Javier Macías del Campo
#     Fecha: 22/12/2024

	.globl rectangulo

	.text
	
rectangulo:
	
	addi sp, sp, -32   # reservamos espacio en la pila
	sw ra, 28(sp)      # salvamos dirección de retorno
	sw s0, 0(sp)       # salvamos s0
	sw s1, 4(sp)       # salvamos s1
	sw s2, 8(sp)       # salvamos s2
	sw s3, 12(sp)      # salvamos s3

		
	mv s0, a0  	# s0: ancho
	mv s1, a1 	# s1: alto
	mv s2, a2  	# s2: caracter relleno	
	mul s3, s0, s1  # s3: "área" (nº caracteres rectángulo)
			
	beqz s0, fin    # si el ancho es 0, terminar
	beqz s1, fin    # si el alto es 0, terminar

	# escritura rectángulo, línea a línea (s1: contador-> altura pendiente de completar) 
bucle:	mv a0, s0
	mv a1, s2
	li a2, 1
	jal linea					
	addi s1, s1, -1
	bnez s1, bucle								
				
fin:
	mv a0, s3         # valor retorno (número caracteres "área")
	lw ra, 28(sp)     # restauramos dirección retorno desde la pila
	lw s0, 0(sp)      # restauramos s0
	lw s1, 4(sp)      # restauramos s1
	lw s2, 8(sp)      # restauramos s2
	lw s3, 12(sp)     # restauramos s3
	addi sp, sp, 32   # liberamos espacio ocupado en la pila
	ret

cuadrado.asm

# Subrutina: cuadrado
#   Fichero: cuadrado.asm
# Propósito: Dibuja un cuadrado en pantalla con un carácter dado
#   Entrada: a0: lado, a1: carácter de relleno
#    Salida: Número de caracteres impresos ("área")
#     Autor: Javier Macías del Campo
#     Fecha: 22/12/2024

	.globl cuadrado

	.text

cuadrado:

	addi sp, sp, -16   # reservamos espacio en la pila
	sw ra, 12(sp)      # salvamos dirección de retorno
	
	mv a2, a1
	mv a1, a0          # un cuadrado es un rectángulo con los lados iguales
	jal rectangulo
	
	lw ra, 12(sp)      # restauramos dirección retorno desde la pila
	addi sp, sp, 16    # liberamos espacio ocupado en la pila
	ret

triangulo.asm

# Subrutina: triangulo
#   Fichero: triangulo.asm
# Propósito: Dibuja un triangulo en pantalla con un carácter dado
#   Entrada: a0: altura, a1: carácter de relleno
#    Salida: Número de caracteres impresos ("área")
#     Autor: Javier Macías del Campo
#     Fecha: 22/12/2024

	.globl triangulo
	
	.eqv SPACE 32     # carácter espacio al escribir triángulo (espacio, ascii 32)

	.text

triangulo:

        addi sp, sp, -32   # reservamos espacio en la pila
	sw ra, 28(sp)      # salvamos dirección de retorno
	sw s0, 0(sp)       # salvamos s0
	sw s1, 4(sp)       # salvamos s1
	sw s2, 8(sp)       # salvamos s2
	sw s3, 12(sp)      # salvamos s3
		
	mv s0, a0	   # s0: altura
	mv s1, a1          # s1: carácter relleno 
	li s2, 1	   # s2: nº caracteres del triángulo en la línea actual
        mul s3, a0, a0     # s3: "área" (nº caracteres triángulo; es el cuadrado de la altura)
	
 	beqz s0, fin       # si la altura del triángulo es 0, terminamos
	
	# escritura del triángulo, líea a línea (s0: contador-> altura pendiente de completa)
bucle:	
	# imprimimos blancos iniciales
	addi s0, s0, -1    # número de blancos a imprimir (desciende en uno en cada iteración)
	mv a0, s0          
	li a1, SPACE	   # a1 = carácter espacio
	li a2, 0           # no retorno línea
	jal linea
	
	# imprimimos caracteres relleno
	mv a0, s2
	mv a1, s1
	li a2, 1	   # sí retorno línea
	jal linea
	
	addi s2, s2, 2     # número caracteres cuerpo triángulo aumenta dos en cada iteración

	bnez s0, bucle
		
				
fin:    mv a0, s3         # valor retorno
	lw s0, 0(sp)      # restauramos s0
	lw s1, 4(sp)      # restauramos s1
	lw s2, 8(sp)      # restauramos s2
	lw s3, 12(sp)     # restauramos s3
	lw ra, 28(sp)     # restauramos dirección retorno desde la pila
	addi sp, sp, 32   # liberamos espacio ocupado en la pila
	ret

Autores

  • Miguel Ángel de Miguel
  • Javier Macías

Licencia

Enlaces