Examen: 2020_07_07:Teleco - myTeachingURJC/2019-20-LAB-AO GitHub Wiki
Examen convocatoria extraordinaria: 2020-07-07. Teleco
- Tiempo: 2h
- Objetivo:
- Solución de la convocatoria extraordinaria de los grados de IST, ITT, IT, IT-ADE y IT-AEROESPACIAL, con fecha 2020/Jul/07
Contenido
Enunciado
- Aquí está disponible el Enunciado en PDF
Solución comentada
TODO
Solución
Los cuatro ficheros pedidos son los siguientes:
- Fichero division.s
Por especificaciones del enunciado, el RISC-V del proyecto que nos ha pendido no tiene Unidad de División hardware, esto significa que NO TIENE INSTRUCCION DIV. Por eso nuestro jefe de proyecto nos pide que implementemos la división de dos números mediante software, usando el algoritmo de restas sucesivas
Si usas la instrucción DIV estás violando la especificación: Por un lado porque nos piden implementar la división por software, y por otro lado porque si usas div entonces NO estás siguiente el algoritmo que nos han dado, sino que estás implementando una cosa que te has inventado tu, y no lo que te ha pedido tu jefe de proyecto
#-- Programa para hacer la división por software
.globl division
.text
# -----------------------------------------------------
# - Funcion division(a,b): Calcular a / b y el resto
# - Entradas:
# - a0: Dividendo (a)
# - a1: Divisor (b)
# - Salidas
#- a0: cociente
#- a1: Resto
#------------------------------------------------------
division:
# -- Inicializar cociente y resto a 0
li t0, 0 #-- Cociente
li t1, 0 #-- Resto
bucle:
# -- Comprobar si Dividendo < Divisor (a0 < a1)
blt a0, a1, fin #-- Si: hemos terminado
#-- El divisor es mayor o igual que dividendo
#-- Calcular el resto r = a - b
sub t1, a0, a1 #-- t1 = a0 - a1
#-- El resto es el nuevo dividendo
mv a0, t1
#-- Incrementar el cociente
addi t0, t0, 1
# -- Siguiente iteracion
b bucle
fin:
#-- Devolver el cociente y el resto
mv a0, t0 #-- Cociente
mv a1, t1 #-- Resto
ret
- Programa test-division.s
.eqv EXIT 10
.eqv PRINT_STRING 4
.eqv READ_INT 5
.eqv PRINT_INT 1
.data
msg1: .string "\nIntroduce Dividendo: "
msg2: .string "Introduce Divisor: "
msg3: .string "Resultado:\n Cociente: "
msg4: .string "\n Resto: "
.text
bucle:
#-- Imprimir mensaje
la a0, msg1
li a7, PRINT_STRING
ecall
#-- Pedir dividendo al usuario
li a7, READ_INT
ecall
#-- Si es -1 terminamos
li t0, -1
beq a0, t0, fin
#-- Guardar el dividendo en s0
mv s0, a0
#-- Imprimir mensaje
la a0, msg2
li a7, PRINT_STRING
ecall
#-- Pedir divisor al usuario
li a7, READ_INT
ecall
#-- Guardar divisor en s1
mv s1, a0
#-- Hacer la division
mv a0, s0
mv a1, s1
jal division
#-- Guardar los resultados en s0 y s1
mv s0, a0
mv s1, a1
#-- Mostrar resultado
la a0, msg3
li a7, PRINT_STRING
ecall
#-- Imprimir cociente
mv a0, s0
li a7, PRINT_INT
ecall
#-- Imprimir el resto
la a0,msg4
li a7, PRINT_STRING
ecall
mv a0, s1
li a7, PRINT_INT
ecall
b bucle
fin:
li a7, EXIT
ecall
- Fichero divisible.s
.globl divisible
.text
#---------------------------------
#-- Funcion para determinar si un numero es divisible entre otro o no
#-- Entradas:
#-- a0: Primer numero (a)
#-- a1: Segundo numero (n) (n<=a)
#-- Salidas:
#-- a0: Devuelve 1 si a/n es una división exacta (resto 0)
#-- Devuelve 0 si a NO es divisible entre n
#------------------------------------------------------------------------
divisible:
#-- Se traa de una funcion intermedia,
#-- que llama a division por lo que es necesario
#-- crear la pila para guarlar la direccion de retorno
addi sp,sp,-16
#-- Guardar direccion de retorno
sw ra, 12(sp)
#-- Para saber si a es divisible entre n llamamos a division
#-- NO hace falta guardar nada en la pila porque en este caso
#-- los parámetros de divisible y division coinciden. Asi que
#-- llamamos a division directamente
jal division
#-- En a1 tenemos el resto
#-- Si el resto es 0, es divisible, por lo que hay que
#-- devolver 1.
#-- Si el resto es distinto de 0 NO es divisible, y devolvemos 0
beq a1, zero, es_divisible
#-- El resto es distinto de zero
li a0, 0 #-- No es divisible
b fin
es_divisible:
#-- El resto es cero
li a0, 1 #-- Es divisible
fin:
#-- Recuperar direccion de retorno
lw ra, 12(sp)
addi sp,sp, 16
ret
- Fichero test-divisible.s
.eqv EXIT 10
.eqv PRINT_STRING 4
.eqv PRINT_CHAR 11
.eqv READ_INT 5
.eqv PRINT_INT 1
.eqv N_INI 100
.eqv N_FIN 105
.data
msg1: .string "\nDivisores de "
msg2: .string "Divisores:\n"
.text
#-- S0 contiene el numero a comprobar
li s0, N_INI
next_num:
#-- Imprimir mensaje
la a0, msg1
li a7, PRINT_STRING
ecall
#-- Imprimir numero a comprobar
mv a0, s0
li a7, PRINT_INT
ecall
#-- En s1 tenemos los divisores
li s1, 0
#-- Salto de linea
li a0, '\n'
li a7, PRINT_CHAR
ecall
bucle:
#-- Incrementar divisor
addi s1, s1, 1
#-- Comprobar si es divisible entre s1
mv a0, s0
mv a1, s1
jal divisible
#-- a0 nos indica si es o no divisible
#-- Si no divisible, pasa al proximo divisor
beq a0, zero, bucle
#-- Imprimir el divisor
mv a0, s1
li a7, PRINT_INT
ecall
#-- Salto de linea
li a0, '\n'
li a7, PRINT_CHAR
ecall
#-- Es el divisor menor numero? Si: pasar al siguiente divisor
blt s1,s0, bucle
#-- El divisor es igual al numero:
#-- Hemos terminado con este numero
#-- Comprobar el siguiente numero
addi s0, s0, 1
#-- Si es <= que el maximo, repetimos
li t0, N_FIN
ble s0, t0, next_num
#-- Hemos terminado
fin2:
li a7, EXIT
ecall
Autores
- Katia Leal Algara
- Juan González-Gómez (Obijuan)