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

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

Licencia

Enlaces