Skip to content

Practica 2: Soluciones a los ejercicios

Juan Gonzalez-Gomez edited this page Oct 21, 2019 · 101 revisions

Práctica 2: Soluciones a los ejercicios

Soluciones comentadas a los ejercicios propuestos en las sesiones de la práctica 2. Antes de ver las soluciones es importante que hayas intentado hacer los ejercicios por tu cuenta

Contenido

Práctica 2

Sesión 4

Solución a los ejercicios de la Sesión de laboratorio L4:2-1

Ejercicio 1

Tenemos que implementar un programa en el que haya un contador en la variable contador, inicializada con la constante INICIO, y que se incremente según la constante INC

#-- Ejercicio 1
#-- Contador con valor incial e incremento

	#-- DEFINICION de constantes
	.eqv INICIO 100   #-- Valor de inicio del contador
	.eqv INC 10       #-- Incremento del contador
	
	#-- Variables
	.data
	
contador:  .word 0

	#-- Código
	.text
	
	#-- Usamos el registro x5 como contador
	#-- x5 = INICIO (Inicializacion)
	li x5, INICIO
	
	#-- PUntero a la variale contador: x6
	la x6, contador

bucle:	
	#-- Actualizar la variable contador
	#-- Almacenar el valor de x5 en contador
	sw x5, 0(x6)
	
	#-- Incrementar el contador
	addi x5, x5, INC
	
	#-- Bucle infinito
	b bucle

Ejercicio 2

Al ejecutar el programa, observamos que los 4 elementos de la tabla, que tienen los valores 0xBEBECAFE, 0xFACEB00C, 0x00FABADA, 0xCACABACA se han cargado en los registros x10, x11, x12 y x13 respectivamente

Este programa nos enseña cómo definir una tabla y cómo acceder de manera sencilla a sus elementos, usando identificadores. Si en vez de el identificador utilizásemos directamente los números de desplazamiento, el programa sería mucho más difícil de entender. Somo humanos. Necesitamos que los programas tengan información para humanos

Así, con la instrucción:

lw x10, E1(x5)

hemos cargado el elemento 1 de la tabla en el registro x10, y con

lw x13, E4(x5)

cargamos el elemento 4 en el registro x13

Ejercicio 3

En este programa tenemos que incrementar en una unidad TODOS los elementos de la tabla. Como todavía no sabemos hacer bucles, lo haremos manualmente. Primero leemos los valores de la tabla y los cargamos en los registros del x10 al x13. Al estar en los registros, ya podemos realizar las operaciones, que en este ejemplo es incrementar cada registro en 1 unidad. Por último, hay que almacenar los registros incrementados en sus posiciones de la tabla, usando instrucciones sw

##-- Solución al Ejercicio 3
##-- Incrementar cada uno de los elmementos de la tabla en INC unnidades

	#-- Definiciones. Estos indetificadores nos permiten acceder
	#-- directamente a los elementos de la tabla: E1, E2, E3 y E4
	.eqv E1 0
	.eqv E2 4
	.eqv E3 8
	.eqv E4 0xC
	
	#-- Incremento: Valor a incrementar TODOS los elementos de la tabla
	.eqv INC 1
	
	#----------------------- Variables
	.data
	
	#-- Tabla de 4 elementos, inicializados a ciertos valores
tabla:	.word 0xBEBECAFE, 0xFACEB00C, 0x00FABADA, 0xCACABACA
	
	
	#------------------------ Código
	.text
	
	#-- x5 es un puntero a la tabla (x5 contiene la direccion del primer elemento de la tabla)
	la x5, tabla
	
	#-- Leer todos los elementos de la tabla, y situarlos en los registros x10, x11, x12 y x13
	lw x10, E1(x5)
	lw x11, E2(x5)
	lw x12, E3(x5)
	lw x13, E4(x5)
	
	#-- Incrementar los registros en INC unidades
	addi x10, x10, INC
	addi x11, x11, INC
	addi x12, x12, INC
	addi x13, x13, INC
	
	#-- Actualizar la tabla con los nuevos valores
	sw x10, E1(x5)
	sw x11, E2(x5)
	sw x12, E3(x5)
	sw x13, E4(x5)
	
	#-- Terminar
	li a7, 10
	ecall

Al ensamblar y ejecutar el programa, comprobamos que los 4 elementos de memoria están incrementados en 1 unidad:

  • 0xBEBECAFE --> 0xBEBECAFF
  • 0xFACEB00C --> 0xFACEB00D
  • 0x00FABADA --> 0x00FABADB
  • 0xCACABACA --> 0xCACABACB

Esta es la forma típica de trabajar con elementos de memoria: primero se cargan a registros, ahí se hacen las operaciones, y luego se almacenan de nuevo en memoria (Arquitectura load-store)

Ejercicio 4

En el programa contador del ejericio 1, se utilizaba la variable contador, almacenada en el segmento de datos. Ahora, en vez de almacenarlo en esa variable, hay que escribirlo en la dirección 0xFFFF0000, donde está el puerto de salida. En el simulador RARS NO hay ningún periférico en esa dirección, por lo que en nuestro programa simplemente veremos que la posición de la dirección 0xFFFF0000 se incrementa en cada pasada del bucle

##-- Solución al Ejercicio 4
##-- Contador que se envía por los LEDs

	#-- DEFINICION de constantes
	.eqv INICIO 100       #-- Valor de inicio del contador
	.eqv INC 10           #-- Incremento del contador
	.eqv LEDS 0xFFFF0000  #-- Direccion del puerto de salida
	
	#------------------------ Código
	.text
	
	#-- X5: contador. Inicializar a INICIO
	li x5, INICIO
	
	#-- x6: Puntero para acceso al puerto de salida
	li x6, LEDS
	
bucle:

	#-- Sacar el contador actual por los LEDs
	SW x5, 0(x6)
	
	#-- Incrementar contador
	addi x5, x5, INC
	
	#-- Repetir bucle
	b bucle

Al simularlo paso a paso vemos cómo la ventana inferior cambia y nos muestra la zona de E/S (MMIO). Ahí está nuestro contador, incrementándose de 10 en 10

Ejercicio 5

El display derecho en el simulador RARs está en la dirección 0xFFFF0010, por lo que el programa es el mismo del ejercicio 4 pero cambiando la constante con la dirección del periférico

##-- Solución al Ejercicio 5
##-- Contador que se envía por el puerto del display

	#-- DEFINICION de constantes
	.eqv INICIO 0         #-- Valor de inicio del contador
	.eqv INC 1            #-- Incremento del contador
	.eqv DISPLAY 0xFFFF0010  #-- Direccion del puerto del display
	
	#------------------------ Código
	.text
	
	#-- X5: contador. Inicializar a INICIO
	li x5, INICIO
	
	#-- x6: Puntero para acceso al Display
	li x6, DISPLAY
	
bucle:

	#-- Sacar el contador actual por el display
	SW x5, 0(x6)
	
	#-- Incrementar contador
	addi x5, x5, INC
	
	#-- Repetir bucle
	b bucle

Lo ensamblamos y lo ejecutamos paso a paso. Observamos cómo se van encendido los segmentos del display

Para ciertos valores del contador, obtenemos dígitos y letras reconocibles:

Contador Elemento en display
6 Dígito 1
7 Dígito 7
30 Letra J
63 Dígito 0
79 Dígito 3
91 Dígito 2
95 Letra a
103 Dígito 9
102 Dígito 4
109 Dígito 5
110 Letra Y
113 Letra F
115 Letra P
116 Letra h
118 Letra H
119 Letra A
121 Letra E
124 Letra b
125 Dígito 6
126 Dígito 8

(En el ejercicio no se trata de obtener todos, sino de reconocer unos cuantos y entender el funcionamiento)

Ejercicio 6

En este ejercicio nos están pidiendo que calculemos los valores para sacar un 3, y luego para 1,2 y 4. Estos valores bien los podemos obtener ejecutando el ejercicio anterior hasta que aparezcan en el display, o bien los podemos calcular directamente dibujando los numeros y obteniendos los bits a 1 de los segmentos que hay que encender para que aparezca cada numo.

Así, para que aparezca el dígito 3 hay que encender los segmentos a,b,c,d y g, que se corresponden con los bits 0,1,2,3 y 6. El numero binario es: 01001111, Lo pasamos a hexadecimal: 0x4F. En decimal es 79

#-- Solucion al ejercicio 6
#-- Programa para mostrar por el display
#-- el digito 3

	#-- CONSTANTES
	.eqv DISPLAY 0xFFFF0010  #-- Direccion del puerto de salida del display
	
	#-- Valore para que se muestren en el display los diferentes digitos
	.eqv DIG3 0x4F  #-- Digito 3
	
	.text
	
	#-- x5 es el puntero al display
	li x5, DISPLAY
	
	#-- Valor a sacar por el display
	li x6, DIG3
	
	#-- Sacarlo por el display
	sw x6, 0(x5)
	
	#-- Terminar
	li a7, 10
	ecall

Al ejecutarlo, vemos el dígito 3 en el display:

Calculamos el valor para el resto de dígitos que nos piden, y los almacenamos como constantes. Cambiando la constante que cargamos en el registro x6 comprobamos el número que sale en el display. Este programa de prueba está pensado para probar sólo un valor cada vez que se ejecuta

#-- Solucion al ejercicio 6
#-- Programa para mostrar por el display
#-- el digito 3

	#-- CONSTANTES
	.eqv DISPLAY 0xFFFF0010  #-- Direccion del puerto de salida del display
	
	#-- Valore para que se muestren en el display los diferentes digitos
	.eqv DIG1 0x06  #-- Digito 1
	.eqv DIG2 0x5B  #-- Digito 2
	.eqv DIG3 0x4F  #-- Digito 3
	.eqv DIG4 0x66  #-- Digito 4
	
	.text
	
	#-- x5 es el puntero al display
	li x5, DISPLAY
	
	#-- Valor a sacar por el display
	li x6, DIG3
	
	#-- Sacarlo por el display
	sw x6, 0(x5)
	
	#-- Terminar
	li a7, 10
	ecall

Ejercicio 7

Hay que escribir un programa para que salga por el display los digitos 1,2,3 y 4 consecutivamente, cuando se ejecuta paso a paso (¡Ojo! Si lo ejecutamos del tirón, si hacerlo paso a paso, no veremos cómo aparecen los dígitos)

Los valores para sacar los dígitos 1,2,3 y 4 los denotamos mediante las consatantes DIG1-DIG4 respectivamente. Creamos una tabla con 4 posiciones en el segmento de datos. Para acceder a estos elementos usaremos los offset 0, 4, 8 y 12, pero usando los identificadores E1-E4

##-- Solución al Ejercicio 7
##-- Leer los valores de una tabla y mostrar en el display
##-- Los valores de la tabla haran que en el display aparezcan
##-- los digitos 1,2,3 y 4

	#-- Definiciones. Estos indetificadores nos permiten acceder
	#-- directamente a los elementos de la tabla: E1, E2, E3 y E4
	.eqv E1 0
	.eqv E2 4
	.eqv E3 8
	.eqv E4 0xC

	#-- Estos son las constantes para representar los digitos en el 7 segmentos
	#-- Valore para que se muestren en el display los diferentes digitos
	.eqv DIG1 0x06  #-- Digito 1
	.eqv DIG2 0x5B  #-- Digito 2
	.eqv DIG3 0x4F  #-- Digito 3
	.eqv DIG4 0x66  #-- Digito 4

	#-- Direccion del display
	.eqv DISPLAY 0xFFFF0010

	#----------------------- Variables
	.data

	#-- Tabla de 4 elementos, inicializados a ciertos valores
tabla:
      .word DIG1 
      .word DIG2
      .word DIG3
      .word DIG4


	#------------------------ Código
	.text

	#-- x5 es un puntero a la tabla (x5 contiene la direccion del primer elemento de la tabla)
	la x5, tabla

	#-- x6 es el puntero al display
	li x6, DISPLAY

	#-- Leer el primer elmento y sacarlo por el display
	lw x10, E1(x5)
	sw x10, 0(x6)

	#-- Leer el segundo elemento y sacarlo por el display
	lw x10, E2(x5)
	sw x10, 0(x6)

	#-- Leer el tercer elemento y sacarlo por el display
	lw x10, E3(x5)
	sw x10, 0(x6)

	#-- Leer el cuarto elemento y sacarlo por el display
	lw x10, E4(x5)
	sw x10, 0(x6)

	#-- Terminar
	li a7, 10
	ecall

Lo ensamblamos y lo ejecutamos paso a paso. Vemos cómo aparece la cuenta del 1 al 4 en el display

Ejercicio 8

Este es el programa ampliado, para contar del 0 al 9

##-- Solución al Ejercicio 8
##-- Hacer que salga un contador del 0 al 9 por el display
##-- Usar una tabla

	#-- Definiciones. Estos indetificadores nos permiten acceder
	#-- directamente a los elementos de la tabla: E1, E2, E3, E4.....
	.eqv E1 0
	.eqv E2 4
	.eqv E3 8
	.eqv E4 0xC
	.eqv E5 0x10
	.eqv E6 0x14
	.eqv E7 0x18
	.eqv E8 0x1C
	.eqv E9 0x20
	.eqv E10 0x24
	
	
	#-- Estos son las constantes para representar los digitos en el 7 segmentos
	#-- Valore para que se muestren en el display los diferentes digitos
	.eqv DIG0 0x3F  #-- Digito 0
	.eqv DIG1 0x06  #-- Digito 1
	.eqv DIG2 0x5B  #-- Digito 2
	.eqv DIG3 0x4F  #-- Digito 3
	.eqv DIG4 0x66  #-- Digito 4
	.eqv DIG5 0x6D  #-- Digito 5
	.eqv DIG6 0x7D  #-- Digito 6
	.eqv DIG7 0x07  #-- Digito 7
	.eqv DIG8 0x7F  #-- Digito 8
	.eqv DIG9 0x6F  #-- Digito 9
	
	#-- Direccion del display
	.eqv DISPLAY 0xFFFF0010
	
	#----------------------- Variables
	.data
	
	#-- Tabla de 4 elementos, inicializados a ciertos valores
tabla:  .word DIG0  #-- E1
	.word DIG1  #-- E2
	.word DIG2  #-- E3
	.word DIG3  #-- E4
	.word DIG4  #-- E5
	.word DIG5  #-- E6
	.word DIG6  #-- E7
	.word DIG7  #-- E8 
	.word DIG8  #-- E9
	.word DIG9  #-- E10
	
	
	#------------------------ Código
	.text
	
	#-- x5 es un puntero a la tabla (x5 contiene la direccion del primer elemento de la tabla)
	la x5, tabla
	
	#-- x6 es el puntero al display
	li x6, DISPLAY
	
	#-- Leer el primer elmento y sacarlo por el display
	lw x10, E1(x5)
	sw x10, 0(x6)
	
	#-- Leer el segundo elemento y sacarlo por el display
	lw x10, E2(x5)
	sw x10, 0(x6)
	
	#-- Leer el tercer elemento y sacarlo por el display
	lw x10, E3(x5)
	sw x10, 0(x6)
	
	#-- Leer el cuarto elemento y sacarlo por el display
	lw x10, E4(x5)
	sw x10, 0(x6)
	
	lw x10, E5(x5)
	sw x10, 0(x6)
	
	lw x10, E6(x5)
	sw x10, 0(x6)
	
	lw x10, E7(x5)
	sw x10, 0(x6)
	
	lw x10, E8(x5)
	sw x10, 0(x6)
	
	lw x10, E9(x5)
	sw x10, 0(x6)
	
	lw x10, E10(x5)
	sw x10, 0(x6)
	
	#-- Terminar
	li a7, 10
	ecall

En esta animación lo vemos en funcionamiento

Ejercicio 9

Es ejericicio es casi igual que el 8, pero con los elementos de la tabla en otro orden y con un bucle infinito para que la cuenta se repite indefinidamente

##-- Solución al Ejercicio 9
##-- Cuenta atrás en el display de 7 segmentos
##-- Al llegar a 0 vuelve a comenzar desde 9

	#-- Definiciones. Estos indetificadores nos permiten acceder
	#-- directamente a los elementos de la tabla: E1, E2, E3, E4.....
	.eqv E1 0
	.eqv E2 4
	.eqv E3 8
	.eqv E4 0xC
	.eqv E5 0x10
	.eqv E6 0x14
	.eqv E7 0x18
	.eqv E8 0x1C
	.eqv E9 0x20
	.eqv E10 0x24
	
	
	#-- Estos son las constantes para representar los digitos en el 7 segmentos
	#-- Valore para que se muestren en el display los diferentes digitos
	.eqv DIG0 0x3F  #-- Digito 0
	.eqv DIG1 0x06  #-- Digito 1
	.eqv DIG2 0x5B  #-- Digito 2
	.eqv DIG3 0x4F  #-- Digito 3
	.eqv DIG4 0x66  #-- Digito 4
	.eqv DIG5 0x6D  #-- Digito 5
	.eqv DIG6 0x7D  #-- Digito 6
	.eqv DIG7 0x07  #-- Digito 7
	.eqv DIG8 0x7F  #-- Digito 8
	.eqv DIG9 0x6F  #-- Digito 9
	
	#-- Direccion del display
	.eqv DISPLAY 0xFFFF0010
	
	#----------------------- Variables
	.data
	
	#-- Tabla de 4 elementos, inicializados a ciertos valores
tabla:  .word DIG9  #-- E1
	.word DIG8  #-- E2
	.word DIG7  #-- E3
	.word DIG6  #-- E4
	.word DIG5  #-- E5
	.word DIG4  #-- E6
	.word DIG3  #-- E7
	.word DIG2  #-- E8 
	.word DIG1  #-- E9
	.word DIG0  #-- E10
	
	
	#------------------------ Código
	.text
	
	#-- x5 es un puntero a la tabla (x5 contiene la direccion del primer elemento de la tabla)
	la x5, tabla
	
	#-- x6 es el puntero al display
	li x6, DISPLAY
	
	
repetir:
	#-- Leer el primer elmento y sacarlo por el display
	lw x10, E1(x5)
	sw x10, 0(x6)
	
	#-- Leer el segundo elemento y sacarlo por el display
	lw x10, E2(x5)
	sw x10, 0(x6)
	
	#-- Leer el tercer elemento y sacarlo por el display
	lw x10, E3(x5)
	sw x10, 0(x6)
	
	#-- Leer el cuarto elemento y sacarlo por el display
	lw x10, E4(x5)
	sw x10, 0(x6)
	
	lw x10, E5(x5)
	sw x10, 0(x6)
	
	lw x10, E6(x5)
	sw x10, 0(x6)
	
	lw x10, E7(x5)
	sw x10, 0(x6)
	
	lw x10, E8(x5)
	sw x10, 0(x6)
	
	lw x10, E9(x5)
	sw x10, 0(x6)
	
	lw x10, E10(x5)
	sw x10, 0(x6)
	
	b repetir

Lo simulamos a baja velocidad (3 instrucciones por segundo) y vemos la cuenta atrás...

Ejercicio 10

Para conseguir la animación pedida, sólo hay encender un segmento cada vez. Y en el perímetro sólo hay 6 segmentos: a,b,c,d,e y f. Los valores a enviar para que se enciendan serán los de desplazar un bit a la izquierda: 0x01, 0x02, 0x04, 0x08, 0x10 y 0x20

##-- Solución al Ejercicio 10
##-- Animacion en el display

	#-- Definiciones. Estos indetificadores nos permiten acceder
	#-- directamente a los elementos de la tabla: E1, E2, E3, E4.....
	.eqv E1 0
	.eqv E2 4
	.eqv E3 8
	.eqv E4 0xC
	.eqv E5 0x10
	.eqv E6 0x14
	.eqv E7 0x18
	.eqv E8 0x1C
	.eqv E9 0x20
	.eqv E10 0x24
	
	#-- Direccion del display
	.eqv DISPLAY 0xFFFF0010
	
	#----------------------- Variables
	.data
	
	#-- Tabla de 4 elementos, inicializados a ciertos valores
tabla:  .word 0x01  #-- E1
	.word 0x02  #-- E2
	.word 0x04  #-- E3
	.word 0x08  #-- E4
	.word 0x10  #-- E5
	.word 0x20  #-- E6
	
	
	#------------------------ Código
	.text
	
	#-- x5 es un puntero a la tabla (x5 contiene la direccion del primer elemento de la tabla)
	la x5, tabla
	
	#-- x6 es el puntero al display
	li x6, DISPLAY
	
	
repetir:
	#-- Leer el primer elmento y sacarlo por el display
	lw x10, E1(x5)
	sw x10, 0(x6)
	
	#-- Leer el segundo elemento y sacarlo por el display
	lw x10, E2(x5)
	sw x10, 0(x6)
	
	#-- Leer el tercer elemento y sacarlo por el display
	lw x10, E3(x5)
	sw x10, 0(x6)
	
	#-- Leer el cuarto elemento y sacarlo por el display
	lw x10, E4(x5)
	sw x10, 0(x6)
	
	lw x10, E5(x5)
	sw x10, 0(x6)
	
	lw x10, E6(x5)
	sw x10, 0(x6)
	
	b repetir

Este es el aspecto que tiene la animación al ejecutar el programa a baja velocidad:

Sesión 5

Solución a los ejercicios de la Sesión de laboratorio L5:2-2

Ejercicio 1

Nos piden escribir un programa para calcular la expresión: f = (2*a - b) + c - 1. En ella hay 4 variables matemáticas: a, b,c y f. Para su implementación, como no nos lo piden explícitamente, usamos **registros **para los cálculos. ¿Qué registros? A partir de ahora siempre usaremos registros definidos en la ABI. Para hacer cáclulos temporales usaremos los registros del t0 al t6

#-- Ejercicio 1. Programa para calcular
#-- la expresion f = (2*a - b) + c - 1
#-- Para su evaluacion usar los valores:
#-- a=10, b=20, c=30
#-- Resultado: t5 = 29

	.eqv EXIT 10

	.text
	
	#- Asignacion de registros:
	#- t0 = a, t1 = b, t2 = c, t5 = f
	
	#-- Inicializacion
	li t0, 10  #-- a = 10
	li t1, 20  #-- b = 20
	li t2, 30  #-- c = 30
	
	#----- Calculo de la expresion
	
	#-- t0 = 2*a
	add t0, t0, t0
	
	#-- t3 = (2*a - b)
	sub t3, t0, t1
	
	#-- t4 = c - 1
	addi t4, t2, -1
	
	#-- t5 = (2*a - b) + c - 1
	add t5, t3, t4
	
	#-- Terminar
	li a7, EXIT
	ecall

Recuerda que se puede hacer de muchas formas, tantas como programadores haya 😉 Puedes utilizar los registros t0-t6 que quieras. Si para los cálculos itermedios no estás realizando llamadas al sistema, tambień podrías usar los registros a0-a7

Comprobamos que el cálculo es correcto. En el registro t5 se almacena el resultado final, que es 29, para los valores iniciales: a=10, b=20 y c=30

Desde el terminal de python comprobamos rápidamente que esto es así, con estos comandos:

a,b,c = 10,20,30
f = (2*a - b) + c - 1
f

Ejercicio 2

Para calcular la suma de dos números tenemos que almacenarlos en dos registros de RISC-V y realizar la operación de suma. Podemos usar, por ejemplo, los registros t0 y t1. Como no nos dicen nada de variables, directamente usamos los registros

Para pedir al usuario los números invocamos al servicio READ_INT dos veces. Al pedir el primer número, el sistema operativa nos lo devuelve en el registro a0. Para no perder este valor, porque en la siguiete llamada al sistema se escribirá el segundo, lo guardamos en t0, usando la mv

#-- Suma de dos numeros introducidor por el teclado

	#-- Códigos de servicio
	.eqv EXIT      10
	.eqv READ_INT  5
	.eqv PRINT_INT 1
	
	.text
	
	#-- Pedir el primer numero al usuario
	li a7, READ_INT
	ecall
	
	#-- El valor introducido se devuelve en a0
	
	#-- t0 = primer numero
	mv t0, a0
	
	#-- Pedir el segundo numero
	li a7, READ_INT
	ecall
	
	#-- t1 = segundo numero
	mv t1, a0
	
	#-- Realizar la suma
	#-- a0 = t0 + t1
	add a0, t0, t1
	
	#-- Imprimir el numero en la consola
	li a7, PRINT_INT
	ecall
	
	#-- Terminar
	li a7, EXIT
	ecall

Activamos la opción Setting/pop up dialog... para que sea más fácil. Lo ejecutamos y lo probamos con los valores 10 y 20. En la consola veremos esto:

**** user input : 10
**** user input : 20
30

En esta animación se muestra el programa en funcionamiento

  1. Desde la consola ejecutamos el programa de esta forma:
java -jar rars1_3_1.jar Ejercicio-02.s
RARS 1.3  Copyright 2003-2019 Pete Sanderson and Kenneth Vollmar

10
20
30
Program terminated by calling exit

Ejercicio 3

Aunque para sumar dos números introducidos por el usuario no hace falta usar variables, en este ejercicio nos lo están pidiendo explicitamente. Nos dicen en qué orden se debe hacer. Lo que no nos digan explícitamente lo podemos implementar como queramos, y en el orden que queramos

#-- Suma de dos numeros introducidor por el teclado
#-- Los valores leidos se deben almacenar en las
#-- variables a y b. El resultado en f
#-- El resultado se saca por la consola

	#-- Códigos de servicio
	.eqv EXIT      10
	.eqv READ_INT  5
	.eqv PRINT_INT 1
	
	#-- Cosntantes de acceso a  las variables
	.eqv VA 0
	.eqv VB 4
	.eqv VF 8
	
	.data
	
	#-- Variables. Inicializadas a 0
variables: 
        .word 0   #-- Variable a
	.word 0   #-- Variable b
	.word 0   #-- Variable f = a + b
	
	.text
	
	#-- s0: Puntero a las variables
	la s0, variables
	
	#-- Pedir el primer numero al usuario
	li a7, READ_INT
	ecall
	
	#-- El valor introducido se devuelve en a0
	
	#-- Almacenarlo en a
	sw a0, VA(s0)
	
	#-- Pedir el segundo numero
	li a7, READ_INT
	ecall
	
	#-- Almacenarlo en b
	sw a0, VB(s0)
	
	#-- Realizar la suma. Nos indican explicitamente que leamos
	#-- las variables
	
	#-- t0 = a
	lw t0, VA(s0)
	
	#-- t1 = b
	lw t1, VB(s0)
	
	#-- Realizar la suma
	#-- a0 = t0 + t1
	add a0, t0, t1
	
	#-- Almacenar la suma en F
	sw a0, VF(s0)
	
	#-- Imprimir el numero en la consola
	li a7, PRINT_INT
	ecall
	
	#-- Terminar
	li a7, EXIT
	ecall

Al ejecutarlo, comprobamos que efectivametne las variables contienen lo que ha introducido el usuario, y el resultado de la suma:

En esta animación se muestra en funcionamento:

Ejercicio 4

En el ejercicio 1 se nos pidió que evaluásemos la expresión f = (2*a - b) + c - 1 para unos valores iniciales. Bien, ahora se nos pide que se calcule para tres valores introducidos por el usuario

#-- Suma de dos numeros introducidor por el teclado
#-- Los valores leidos se deben almacenar en las
#-- variables a y b. El resultado en f
#-- El resultado se saca por la consola

	#-- Códigos de servicio
	.eqv EXIT      10
	.eqv READ_INT  5
	.eqv PRINT_INT 1
		
	.text
	
	#-- Pedir el primer numero al usuario
	li a7, READ_INT
	ecall
	
	#-- El valor introducido esta en a0
	#-- t0 = a
	mv t0, a0
	
	#-- Pedir el segundo numero
	li a7, READ_INT
	ecall
	
	#-- t1 = b
	mv t1, a0
	
	#-- Pedir el tercer numero
	li a7, READ_INT
	ecall
	
	#-- t2 = c
	mv t2, a0
	
	#----- Calculo de la expresion
	
	#-- t0 = 2*a
	add t0, t0, t0
	
	#-- t3 = (2*a - b)
	sub t3, t0, t1
	
	#-- t4 = c - 1
	addi t4, t2, -1
	
	#-- t5 = (2*a - b) + c - 1
	add t5, t3, t4
	
	#-- Imprimir el resultado en la consola
	#-- El numero a imprimir debe estar en a0
	mv a0, t5
	
	li a7, PRINT_INT
	ecall
	
	#-- Terminar
	li a7, EXIT
	ecall

Si se prueba con los valores 10,20 y 30, obtenemos el valor 29, que se mostró que es correcto

En esta animación se muestra el programa completo en funcionamiento:

Ejercicio 5

En este programa hay que pedir un número entero al usuario, usando el servicio READ_INT y escribirlo en la dirección donde está mapeado el display de 7 segmentos derecho

#-- Ejercicio 5
#-- Pedir un numero entero al usuario
#-- y enviarlo tal cual al display de 7 segmentos derecho
#-- Test: el 255 (0xFF) debe encender todos los segmentos

	#-- Direccion del display derecho
	.eqv DISP_R 0xFFFF0010
	.eqv EXIT      10
	.eqv READ_INT  5 

	.text
	
	#-- Pedir Numero al usuario
	li a7, READ_INT
	ecall
	
	#-- El valor está en a0
	#-- t0 = puntero para acceder al display
	li t0, DISP_R
	
	#-- Sacar el numero por el display
	sw a0, 0(t0)
	
	#-- Terminar
	li a7, EXIT
	ecall

Hacemos una comprobación introduciendo el número 255, que hace que se enciendan todos los segmentos y el punto

En esta animación lo vemos en funcionamiento. Se ejecuta dos veces, una introduciendo 255 y la otra 79, que se corresponde con el dígito 3

Esta es una forma fácil de experimentar con el display de 7 segmentos, y comprobar si un valor calculado efectivamente activa los segmentos que se quiere

Ejercicio 6

Este tipo de programas, en los que hay que hacer varias acciones repetidas, los implementamos con bucles. Pero todavía NO lo sabemos hacer, así que lo hacemos sin bucles. El objetivo es practicar con las llamadas al sistema, y con el acceso a memoria

#-- Ejercicio 6: escribir en memoria las 4 palabras introducidas por
#-- el usuario. Luego leerlas e imprimirlas en la consola


	#-- Códigos de servicio
	.eqv EXIT      10
	.eqv READ_INT  5
	.eqv PRINT_INT 1
	.eqv PRINT_CHAR 11

	#-- Segmento de datos
	.data
datos:


	.text
	
	#-- t0 es un puntero al comienzo del segmento de datos
	la t0, datos
	
	#-- Pedir valor al usuario
	li a7, READ_INT
	ecall
	
	#-- Almacenar el numero en la direccion indicada por t0
	sw a0, 0(t0)
	
	#-- Incrementar t0 para apuntar a la siguiente palabra
	addi t0, t0, 4
	
	#-- Pedir valor al usuario
	li a7, READ_INT
	ecall
	
	#-- Almacenar el numero en la direccion indicada por t0
	sw a0, 0(t0)
	
	#-- Incrementar t0 para apuntar a la siguiente palabra
	addi t0, t0, 4
	
	#-- Pedir valor al usuario
	li a7, READ_INT
	ecall
	
	#-- Almacenar el numero en la direccion indicada por t0
	sw a0, 0(t0)
	
	#-- Incrementar t0 para apuntar a la siguiente palabra
	addi t0, t0, 4
	
	#-- Pedir valor al usuario
	li a7, READ_INT
	ecall
	
	#-- Almacenar el numero en la direccion indicada por t0
	sw a0, 0(t0)
	
	#-- Incrementar t0 para apuntar a la siguiente palabra
	addi t0, t0, 4
	
	#------------- Ya estan todos los valores en la memoria
	#-- Ahora los leemos y los imprimimos
	
	#-- t0 apunta al comienzo de los datos
	la t0, datos
	
	#-- Leer palabra
	lw a0, 0(t0)
	
	#-- Imprimir palabra en la consola
	li a7, PRINT_INT
	ecall
	
	#-- Imprimir una coma
	li a0, ','
	li a7, PRINT_CHAR
	ecall
	
	#-- Incrementar puntero t0
	addi t0, t0, 4
	
	#-- Leer palabra
	lw a0, 0(t0)
	
	#-- Imprimir palabra en la consola
	li a7, PRINT_INT
	ecall
	
	#-- Imprimir una coma
	li a0, ','
	li a7, PRINT_CHAR
	ecall
	
	#-- Incrementar puntero t0
	addi t0, t0, 4
	
	#-- Leer palabra
	lw a0, 0(t0)
	
	#-- Imprimir palabra en la consola
	li a7, PRINT_INT
	ecall
	
	#-- Imprimir una coma
	li a0, ','
	li a7, PRINT_CHAR
	ecall
	
	#-- Incrementar puntero t0
	addi t0, t0, 4
	
	#-- Leer palabra
	lw a0, 0(t0)
	
	#-- Imprimir palabra en la consola
	li a7, PRINT_INT
	ecall
	
	#-- Incrementar puntero t0
	addi t0, t0, 4
	
	#-- Terminar
	li a7, EXIT
	ecall

En esta animación se muestra en funcionamiento:

Ejercicio 7

Para recorrer el segmento de datos usamos un registro puntero, por ejemplo el t0. En cada pasada del bucle se incrementa t0 en 4 unidades para apuntar a la siguiente palabra

#-- Ejercicio 7: Volcado de memoria
#-- Situar 4 palabras en la memoria y hacer un bucle infinito que la vaya  
#-- recorriendo mostrando en pantalla sus valores
#-- Usar el caracter de salto de linea para separar las palabras


	#-- Códigos de servicio
	.eqv EXIT      10
	.eqv PRINT_INT 1
	.eqv PRINT_CHAR 11

	#-- Segmento de datos
	.data
datos:	.word 1,2,3,4,5,6,7,8,9,10


	.text

	#-- t0 es un puntero al comienzo del segmento de datos
	la t0, datos

	
bucle:			
	#-- Leer palabra
	lw a0, 0(t0)
	
	#-- Imprimir el numero en la consola
	li a7, PRINT_INT
	ecall
	
	#-- Imprimir el salto de linea
	li a0, '\n'
	li a7, PRINT_CHAR
	ecall
	
	#-- Incrementar el puntero
	addi t0, t0, 4
	 
	#-- Bucle infinito
	b bucle

Tras ejecutarlo con el Breakpoint, vemos en la consola cómo aparecen los números del 1 al 10, que estaban en la memoria. Luego se imprimen ceros, que es lo que hay en las posiciones de memoria consecutivas

En esta animación lo vemos en funcionamiento:

Ejercicio 8

El programa es similar al que hemos hecho en ejercicios pasados, pero usando los registros t0, t1 y t2 para almacenar los términos de fibonacci

#-- Ejercicio 8. Calcular la secuencia de fibonacci e
#-- imprimirla en la consola

	#-- Códigos de servicio
	.eqv EXIT      10
	.eqv PRINT_INT 1
	.eqv PRINT_CHAR 11

	#-- Valores de fibonacci iniciales
	.eqv INI0  0
	.eqv INI1  1


	.text

	#-- Usamos los registros t0 y t1 para los dos terminos anteriores
	li t0, INI0
	li t1, INI1
	
	#-- Los terminos iniciales no se imprimen
	
bucle:
	#-- calcular el siguiente termino
	add t2, t1, t0
	
	#-- Imprimir el siguiente termino
	mv a0, t2
	li a7, PRINT_INT
	ecall
	
	#-- Imprimir el caracter ,
	li a0, ','
	li a7, PRINT_CHAR
	ecall
	
	#-- Actualizar los terminos
	mv t0, t1
	mv t1, t2
	 
	#-- Bucle infinito
	b bucle

Lo ejecutamos bien paso a paso (con Breakpoints) o bien a velocidad lenta y vemos cómo en la consola va apareciendo la serie de Fibonacci:

En esta animación se muestra en funcionamiento:

Ejercicio 9

#-- Ejercicio 9. Cifrador sencillo
#-- Leer un caracter,incrementarlo en una unidad e imprimirlo en la consola
#-- Repetirlo en bucle infinito

	#-- Códigos de servicio
	.eqv READ_CHAR 12
	.eqv PRINT_CHAR 11

	.text
	
bucle:
	
	#-- Leer caracter del usuario
	li a7, READ_CHAR
	ecall
	
	#-- Incrementar el caracter recibido en una unidad
	addi a0, a0, 1
	
	#-- Imprimir el caracter en la consola
	li a7, PRINT_CHAR
	ecall
	
	#-- Imprimir un salto de linea
	li a0, '\n'
	li a7, PRINT_CHAR
	ecall
		
	#-- Bucle infinito
	b bucle

Después de haber introducido estos 4 caracteres: 'h', 'o', 'l' y 'a', en la consola veremos su siguiente letra en el alfabeto

En esta animación se muestra en funcionamiento:

Ejercicio 10

Examinando la ayuda, vemos que el sistema operativo nos ofrece el servicio Print_IntHex, cuyo código es el 34, para imprimir un número entero en hexadecimal

#-- Ejercicio 10: Volcado de memoria en hexadecimal
#-- Usar el caracter de salto de linea para separar las palabras


	#-- Códigos de servicio
	.eqv EXIT      10
	.eqv PRINT_INT 1
	.eqv PRINT_CHAR 11
	.eqv PRINT_INT_HEX  34

	#-- Segmento de datos
	.data
datos:	.word 10,11,12,13,14,15,127,255,0x00FABADA, 0xCAFEBACA


	.text

	#-- t0 es un puntero al comienzo del segmento de datos
	la t0, datos

	
bucle:			
	#-- Leer palabra
	lw a0, 0(t0)
	
	#-- Imprimir el numero en la consola
	li a7, PRINT_INT_HEX
	ecall
	
	#-- Imprimir el salto de linea
	li a0, '\n'
	li a7, PRINT_CHAR
	ecall
	
	#-- Incrementar el puntero
	addi t0, t0, 4
	 
	#-- Bucle infinito
	b bucle

Esto es lo que sale en la consola, tras 11 iteraciones:

Y en esta animación lo vemos en funcionamiento:

Sesión 6

Solución a los ejercicios de la Sesión de laboratorio L6:2-3

Ejercicio 1

  1. Las cadenas en tiempo de compilación se definen con la directiva .string (.asciz es equivalente). El programa pedido es el siguiente:
#-- Solucion Ejercicio 1

	.data
	
	.string "Cadena 1"
	.string "Cadena 2"
	.string "Cadena 3"
  1. Ensamblamos el programa y observamos el contenido de la segunda palabra. En hexadecimal es: 0x3120616e

Si la vemos en ASCII, su contenido es: 1 an

  1. Lo podemos contar de varias formas. Una es contando los caracteres que hay en las cadenas, contabilizando también los '\0' de terminación de cada cadena. Así cada cadena tiene en total 9 bytes, y como hay 3 cadenas, nos sale un total de 9 * 3 = 27 bytes

También lo podemos contador directamente en el segmento de datos:

. Vemos que hay 6 palabras completas (6 * 4 = 24 bytes) más 3 bytes de la ultima palabra. Que hacen un total de 27 bytes

  1. Las cadenas se almacenan carácter a carácter, cada uno en una dirección consecutiva, y terminado en '\0'. Por tanto, en la memoria tendremos esto:
Direccion Carácter
0x10010000 'C'
0x10010001 'a'
0x10010002 'd'
0x10010003 'e'
0x10010004 'n'
0x10010005 'a'
0x10010006 ' '
0x10010007 '1'
0x10010008 '\0'
0x10010009 'C'
0x1001000A 'a'
0x1001000B 'd'
0x1001000C 'e'
0x1001000D 'n'
0x1001000E 'a'
0x1001000F ' '
0x10010010 '2'
0x10010011 '\0'
0x10010012 'C'
0x10010013 'a'
0x10010014 'd'
0x10010015 'e'
0x10010016 'n'
0x10010017 'a'
0x10010018 ' '
0x10010019 '3'
0x1001001A '\0'

Que son exactamente 27 bytes

Ejercicio 2

Las cadenas se definen en tiempo de compilación con .string (o .asciz, que es equivalente). Para imprimirlas se invoca dos veces al servicio de PrintString

#-- Solucion Ejercicio 2

	.eqv PRINT_STRING 4
	.eqv EXIT         10

	.data
	
cad1:	.string "Hola\n"
cad2:	.string "Adios\n"
	
		
	.text
	
	#-- Imprimir la primera cadena
	la a0, cad1
	li a7, PRINT_STRING
	ecall
	
	#-- Imprimir la segunda cadena
	la a0, cad2
	li a7, PRINT_STRING
	ecall
	
	#-- Terminar
	li a7, EXIT
	ecall

En vez de usar "numeros mágicos" para los códigos de los servicios de EXIT y PrintString, se han definido identificadores, como ya sabemos hacer. Sin embargo, a partir de ahora estos códigos los incluiremos en un fichero separado (servicios.asm) y usaremos .include para incluirlos en nuestros programas. Así, el código quedaría de esta forma:

#-- Solucion Ejercicio 2

	.include "servicios.asm"

	.data
	
cad1:	.string "Hola\n"
cad2:	.string "Adios\n"
	
		
	.text
	
	#-- Imprimir la primera cadena
	la a0, cad1
	li a7, PRINT_STRING
	ecall
	
	#-- Imprimir la segunda cadena
	la a0, cad2
	li a7, PRINT_STRING
	ecall
	
	#-- Terminar
	li a7, EXIT
	ecall

Al ensamblarlo y ejecutarlo vemos las cadenas en la consola:

Ejercicio 3

Hay que combinar los servicios de impresión de Cadena y lectura de un número entero. Al leer los números hay que llevar el valor devuelto en a0 a alguno de los registros para luego hacer la suma. Como no nos dice explícitamente que usemos variables, y no nos hacen falta, no las usamos

	.include "servicios.asm"

	.data
	
#-- Cadenas con los mensajes a imprimir en cada momento

msg1:	.string "Introduce primer numero: "
msg2:   .string "Introduce el segundo numero: "
msg3:   .string "La suma es: "

	.text
	
	#-- Primer mensaje
	la a0, msg1
	li a7, PRINT_STRING
	ecall
	
	#-- Pedir numero
	li a7, READ_INT
	ecall
	
	#-- Guardar el primer numero en t1
	mv t1, a0
	
	#-- Segundo mensaje
	la a0, msg2
	li a7, PRINT_STRING
	ecall
	
	#-- Pedir numero
	li a7, READ_INT
	ecall
	
	#-- Guardar el segundo numero en t2
	mv t2, a0
	
	#-- Calcular la suma en t3
	add t3, t1, t2
	
	#-- Imprmir mensaje 3
	la a0, msg3
	li a7, PRINT_STRING
	ecall
	
	#-- Imprimir el resultado final
	li a7, PRINT_INT
	mv a0, t3
	ecall
	
	#-- Terminar
	li a7, EXIT
	ecall 

Ejercicio 4

Este ejercicio es para practicar con las cadenas definidas en tiempo de ejecución. Hay que usar la directiva .space para reservar espacio para su almacenamiento. Tenemos que calcular su tamaño máximo. En este ejericcio nos dicen explícitamente que el tamaño máximo debe ser de 1024. Si no nos dijeran, estbleceríamos nosotros su valor (un valor sensato)

  1. Este es el programa. Usamos la constante MAX para establecer el tamaño máximo. La usamos con la directiva .space y con el servicio READ_STRING. Así, si queremos establecer otro valor sólo hay que modificar esta constante al comienzo del programa
#-- Solucion ejercicio 4
#-- Lectura de una cadena
#-- Se pide al usuario que introduzca un texto
#-- que luego se imprime en la consola

	#-- Codigo de servicios
	.include "servicios.asm"
	
	#-- Tamaño máximo del texto
	.eqv MAX 1024

	.data
	
	#-- Mensajes de salida
msg1:	.string "Introduce un texto: "
msg2:   .string "Esto es lo que has escrito: \n"

	#-- Texto introducido por el usuario
texto:	.space MAX

	.text
	
	#-- Imprimir mensaje 1 pidiendo un texto
	la a0, msg1
	li a7, PRINT_STRING
	ecall

	#-- Leer texto introducido
	la a0, texto
	li a1, MAX
	li a7, READ_STRING
	ecall
	
	#-- Imprimir mensaje 2
	la a0, msg2
	li a7, PRINT_STRING
	ecall
	
	#-- Imprimir texto introducido por el usuario
	la a0, texto
	li a7, PRINT_STRING
	ecall
	
	#-- Terminar
	li a7, EXIT
	ecall
  1. Cuando se introduce la cadena "Búsca el carácter X", el carácter 'X' está almacenado en la dirección 0x10010045

Ejercicio 5

  1. La cadena ocupa 5 bytes (4 caracteres + el \0). A continuación hay definidos 4 bytes, por lo que el tamaño total es de 5 + 4 = 9 bytes. Esta es la posición de los elementos en el segmento de datos:

  1. En total los datos ocupan 3 palabras, aunque de la última sólo se usa un bytes

  1. Los bytes almacenados, en orden, son '1','2','3','4','\0',0xAA,0xBB,0xCC, 0xDD

  2. Al ejecutarlo se produce un error en tiempo de ejecución (una excepción). Estos errores se consideran graves, porque se aborta el programa por completo. En concreto, es un error de alineamiento de palabras

  1. Como no está claro el propósito del programa, porque el programador no ha puesto comentarios, vamos a analizar las diferentes alternativas. El error es debido a que se está intentando leer la palabra que está en la direcciónn 0x10010005, que NO está alineada. Una solución es alinearla, colocando .align 2:
#-- Solución ejercicio 5
	
	.data
	
	.string "1234"
	
	#-- Solucion 1: Alinear la etiqueta v1
	.align 2
	
v1:	.byte 0xAA
	.byte 0xBB
	.byte 0xCC
	.byte 0xDD
	
	.text
	
	la t0, v1
	lw t1, 0(t0)
	
	li a7,10
	ecall

Otra solución sería sustituir los cuatro .byte por un .word, inicializado con el valor 0xDDCCBBAA

#-- Solución ejercicio 5
	
	.data
	
	.string "1234"
	
v1:	.word 0xDDCCBBAA
	
	.text
	
	la t0, v1
	lw t1, 0(t0)
	
	li a7,10
	ecall
  1. Otra posibilidaad es que el programador en realidad sólo quería leer el byte situado en v1, pero hay una errata y puso lw en lugar de lb. En ese caso hay que sustutir lw por lb y ya no se producirá el error de alineamiento
#-- Solución ejercicio 5
	
	.data
	
	.string "1234"
v1:	.byte 0xAA
	.byte 0xBB
	.byte 0xCC
	.byte 0xDD
	
	.text
	
	la t0, v1
	lb t1, 0(t0)
	
	li a7,10
	ecall

Ejercicio 6

En este ejericicio se nos pide que modifiquemos el cuarto carácter de una cadena definida en tiempo de compilación. Y es que aunque la cadena esté definida a priori, al estar en memoria, nuestros programas pueden acceder a ellas y modicarlas

Este es el programa:

#-- Solucion al ejercicio 6

	#-- Código de los servicios del S.O
	.include "servicios.asm"

	.data
	
	#-- Cadena definida en tiempo de compilacion
hola:	.string "Hola\n"

	.text
	
	#-- Imprimir la cadena original
	la a0, hola
	li a7, PRINT_STRING
	ecall
	
	#-------- Modificar la 'a' por una 'i'
	li t1, 'i' #-- Nuevo caracter
	
	#-- La 'a' está 3 bytes adelante
	sb t1, 3(a0)
	
	#-- Imprimir la nueva cadena
	la a0, hola
	li a7, PRINT_STRING
	ecall
	
	#-- Terminar
	li a7, EXIT
	ecall

Ejercicio 7

La solución general se haría usando un bucle, pero todavía no los hemos visto. Así que se hace carácter a carácter. El objetivo del ejericicio es practicar con la manipulación de cadenas sencillas. Cambiando el desplazamiento (offset) accedemos fácilmente a los diferentes caracteres, manteniendo el mismo puntero al comienzo de la cadena

#-- Solucion del ejercicio 7
#-- Cifrado sencillo de una cadena de 4 bytes,
#-- Simplemente se suma 1 a cada caracter

	#-- Códigos de los servicios del S.O
	.include "servicios.asm"

	.data
	
msg:	.string "Hola\n"

	.text
	
	#-- Puntero a la cadena
	la a0, msg
	
	#-- Imprimir el mensaje original
	li a7, PRINT_STRING
	ecall
	
	#---------- CIFRADO
	#-- Leer cada byte de la cadena, incrementarlo y guardarlo
	lb t0, 0(a0)
	addi t0, t0, 1
	sb t0, 0(a0)
	
	lb t0, 1(a0)
	addi t0, t0, 1
	sb t0, 1(a0)
	
	lb t0, 2(a0)
	addi t0, t0, 1
	sb t0, 2(a0)
	
	lb t0, 3(a0)
	addi t0, t0, 1
	sb t0, 3(a0)
	
	#-- Imprimir el mensaje cifrado
	li a7, PRINT_STRING
	ecall

	#-- Terminar
	li a7, EXIT
	ecall 

Ejercicio 8

Este es el programa:

#-- Solucion al ejercicio 8

	#-- Código de servicios del S.O
	.include "servicios.asm"

	.data
	
	#-- Definir una palabra
v1:	.word 0xCADACAFE
v2:	.half 0xBACA
v3:	.byte 0xEA

	.text
	
	#-- Incrementar la palabra
	la t0, v1
	lw t1, 0(t0)
	addi t1,t1,1
	sw t1, 0(t0)
	
	#-- Incrementar la media palabra
	la t0, v2
	lh t1, 0(t0)
	addi t1,t1,1
	sh t1, 0(t0)
	
	#-- Incrementar el byte
	la t0, v3
	lb t1, 0(t0)
	addi t1,t1,1
	sb t1, 0(t0)
	
	
	#-- Terminar
	li a7, EXIT
	ecall

Al ensamblarlo, el segmento de datos contiene los valores iniciales:

Al ejecutarlo, se incrementan las tres variables, y lo vemos en la memoria:

Ejercicio 9

El acceso a ambos displays lo tenemos que hacer usando sb, porque son puertos de salida de byte. No nos piden sacar dígitos, sino simplemente escribir el valor de dos contadores a los puerto de salida, por lo que se encenderán diferentes segmentos, sin formar dígitos necesariamente

#-- Solucion al ejercicio 9
#-- Se tienen dos contadores, uno empieza en 0 y el otro en 1
#-- que se van incrementando en cada pasada de un bucle
#-- infinito. Estos valores se deben escribir en los puertos
#-- de salida de los displays Derecho e izquierdo, respectivamente

	#-- Direccion base de acceso a los displays
	.eqv BASE 0xFFFF0010
	
	#-- Desplazamientos de acceso a los displays
	.eqv DISP_R 0
	.eqv DISP_L 1

	.text
	
	#-- Registro t0 para acceder a los displays de 7 segmentos
	li t0, BASE
	
	
	#-- Contador 1 en registro t1. Inicializado a 0
	li t1, 0
	
	#-- Contador 2 en registro t2. Inicializado a 1
	li t2, 1
	
bucle:	#-- Escribir contadores en los puertos de salida de los displays
	sb t1, DISP_R(t0)
	sb t2, DISP_L(t0)
	
	#-- Incrementar los contadores
	addi t1, t1, 1
	addi t2, t2, 1
	
	#-- Repetir
	b bucle

Lo ensamblamos y lo ejecutamos a baja velocidad, para ver los segmentos de los displays. En esta animación lo vemos en funcionamiento:

Ejercicio 10

Se leen las teclas de la primera fila y su código se saca por el display izquierdo. No se pide que salgan dígitios, sino que simplemente se escriba el código de la tecla en el puerto de salida del display izquierdo

#-- Solucion al ejercicio 10
#-- Leer las teclas de la primera fila del teclado hexadecimal
#-- y escribir su código en el puerto de salida del display
#-- izquierdo

	#-- Direccion base de acceso a perifericos
	.eqv BASE 0xFFFF0010
	
	#--- Offset para accdeder a los diferentes perifericos
	
	#-- Display izquierdo
	.eqv DISP_L 01  #-- BASE + 1
	
	#-- Seleccion de la fila
	.eqv KEY_ENA 02  #-- BASE + 2
	
	#-- Lectura del codigo de tecla
	.eqv KEY_RD  04  #-- BASE + 4
	
	.text
	
	#-- Puntero base de acceso a perifericos
	li t0, BASE

	#-- Bucle infinito que está constntemente leyendo la 
	#-- primera fila
bucle:		
	#-- Seleccionar la fila 1
	li t1, 01
	sb t1, KEY_ENA(t0)
	
	#-- Leer la tecla
	lb t2, KEY_RD(t0)
	
	#-- Escribir el código en el display izquierdo
	sb t2, DISP_L(t0)
	
	b bucle

En esta animación se muestra en funcionamiento

Autores

Licencia

Enlaces

Página principal


Sesiones de Prácticas

P1: Simulador RARs

L1: Práctica 1-1. RARs
L2: Práctica 1-2. Ensamblador
L3: Práctica 1-3. Variables

P2: E/S mapeada. Llamadas al sistema

L4: Pract 2-1. E/S mapeada
L5: Práctica 2-2: Inst. ecall
L6: Prác 2-3: Cadenas

P3: Bucles y Saltos condicionales

L7: Práct 3-1: Bucles y saltos
L8: Práct 3-2: Cadenas II

P4: Subrutinas

L9: Pract 4-1: Subrut. Nivel-1
L10: Pract 4-2: La pila
L11: Pract 4-3: Recursividad

P5: Memoria Dinámica

L12: Pract 5-1. Heap. Listas

VÍDEO DE DESPEDIDA

Ejercicios de examen

Simulacro examen 1
GISAM. Ordinario. 2019-Dic-11
GISAM. Extra. 2020-Jul-03
GISAM. Ordinario. 2021-Ene-21
GISAM. Ordinario. 2022-Ene-10
GISAM. Extra. 2022-Jun-29
GISAM. Parcial 1. 2022-Oct-26
GISAM. Parcial 2. 2022-Nov-30
GISAM. Parcial 3. 2022-Dic-21
GISAM. Parcial 1. 2023-Oct-09
GISAM. Parcial 2. 2023-Nov-11
GISAM. Parcial 3. 2023-Dic-20
GISAM. Extra. 2024-Jun-17
GISAM. Parcial 1. 2024-Oct-14
GISAM. Parcial 2. 2024-Nov-13
GISAM. Parcial 3. 2024-Dic-16
TELECO. Ordinario. 2019-Dic-13
TELECO. Extra. 2020-Jul-07
TELECO. Ordinario. 2021-Ene-21
TELECO. Extra. 2021-Jul-02
TELECO. Ordinario. 2022-Ene-10
TELECO. Extra. 2022-Jun-29
TELECO. Ordinario. 2023-Ene-10
TELECO. Extra. 2023-Jun-29
TELECO. Parcial 1. 2023-Oct-20
TELECO. Parcial 2. 2023-Nov-17
TELECO. Parcial 3. 2023-Dic-22
TELECO. Extra. 2024-Jun-17
TELECO. Parcial 1. 2024-Oct-10
TELECO. Parcial 2. 2024-Nov-21
TELECO. Parcial 3. 2024-Dic-19
Robótica. Ordinario. 2020-Jun-1
Robótica. Extra. 2020-Jul-13
Robótica. Ordinario. 2021-Mayo-20
Robótica. Extra. 2021-Junio-16
Robótica. Parcial 1. 2022-Feb-25
Robótica. Parcial 2. 2022-Abril-1
Robótica. Parcial 3. 2022-Mayo-6
Robótica. Parcial 1. 2023-Feb-27
Robótica. Parcial 2. 2023-Mar-27
Robótica. Parcial 3. 2023-May-08
Robótica. Parcial 1. 2024-Feb-26
Robótica. Parcial 2. 2024-Mar-20
Robótica. Parcial 3. 2024-May-06
Robótica. Extra. 2024-Junio-24
Datos. Parcial 1. 2023-Oct-09
Datos. Parcial 2. 2023-Nov-15
Datos. Parcial 3. 2023-Dic-20
Datos. Parcial 1. 2024-Oct-09
Datos. Parcial 2. 2024-Nov-13

SOLUCIONES

Práctica 1: Sesiones 1,2 y 3
Práctica 2: Sesiones 4, 5 y 6
Práctica 3: Sesiones 7 y 8
Práctica 4: Sesiones 9, 10 y 11
Práctica 5: Sesión 12

Clone this wiki locally