Practica 5: Soluciones a los ejercicios - myTeachingURJC/2019-20-LAB-AO GitHub Wiki

Práctica 5

Sesión 10

Solución a los ejercicios de la Sesión de laboratorio L12:5-1

Ejercicio 1

#-- Solución al ejericico 1
#-- Programa principal

	.include "servicios.asm"

	.data
msg:	.string "Introduce numeros enteros positivos:\n"	
msg2:   .string "\nLISTA:\n"
			
	.text
	
	#-- Usamos s0 como puntero de acceso a la lista
	#-- Inicialmente es NULL
	li s0, 0
	
	#-- Imprimir mensaje
	la a0, msg
	li a7, PRINT_STRING
	ecall
	
	#-- Pedir números hasta que se introduzca uno negativo
next:	
	#-- Pedir Numero entero
	li a7, READ_INT
	ecall
	
	#-- Si el a0 < 0, finalizar la introduccion de numeros
	blt a0, zero, fin
	
	#-- Guardar el numero en la lista
	mv a1, a0
	mv a0, s0
	jal create
	
	#-- Guardamos en s0 la cabeza de la lista
	mv s0, a0
	
	#-- repetir
	b next
	
fin:
	#----- Mensaje 2
	la a0, msg2
	li a7, PRINT_STRING
	ecall 
	
	#-- Imprimir la lista
	mv a0, s0
	jal print
	
	#-- Terminar
	li a7, EXIT
	ecall

Ejercicio 2

El programa principal es el mismo que el del ejercicio 1. La nueva subrutina de print es esta:

#--------------------------------------
#-- Subrutina: Imprimir el contenido de una lista enlazada en sentido inverso
#-- Se imprime usando un algoritmo recursivo
#-- 
#-- ENTRADA: 
#--   a0: Puntero a la lista a imprimir
#--
#-- SALIDA: Ninguna
#------------------------------------------------------------

	.include "servicios.asm"
	
	.globl print
	
	#---- Informacion sobre el nodo
	.eqv NEXT 0  #-- Offset del campo NEXT
	.eqv NUM 4   #-- Offset del campo NUM
	
	.text
print:	

	#-- Si es una lista vacia, terminar
	beq a0, zero, fin

	#-- No es una lista vacia
	#-- Crear la pila para guardar la direccion de retorno
	addi sp,sp,-16
	sw ra, 12(sp)
	
	#-- Guardar a0 en la pila, para preservarlo
	sw a0, 8(sp)
	
	#-- Obtener el puntero al siguiente nodo
	lw a0, NEXT(a0)
	
	#-- Imprimir la sublista en orden inverso
	jal print
	
	#-- Recuperar el puntero a la lista original
	lw a0, 8(sp)
	
	#-- Imprimir el valor del nodo
	lw a0, NUM(a0)
	li a7, PRINT_INT
	ecall
	
	#-- Imprimir '\n'
	li a0, '\n'
	li a7, PRINT_CHAR
	ecall
	
	#-- Recuperar direccion de retorno
	lw ra, 12(sp)
	addi sp,sp,16
	
fin:	
	#-- Terminar
	ret

Ejercicio 3

Esta es la implementación de la función len(), usando un algoritmo iterativo:

#------- Calcular la longitud de una lista 
#---- Algoritmo iterativo
#--- SUBRUTINA len
#--   ENTRADAS: 
#--     a0: Puntero de acceso a la lista
#--
#--   DEVUELVE:
#--     a0: Número de nodos en la lista
#----------------------------------------------
	
	.globl len
	
	#-- Informacion sobre la lista
	.eqv NUM 4
	.eqv NEXT 0
	
len:
	#-- Usamos t0 como contador
	li t0, 0
	
next:
	#-- Si a0 es NULL, terminar
	beq a0, zero, fin
	
	#-- Es un nodo. INcrementar el contador
	addi t0, t0, 1
	
	#-- Apuntar al siguiente nodo
	lw a0, NEXT(a0)
	
	#-- Repetir
	b next
	
fin:

	#-- Devolver en a0 la longitud
	mv a0, t0

	ret

y este es el programa principal modificado:

#-- Solución al ejericico 3
#-- Programa principal

	.include "servicios.asm"

	.data
msg:	.string "Introduce numeros enteros positivos:\n"	
msg2:   .string "\nNumero de elementos de la LISTA: "
			
	.text
	
	#-- Usamos s0 como puntero de acceso a la lista
	#-- Inicialmente es NULL
	li s0, 0
	
	#-- Imprimir mensaje
	la a0, msg
	li a7, PRINT_STRING
	ecall
	
	#-- Pedir números hasta que se introduzca uno negativo
next:	
	#-- Pedir Numero entero
	li a7, READ_INT
	ecall
	
	#-- Si el a0 < 0, finalizar la introduccion de numeros
	blt a0, zero, fin
	
	#-- Guardar el numero en la lista
	mv a1, a0
	mv a0, s0
	jal create
	
	#-- Guardamos en s0 la cabeza de la lista
	mv s0, a0
	
	#-- repetir
	b next
	
fin:
	
	#-- Calcular el numero de elementos de la lista
	mv a0, s0
	jal len
	
	#-- Guardar la longitud en t0
	mv t0, a0
	
	#----- Mensaje 2
	la a0, msg2
	li a7, PRINT_STRING
	ecall 
	
	#-- Imprimir su longitud
	mv a0, t0
	li a7, PRINT_INT
	ecall
	
	#-- Terminar
	li a7, EXIT
	ecall

Ejercicio 4

Implementación de la función len() usando un algoritmo recursivo:

#------- Calcular la longitud de una lista 
#---- Algoritmo recursivo
#--- SUBRUTINA len
#--   ENTRADAS: 
#--     a0: Puntero de acceso a la lista
#--
#--   DEVUELVE:
#--     a0: Número de nodos en la lista
#----------------------------------------------
	
	.globl len
	
	#-- Informacion sobre la lista
	.eqv NUM 4
	.eqv NEXT 0
	
len:
	#-- Usamos t0 como acumulador
	li t0, 0
	
	#-- Si a0 es NULL, terminar
	beq a0, zero, fin
	
	#-- Crear la pila
	addi sp, sp, -16
	sw ra, 12(sp)
	
	#-- Apuntar al siguiente nodo
	lw a0, NEXT(a0)
	
	#-- Calcula la longitud de la sublista
	jal len
	
	#-- Sumar un elemento mas
	addi t0, a0, 1
	
	#-- Recuperar direccion de retorno
	lw ra, 12(sp)
	addi sp, sp, 16
	
fin:

	#-- Devolver en a0 la longitud
	mv a0, t0

	ret

Ejercicio 5

Implementación de la función sum() con algoritmo iterativo

#------- Calcular la suma de todos los elementos de la lista
#---- Algoritmo iterativo
#--- SUBRUTINA sum
#--   ENTRADAS: 
#--     a0: Puntero de acceso a la lista
#--
#--   DEVUELVE:
#--     a0: Suma de sus elementos
#----------------------------------------------
	
	.globl sum
	
	#-- Informacion sobre la lista
	.eqv NUM 4
	.eqv NEXT 0
	
sum:
	#-- Usamos t0 como acumulador de la suma
	li t0, 0
	
next:
	#-- Si a0 es NULL, terminar
	beq a0, zero, fin
	
	#-- Es un nodo. Leer su valor
	lw t1, NUM(a0)
	
	#-- Sumarlo al acumulador
	add t0, t0, t1
	
	#-- Apuntar al siguiente nodo
	lw a0, NEXT(a0)
	
	#-- Repetir
	b next
	
fin:

	#-- Devolver en a0 la suma total
	mv a0, t0

	ret

Este es el programa principal:

#-- Solución al ejericico 5
#-- Programa principal

	.include "servicios.asm"

	.data
msg:	.string "Introduce numeros enteros positivos:\n"	
msg2:   .string "\nSuma de los elementos: "
			
	.text
	
	#-- Usamos s0 como puntero de acceso a la lista
	#-- Inicialmente es NULL
	li s0, 0
	
	#-- Imprimir mensaje
	la a0, msg
	li a7, PRINT_STRING
	ecall
	
	#-- Pedir números hasta que se introduzca uno negativo
next:	
	#-- Pedir Numero entero
	li a7, READ_INT
	ecall
	
	#-- Si el a0 < 0, finalizar la introduccion de numeros
	blt a0, zero, fin
	
	#-- Guardar el numero en la lista
	mv a1, a0
	mv a0, s0
	jal create
	
	#-- Guardamos en s0 la cabeza de la lista
	mv s0, a0
	
	#-- repetir
	b next
	
fin:
	
	#-- Calcular la suma de los elementos
	#-- de la lista
	mv a0, s0
	jal sum
	
	#-- Guardar el resultado en t0
	mv t0, a0
	
	#----- Mensaje 2
	la a0, msg2
	li a7, PRINT_STRING
	ecall 
	
	#-- Imprimir resultado
	mv a0, t0
	li a7, PRINT_INT
	ecall
	
	#-- Terminar
	li a7, EXIT
	ecall

Ejercicio 6

Implementación de la función sum() usando algoritmo recursivo:

#------- Calcular la suma de los elmeentos de la lista 
#---- Algoritmo recursivo
#--- SUBRUTINA sum
#--   ENTRADAS: 
#--     a0: Puntero de acceso a la lista
#--
#--   DEVUELVE:
#--     a0: suma de los elementos de la lista
#----------------------------------------------
	
	.globl sum
	
	#-- Informacion sobre la lista
	.eqv NUM 4
	.eqv NEXT 0
	
sum:
	#-- Usamos t0 como acumulador
	li t0, 0
	
	#-- Si a0 es NULL, terminar
	beq a0, zero, fin
	
	#-- Crear la pila
	addi sp, sp, -16
	sw ra, 12(sp)
	
	#-- Guardar en la pila el puntero a la lista
	sw a0, 8(sp)
	
	#-- Apuntar al siguiente nodo
	lw a0, NEXT(a0)
	
	#-- Calcula la suma de la sublista
	jal sum
	
	#-- Guardar en t0 la suna de la sublista
	mv t0, a0
	
	#-- Recuperar puntero al nodo actual
	lw a0, 8(sp)
	
	#-- Leer el valor del nodo actual
	lw t1, NUM(a0)
	
	#-- Sumar la sublista con el valro actual
	add t0, t0, t1
	
	#-- Recuperar direccion de retorno
	lw ra, 12(sp)
	addi sp, sp, 16
	
fin:

	#-- Devolver en a0 la longitud
	mv a0, t0

	ret

El programa principal es el mismo que el del ejercicio 5

Ejercicio 7

Implementación de la subrutina append(), con algoritmo iterativo:

#-- Añadir un elemento al final de la lista
#--
#--  ENTRADA:
#--    a0:  Puntero a la lista
#--    a1:  Numero a guardar en la lista
#--
#--  SALIDAS:
#--    Ninguna
#--------------------------------------------------------

	.globl append
	
	#---- Informacion sobre el nodo
	.eqv NEXT 0  #-- Offset del campo NEXT
	.eqv NUM 4   #-- Offset del campo NUM
	
append:

	#-- Es una subrutina intermdia
	#-- Necesitamos crear la pila
	addi sp, sp, -16
	sw ra, 12(sp)

	#--- Primero recorremos la lista 
	#--- hasta llegar al último nodo
	#--- Sabemos si es el ultimo portque NEXT es 0
	
next:	
	#-- Leer el campo next
	lw t0, NEXT(a0)

	#-- Si es el ultimo elemento
	#-- salimos del bucle
	beq t0, zero, cont
	
	#-- Actualizar a0 para apuntar al siguiente elemento
	mv a0, t0
	
	#-- Repetir
	b next

cont:	
	#--- a0 apunta al último elemento de la lista
	#-- Guardamos el puntero en la pila
	sw a0, 8(sp)
	
	#-- Crear un nodo nuevo, con next = 0 y num = a1
	li a0, 0
	jal create
	
	#-- Recuperar el puntero del nodo. Lo metemos en t0
	lw t0, 8(sp)
	
	#-- Hacemos que su campo next apunter al nuevo nodo creado
	sw a0, NEXT(t0)
	
	
	#-- Recuperar direccion de retorno 
	lw ra, 12(sp)
	addi sp, sp, 16

	ret

El programa principal es este:

#-- Solución al ejericico 7
#-- Programa principal

	.include "servicios.asm"
			
	.text
	
	
	#-- Meter el número 1 en la lista
	li a0, 0
	li a1, 1
	jal create
	
	#-- Mover el puntero de acceso a la lista a s0
	mv s0, a0
	
	#-- Llamar a add para añadir a la lista el numero 2
	li a1,2
	jal append
	
	#-- Añadir el numero 3
	mv a0, s0
	li a1, 3
	jal append
	
	#-- Imprimir la lista
	mv a0, s0
	jal print
	
	
	#-- Terminar
	li a7, EXIT
	ecall

Ejercicio 8

Implementación de la función append() recursiva:

#-- Añadir un elemento al final de la lista
#-- Algoritmo recursivo
#--
#--  ENTRADA:
#--    a0:  Puntero a la lista
#--    a1:  Numero a guardar en la lista
#--
#--  SALIDAS:
#--    Ninguna
#--------------------------------------------------------

	.globl append
	
	#---- Informacion sobre el nodo
	.eqv NEXT 0  #-- Offset del campo NEXT
	.eqv NUM 4   #-- Offset del campo NUM
	
append:

	#-- En todos los casos hay que llamar a otra subrutina
	#-- Hay que crear la pila
	addi sp, sp, -16
	sw ra, 12(sp)

	#-- Leer el campo next
	lw t0, NEXT(a0)

	#-- Si es el ultimo elemento
	#-- creamos nodo y lo enlazamos
	beq t0, zero, crear
	
	#-- No es el último: Insertar el valor en la sublista
	mv a0, t0
	jal append
	
	b fin
	
crear:  
	
	#-- Guardar el puntero al ultimo nodo en la pila
	sw a0, 8(sp)
	
	#-- Crear un nodo nuevo, con next = 0 y num = a1
	li a0, 0
	jal create
	
	#-- Recuperar el puntero del nodo. Lo metemos en t0
	lw t0, 8(sp)
	
	#-- Hacemos que su campo next apunter al nuevo nodo creado
	sw a0, NEXT(t0)
	
fin:	
	#-- Recuperar direccion de retorno 
	lw ra, 12(sp)
	addi sp, sp, 16

	ret

El programa principal es el mismo que el del ejercicio 8

Ejercicio 9

Implementación de la función create_str():

#-- Crear un nodo inicializado con una cadena 
#-- pedida al usuario. Se inicializa el campo NEXT 
#-- con el valor pasado
#--
#--  ENTRADAS:
#--     a0: Puntero a almacenar al campo next
#--
#--  SALIDAS:
#--     a0: Puntero al nuevo nodo creado
#--------------------------------------------------------

	.include "servicios.asm"
	
	.globl create_str
	
	#-- Informacion del nodo
	.eqv NEXT 0
	.eqv STR  4
	
	 #-- Tamaño del nodo: 20 bytes para la cadena y 4 para el puntero
	.eqv TAM  24 
	.eqv MAX_STR 20  #-- Tamaño de la cadena
	
	.text
	
	
create_str:	
	
	#-- a0 Contiene se debe guardar en NEXT
	#-- Lo movemos a a1 para no perderlo
	mv a1, a0
	
	#-- Crear un nodo nuevo
	li a0, TAM
	li a7, SBRK
	ecall 
	
	#-- a0 contiene el puntero al nodo
	#-- Lo movemos a t0 para no perderlo
	mv t0, a0
	
	#-- Inicializar los campos
	sw a1, NEXT(t0)
	sw zero, STR(t0)
	
        #-- a0 apunta al campo str
	addi a0,t0,STR
	
	#-- Pedir cadena al usuario y guardarla en 
	#-- el campo STR
	li a1, MAX_STR
	li a7, READ_STRING
	ecall
	
	#-- Devolver el puntero al nodo creadd
	mv a0, t0
	
	ret
  • Implementación de la función print():
#---------------------------------------
#-- Subrutina para imprimir todas las cadenas
#-- contenidas en los nodos de la lista
#--
#--  ENTRADAS:  
#--    a0: Puntero a la lista
#--
#--  SALIDAS:
#--    Ninguna
#-----------------------------------------------

	.include "servicios.asm"
	
	.globl print
	
	#-- Informacion del nodo
	.eqv NEXT 0
	.eqv STR  4
	
	.text
	
print:

	#-- Usamos t0 para recorrer la lista
	mv t0, a0

next:
	#-- Si el puntero es NULL, terminamos
	beq t0, zero, fin

	
	#-- a0 apunta al campo 	
	addi a0, t0, STR
	
	#-- Imprimir la cadena del campo STR
	li a7, PRINT_STRING
	ecall 
	
	#-- Apuntar al siguiente nodo
	lw t0, NEXT(t0)
	
	#-- Repetir
	b next
	
fin:
	ret
  • Programa principal:
#-- Solución al ejercicio 9
#-- Programa principal

	.include "servicios.asm"
	
	
	#-- Informacion del nodo
	.eqv NEXT 0
	.eqv STR  4
	
	 #-- Tamaño del nodo: 20 bytes para la cadena y 4 para el puntero
	.eqv TAM  24 
	.eqv MAX_STR 20  #-- Tamaño de la cadena
	
	.data
msg:	.string "\nIntroduce dos cadenas:\n"
msg2:   .string "\nContenido de la LISTA:\n"
	
	.text
	
	#-- Pedir dos cadenas al usuario
	#-- Imprimir mensaje 1
	la a0, msg
	li a7, PRINT_STRING
	ecall
	
	#-- Crear el primer nodo
	li a0, 0
	jal create_str
	
	
	#-- a0 contiene el puntero al nodo, inicializado
	#-- con NEXT = 0
	#-- STR = Cadena introducida por el usuario
	
	#-- Crear el segundo nodo
	jal create_str
	
	mv t0, a0
	
	#-- Imprimir mensaje 2
	la a0, msg2
	li a7, PRINT_STRING
	ecall
	
	
	mv a0, t0
	
	#-- Imprimir la lista
	jal print
	
	
	li a7, EXIT
	ecall 

Ejercicio 10

El programa principal es:

#-- Solución al ejercicio 10
#-- Programa principal

	.include "servicios.asm"
	
	
	#-- Informacion del nodo
	.eqv NEXT 0
	.eqv STR  4
	
	.data
msg:	.string "\nIntroduce nombres de usuarios:\n"
msg2:   .string "\nLa Lista contiene los siguientes nombres:\n"
	
	.text
	
	#-- Pedir dos cadenas al usuario
	#-- Imprimir mensaje 1
	la a0, msg
	li a7, PRINT_STRING
	ecall
	
	#--- Usamos s0 como puntero a la lista
	#-- Inicialmente s0 es NULL
	li s0, 0
	
	
bucle:
	#-- Crear nodo enlazado como primer elemento de la lista
	mv a0, s0
	jal create_str
	
	#-- a0 contiene el puntero al nodo
	#-- Lo guardamos en s0
	mv s0, a0
	
	
	#-- Leemos el primer byte del campo STR
	lw t0, STR(a0)
	
	#-- Si es '\n', es la cadena nula --> Terminar
	li t1, '\n'
	beq t0, t1, imprimir
	
	#-- Crear siguiente nodo de la lista
	b bucle
	
	
	#-- Henmos terminado de introducir las cadenas
	#--- Ahora imprimimos la lista
	
imprimir:	
	
	#-- Imprimir mensaje 2
	la a0, msg2
	li a7, PRINT_STRING
	ecall
	
	#-- El puntero a la lista lo tenemos en s0
	mv a0, s0
	
	#-- Imprimir la lista
	jal print
	
	
	li a7, EXIT
	ecall 

Autores

Licencia

Enlaces