Skip to content

SOLUCIONES a los ejercicios

Juan Gonzalez-Gomez edited this page Oct 1, 2025 · 117 revisions

Práctica 1: Soluciones a los ejercicios

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

Contenido

Práctica 1

Soluciones L3

Solución a los ejercicios de la Sesión L3

Ejercicio 1

  1. El objetivo de este ejercicio es familiarizarse con las pseudo-instrucciones li y mv. Si se ejecuta el programa completamente, veremos que todos los resultados son correctos, salvo el del registro x17, que contedrá el valor 10 en vez de 7. En la práctica 2 veremos la causa
#-- Ejercicio 1
#-- Inicializacion de los registros x5-x8
#-- Transferencia a los registros x15-x18

#-- Para inicializar los registros y hacer
#-- transferencias no necesitamos usar
#-- el segmento de datos. El enunciado no
#-- nos expecifica que los valores de inicializacion
#-- deban estar almacenados en memoria

#-- Por tanto, solo hay segmento de codigo
#-- y NO de datos

	.text
	
	#-- Inicializar los registros
	li x5, 5
	li x6, 6
	li x7, 7
	li x8, 8
	
	#-- Transferir los valores a los
	#-- registros x15-x18
	mv x15, x5
	mv x16, x6
	mv x17, x7
	mv x18, x8
	
	#-- Terminar
	#-- ¡OJO! se modifica el registro x17
	li a7, 10
	ecall

  1. El programa contiene 10 instrucciones en total

  2. Ocupa 10 * 4 = 40 bytes

  3. Al exportarlo a un fichero de hexadecimal de texto, obtenemos esto:

00500293  
00600313  
00700393
00800413
005007b3
00600833
007008b3
00800933
00a00893
00000073

Ejercicio 2

  1. Para saber las palabras almacenadas sólo hay que buscar las directivas .word del segmento de datos y contar el número total de palabras que hay. En este ejemplo hay en total 7 palabras, inicializadas con los valores 1,2,3,4,10,20 y 30. Las etiquetas NO definen palabras. Son simples alias para las direcciones de memoria

En este pantallazo se marcan todas las palabras definidas en el segmento de datos

  1. Puesto que hay 7 palabras, y cada palabra ocupa 4 bytes, en segmento de datos ocupa un total de 7 * 4 = 28 bytes

  2. Cuando nos piden el tamaño del programa, se refieren siempre a la parte del segmento de código. En este caso hay 2 instrucciones, por lo que el programa ocupa 8 bytes

  3. Las direcciones de las etiquetas las obtenemos directamente de la tabla de símbolos del simulador:

Por tanto la solución es esta:

Etiqueta Dirección
a 0x10010000
b 0x10010000
c 0x10010010
d 0x10010018
e 0x1001001c
  1. Ensamblamos el programa y miramos en la ventana del segmento de datos, en la dirección 0x10010014:

El valor almacenado es 20 (en decimal) ó 0x14 en hexadecimal

  1. Teniendo en cuenta que se usa el convenio Little-endian (los bytes de menor peso se almacenan en las direcciones más bajas), los bytes que se encuentran en las direcciones pedidas son:
Dirección Byte
0x10010000 01
0x10010001 00
0x10010002 00
0x10010003 00
0x10010004 02
0x10010005 00
0x10010006 00
0x10010007 00
--------- -----
0x10010018 30
0x10010019 00
0x1001001A 00
0x1001001B 00
  1. Si volcamos el segmento de datos a un fichero hexadecimal, obtenemos:
00000001
00000002
00000003
00000004
0000000a
00000014
0000001e
00000000
00000000
00000000
00000000
...
00000000

Se vuelcan las primeras 4KiB. Las 7 primeras palabras son las que hay en el programa. El resto de posiciones de memoria están a cero

Ejercicio 3

El programa que nos piden es el siguiente. Nos dan los nombres de las variables: v1, v2, v3 y v4: son las etiquetas que utilicemos para acceder a sus valores

#-- Programa para crear 4 variables
#-- inicializadas a unos valores

	#-- Segmento de datos
	.data
v1:	.word 0x12345678
v2:	.word 0x11223344
v3:	.word 0xCACABACA
v4:	.word 0x00FABADA

	#-- Segmento de código
	.text
	
	li a7, 10
	ecall
  1. Ensamblamos el programa y comprobamos que efectivamente las primeras 4 palabras tienen los valores que nos han indicado:

  1. Exportamos el segmento de datos a un fichero hexadecimal de texto. Las cuatro primeras posiciones contienen:
12345678
11223344
cacabaca
00fabada
  1. Con el comando hd vemos:
00000000  78 56 34 12 44 33 22 11  ca ba ca ca da ba fa 00  |xV4.D3".........|
00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00001000

El byte que se encuentra en la quinta posición es: 0x44. Está en la dirección de memomria: 0x10010004

Ejercicio 4

  1. El programa es:
#-- Cargar las direcciones de las
#-- variables en los registros x5-x8

	#-- Variables en el seg. de datos
	.data
a:	.word 0
b:	.word 0
c:	.word 0
d:	.word 0

	#-- Segmento de código
	.text
	
	#-- Obtener las direcciones
	la x5, a
	la x6, b
	la x7, c
	la x8, d
	
	#-- Terminar
	li a7, 10
	ecall
  1. Ensamblamos y abrimos la tabla de símbolos

Las direcciones son:

0x10010000
0x10010004
0x10010008
0x1001000C
  1. Ensamblamos el programa. Hay 10 instrucciones en código máquina:

Por tanto el programa ocupa 10 * 4 = 40 bytes

Ejercicio 5

  1. Este es el programa modificado. Las variables se inicializan directamente en el segmento de datos. Una vez que se tienen sus direcciones en los registros x5,x6,x7 y x8, se procede a cargar sus valores en los registros x10,x11,x12 y x13 utilizando la instrucción de carga de palabras: lw
#-- Cargar las direcciones de las
#-- variables en los registros x5-x8
#-- Inicializa los registros x10-x13 con los valores de 
#-- las variables 

	#-- Variables en el seg. de datos
	.data
a:	.word 1
b:	.word 2
c:	.word 3
d:	.word 4

	#-- Segmento de código
	.text
	
	#-- Obtener las direcciones
	la x5, a
	la x6, b
	la x7, c
	la x8, d
	
	#-- Inicializar los registros
	lw x10, 0(x5)  #-- x10 = a
	lw x11, 0(x6)  #-- x11 = b
	lw x12, 0(x7)  #-- x12 = c
	lw x13, 0(x8)  #-- x13 = d
	
	
	#-- Terminar
	li a7, 10
	ecall

Ensamblamos y ejecutamos el programa. Podemos ver los valores de las variables en memoria y cómo se han cargado en los respectivos registros

  1. El programa tiene 14 instrucciones. Por tanto ocupa: 14 * 4 = 56 bytes

Ejercicio 6

  1. El nuevo programa es el siguiente. Aunque están definidas las etiquetas b,c y d, sólo usamos la de a para inicializar el puntero en x5. A partir de él, podemos acceder a todas las variables mediante 0(x5), 4(x5), 8(x5) y 12(x5)
#-- Inicializa los registros x10-x13 con los valores de 
#-- las variables. En x5 se debe situar la direccion de la variable a 
#-- y usarlo para acceder al resto de variables

	#-- Variables en el seg. de datos
	.data
a:	.word 1
b:	.word 2
c:	.word 3
d:	.word 4

	#-- Segmento de código
	.text
	
	#-- Obtener la direccion de a
	la x5, a
	
	#-- Inicializar los registros
	lw x10, 0(x5)  #-- x10 = a
	lw x11, 4(x5)  #-- x11 = b
	lw x12, 8(x5)  #-- x12 = c
	lw x13, 12(x5)  #-- x13 = d
	
	
	#-- Terminar
	li a7, 10
	ecall

Lo ensamblamos y lo ejecutamos. Comprobamos que funciona correctamente, cargando en los registros x10-x13 los valores iniciales de las varaibles

  1. Este programa hace lo mismo que el del ejercicio 5, pero sólo tiene 8 instrucciones, por lo que ocupa: 8 * 4 = 32 bytes.

  2. Este programa es más optimo que el anterior, ya que ocupa menos espacio. Por ello, siempre que tengamos variables contiguas de memoria, es más óptimo acceder a ellas usando un único puntero

Ejercicio 7

  1. El programa se puede implementar de muchas formas. Pero, teniendo en cuenta los resultados de los ejercicios anteriores, usamos un único puntero para acceder a las variables, por lo que el programa será más óptimo
#-- Programa para calcular la expresion f = (a + b + c) - (d - 3)


	#-- Variables
	.data
	
a:	.word -5
b: 	.word 2
c:	.word 30
d:	.word 5
f:	.word 0

	#-- Segmento de código
	.text
	
	#-- Para calcular la expresion usaremos los sig. registros:
	#-- x5 = a
	#-- x6 = b
	#-- x7 = c
	#-- x8 = d
	#-- x12 = f
	
	#-- Leer las variables y las situamos en los registros
	la x4, a  #-- Usamos x4 como puntero para acceder a las varaibles
	lw x5, 0(x4)  #-- x5 = a
	lw x6, 4(x4)  #-- x6 = b
	lw x7, 8(x4)  #-- x7 = c
	lw x8, 12(x4) #-- x8 = d
	
	#-------------- Calcular la expresión
	add x9, x5, x6  #-- x9 = a + b
	add x9, x9, x7  #-- x9 = a + b + c
	addi x10, x8, -3  #-- x10 = d - 3
	sub x12, x9, x10  #-- x12 = (a + b + c) - (d - 3)
	
	#-- Almacenar el resultado en f
	sw x12, 16(x4)  #-- f = (a + b + c) - (d - 3)
	
	#-- Terminar
	li a7, 10
	ecall
  1. Lo ensamblamos y lo ejecutamos. El valor obtenido en f es correcto: 25

  1. El programa tiene 13 instrucciones, por lo que ocupa 13 * 4 = 52 ybtes

  2. En el pantallazo anterior se puede ver. Es la variable que se encuentra en la quinta posición. Su dirección es la 0x10010010. También lo podemos ver mostrando la tabla de símbolos

Ejercicio 8

  1. Este es el programa que calcula la sucesión de fibonacci, dejando los términos calculaos en palabras consecutivas del segmento de datos
#-- Calcular la sucesion de fibonacci
#-- Almacenarla en el segmento de datos,
#-- en palabras consecutivas

	.data
	
	#-- Valores iniciales de la secuencia de fibonacci
fib0:	.word 0
fib1: 	.word 1


	.text
	
	#-- Puntero para acceder a los datos
	la x5, fib0
	
	#-- Los terminos de Fibonacci estan en los registros x10 y x11
	lw x10, 0(x5)  #-- Primer termino de fibonacci
	lw x11, 4(x5)  #-- Segundo termino de fibonacci
	
	#-- x5 es el puntero hacia el siguiente termino de fibonacci en memoria
	addi x5, x5, 8
	
bucle:
	#-- Obtener el siguiente termino de Fibonacci
	add x12, x10, x11  
	
	#-- Almacenarlo en la memoria, en la direccion apuntada por x5
	sw x12, 0(x5)
	
	#-- Incrementar el puntero x5 para apuntar a la siguiente palabra
	addi x5, x5, 4
	
	#-- Actulizar los terminos anteriores de fibonacci
	mv x10, x11
	mv x11, x12
	
	#-- Repetir
	b bucle

En esta animación se muestra la simulación del programa, y cómo está funcionando correctamente

  1. Al ejecutarlo sin breakpoint, al cabo de un tiempo vemos que le programa se para y aparece un error en la consola

Si miramos en la parte de la derecha, el error dice:

line 29: Runtime exception at 0x00400018: address out of range 0x10400000

Estamos usando un bucle infinito, por lo que se va rellenando el segmento de datos indefinidamente. Hasta llegar a su límite: estamos intentando acceder a una dirección que está fuera del segmento de datos

Ejercicio 9

Se puede probar bien poniendo un breakpoint y ejecutando manualmente, o bien bajando la velocidad y que se ejecute sin breakpoint. Se comprueba que efectivamente se está accediendo secuencialmente a la memoria. En esta animación se muestra en acción

Ejercicio 10

Nos piden un programa que escriba el valor 0xAA5555AA en ciertas palabras del segmento de datos: en la primera (1), cuarta, quinta y octava. Esas direcciones se corresponden con los desplazamientos (offsets): 0, 0xC, 0x10 y 0x1C. Sólo hay que usar un puntero que tenga la dirección de la primera palabra y escribir el valor patrón en esos offsets:

#-- Comprobacion de la memoria
#-- Este programa debe escribir un valor en las palabras
#-- de la memoria 0, 3, 4 y 7

	.data
memoria:

	.text
	
	#-- Puntero para acceder a la memoria, en x5
	la x5, memoria
	
	#-- Valor de test a escribir:
	li x10, 0xAA5555AA
	
	#-- Escribir en la primera posicion
	sw x10, 0(x5)
	
	#-- Escribir en la cuarta palabra
	sw x10, 0xC(x5)
	
	#-- Escribir en la quinta palabra
	sw x10, 0x10(x5)
	
	#-- Escribir en la octava palabra
	sw x10, 0x1C(x5)
	
	#-- Terminar
	li a7, 10
	ecall

Comprobamos que al ejecutarlo efectivamente se obtiene el patrón pedido, y también vemos que en las posiciones indicadas se ha escrito el valor 0xAA5555AA

Ejercicio 11

Para obtener ese patrón de acceso a memoria podemos bien escribir cualquier valor en esas posiciones, o bien leerlo. La herramienta de visualización de memoria nos hace el recuento de los accesos en lectura y/o escritura. Usamos por ejemplo escrituras, como en el ejercicio anterior

Lo que tenemos que calcular son los desplazamientos necesarios para acceder a las posiciones de memoria pedidas. Cada cuadrado es una palabra, y en cada línea hay 16 palabras: 16 * 4 = 64 bytes. Si se incrementa el offset en 64, se accede al cuadrado que está debajo, en la siguente fila

A partir de esto vamos calculando los offsets de las 9 posiciones pedidas:

#-- Generar un "smiley" en el monitor
#-- de acceso a memoria :-)

	.data
memoria:

	.text

	#-- Puntero al comienzo del segmento de datos
	la x5, memoria
	
	#-- Valor a almacenar en las posiciones de memoria
	#-- vale cualquiera
	li x10, 1
	
	#-- Ojos
	sw x10, 0x48(x5)
	sw x10, 0x50(x5)
	sw x10, 0x88(x5)
	sw x10, 0x90(x5)
	
	#-- Parte superior sonrisa
	sw x10, 0x104(x5)
	sw x10, 0x114(x5)
	
	#-- Parte inferior sonrisa
	sw x10, 0x148(x5)
	sw x10, 0x14C(x5)
	sw x10, 0x150(x5)
	
	#-- Terminar
	li a7, 10
	ecall

Lo ensamblamos y lo ejecutamos. Vemos que el patrón que aparece es el pedido. También podemos ver los valores almacenados en el segmento de datos (en las 9 posiciones)

Autores

Licencia

Enlaces

Página principal


Sesiones de Prácticas

P1: Simulador RARs

L1: El simulador RARs
L2: Calculando expresiones
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

SESIONES ADICIONALES

L13: RV32I: Resto de instrucciones
L14: Macros
L15: Entrada/Salida a bajo nivel
L16: Multiplicaciones/divisiones. Unit Tests 🚧
L17: Biblioteca stdio: salida a alto nivel 🚧
Los registros de estado y control (CSR)
Interrupciones y excepciones
Borrador

SOLUCIONES

Soluciones a los ejercicios planteados en cada sesión para practicar:
Sesión L1
Sesión L2
Sesión L3
Sesión L4
Sesión L5
Sesión L6
Sesión L7
Sesión L8
Sesión L9
Sesión L10
Sesión L11
Sesión L12

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
GISAM. Extra. 2025-Jun-17
GISAM. Parcial 1. 2025-Oct-20
GISAM. Parcial 2. 2025-Nov-19
GISAM. Parcial 3. 2026-Enero-9
GISAM. Parcial 1. 2026-Oct-21
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
TELECO. Extra. 2025-Jun-17
TELECO. Parcial 1. 2025-Oct-10
TELECO. Parcial 2. 2025-Nov-13
TELECO. Parcial 3. 2026-Ene-21
TELECO. Extra. 2026-Jun-25
TELECO. Parcial 1. 2026-Oct-09
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
Robótica. Parcial 1. 2025-Feb-25
Robótica. Parcial 2. 2025-Mar-31
Robótica. Parcial 3. 2025-May-19
Robótica. Parcial 1. 2026-Feb-23
Robótica. Parcial 2. 2026-Abr-13
Robótica. Parcial 3. 2026-May-11
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
Datos. Parcial 3. 2025-Ene-17
Datos. Parcial 1. 2025-Oct-15
Datos. Parcial 2. 2025-Nov-19

Clone this wiki locally