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