Examen: 2019_12_11:GISAM - myTeachingURJC/2019-20-LAB-AO GitHub Wiki

Examen convocatoria ordinaria: 2019-12-11. GISAM

  • Tiempo: 2h
  • Objetivo:
    • Resolver el problema de examen de la convocatoria ordinadira de GISAM, con fecha 2019/Dic/11

Contenido

Enunciado

  • Aquí está disponible el Enunciado en PDF
  • Animación con un ejemplo del funcionamiento del programa:

Solución comentada

TODO

Solución

Los cuatro ficheros pedidos son los siguientes:

  • Fichero len.s
#------------------------------------------------------------------
#- SUBRUTINA: len(cad)
#-- Calcular la longitud de una cadena
#-- Como final de cadena se usa \0 y \n
#-- ENTRADAS:
#--    a0: Puntero a la cadena
#-- SALIDAS:
#--    a0: Longitud de la cadena
#------------------------------------------------------------------

	.globl len
	
	.text
	
len:

	#-- Es una subrutina hoja: no hace falta guardar la direccion de retorno
	#-- en la pila (ya está en ra)
	
	#-- Usamos t0 como contador de caracteres
	li t0, 0
	
bucle:
	#-- Leer el caracter
	lb t1, 0(a0)
	
	#-- Si es 0 terminar
	beq t1, zero, fin
	
	#-- Si es '\n', terminar
	li t2, '\n'
	beq t1, t2, fin
	
	#-- Es un caracter diferente de 0 y '\n'
	#-- Incrementar el contador de caracteres
	addi t0, t0, 1
	
	#-- Apuntar al siguiente caracter
	addi a0, a0, 1
	
	#-- Repetir
	b bucle

fin:
	#-- Devolver la longitud de la cadena por a0
	mv a0, t0

	ret
  • Fichero reverse.s
#-------------------------------------------------------
#--  SUBRUTINA: Reverse(cad)
#--  
#--  ENTRADA:
#--   a0: Puntero a la cadena a imprimir al reves
#--
#--  SALIDAS:
#--   Ninguna
#-------------------------------------------------------

	.eqv PRINT_CHAR 11

	.globl reverse

	.text
	
reverse:  

	#-- Ultimo nivel: Si la cadena es "'\n'" o "" 
	lb t0, 0(a0)      ### DEBUG: REVERSE
	beq t0, zero, terminar
	
	li t1, '\n'
	beq t0, t1, terminar
	
	#------- Algoritmo recursivo
	
	#-- Es necesario crear la pila
	addi sp, sp, -16
	
	#-- Guardar la direccion de retonro
	sw ra, 12(sp)


	#-- Guardar el puntero a la cadena actual, para no
	#-- perderlo al llamar a reverse
	sw a0, 8(sp)

	#-- Obtener la subcadena
	addi a0, a0, 1
	
	#-- Imprimir la subcadena al reves
	jal reverse
	

	#-- Recuperar puntero de la pila
	lw a0, 8(sp)
		
	#-- Imprimir el primer caracter
	lb a0, 0(a0)
	li a7, PRINT_CHAR
	ecall

	#-- Recuperar la direccion de retorno
	lw ra, 12(sp)
	
	#-- Liberar la pila
	addi sp, sp, 16

	b fin

	#-- Ultimo nivel
terminar:
        #-- Aqui llega en el ultimo nivel
        #-- ESta es una instruccion nula, que se usa para poner un breakpoint
        #-- y saber el valor del sp en este último nivel
        addi zero, zero, 0  #--- ULTIMO NIVEL
        #-- El valor del sp es: 0x7fffefac
fin:
	#-- Imprimir la cadena 

	ret
  • Fichero procesar.s
#-------------------------------------------------------------------------
#-- SUBRUTINA: Procesar(cad)
#--
#-- Imprimir a longitud de la cadena y la cadena al revés
#-- Para obtener la longitud se invoca a la funcion len()
#-- Para imprimir del revés se llama a la función reverse()
#--
#--  ENTRADAS:
#--    a0: Puntero a la cadena a procesar
#--
#--  SALIDAS:
#--    Ninguna
#------------------------------------------------------------------------

	.globl procesar

	.eqv PRINT_STRING  4
	.eqv PRINT_INT     1

	.data
msg1:   .string "\nLongitud cadena: "
msg2:   .string "\nCadena invertida: "
	.text
	
procesar:

	#-- Es una funcion intermedia
	#-- Hay que crear la pila para guardar la direccion de retorno
	addi sp, sp, -16

	#-- Guardar la direccion de retorno
	sw ra, 12(sp)
	
	#-- Almacenar la direccion de la cadena para no perderla
	sw a0, 8(sp)
    	
    	#---- Imprimir mensaje 1
    	la a0, msg1
    	li a7, PRINT_STRING
    	ecall
    	
    	#------ Calcular la longitud de la cadena, llamandando a la funcion len()
    	lw a0, 8(sp)
    	jal len
    	
    	#-- Imprimir la longitud
    	li a7, PRINT_INT
    	ecall
    	
    	#--- Imprimir mensaje 2
    	la a0, msg2
    	li a7, PRINT_STRING
    	ecall
    	
    	#-- Recuperar el puntero de la cadena
    	lw a0, 8(sp)
    	
    	#-- Imprimir la cadena invertida
    	jal reverse

	#-- Recuperar la direccion de retorno
	lw ra, 12(sp)
	
	#-- Liberar la pila
	addi sp, sp, 16

	ret
  • Fichero: main.s
#----- PROGRAMA PRINCIPAL

         #-- Servicios del sistema operativo
         .eqv EXIT          10
         .eqv PRINT_STRING  4
         .eqv READ_STRING   8
         .eqv MAX 100
    
         .data
msg1:    .string "\n\nIntroduce cadena: "        
cad:     .space MAX
        
    .text

    #-- Repetir el bucle hasta que se introduzca la cadena nula "\n"
    #-- (Pulsar enter sin introducir nada)
    
bucle:        
    #-- Imprimir mensaje 1
    la a0, msg1
    li a7, PRINT_STRING
    ecall 
    
    #-- Pedir cadena al usuario
    la a0, cad
    li a1, MAX
    li a7, READ_STRING
    ecall
    
    #-- Si el primer caracter es '\n' terminar
    lb t0, 0(a0)
    li t1, '\n'
    beq t0, t1, fin 
    
    #-- Llamar a la funcion de procesar
    la a0, cad
    jal procesar
            
    #-- Repetir
    b bucle
    
fin:    
    
    #--- Terminar
    li a7, EXIT
    ecall

Autores

Licencia

Enlaces