Repository navigation
L2: SOLUCIONES
Solución a los ejercicios de la Sesión L2
- Ejercicio 1
- Ejercicio 2
- Ejercicio 3
- Ejercicio 4
- Ejercicio 5
- Ejercicio 6
- Ejercicio 7
- Ejercicio 8
- Ejercicio 9
- Ejercicio 10
- Autores
- Licencia
- Enlaces
- El programa suma-enteros.s tiene 5 instrucciones en código máquina. Para comprobarlo hay que ensamblar el programa y contar el número de filas de la columna que pone Code

-
El programa tiene 5 instrucciones. Cada instrucción ocupa 4 bytes. Por tanto, su tamaño es de 5 * 4 = 20 bytes
-
Para completar la tabla sólo hay que mirar en la columna que pone Address. Esa columna nos indica las direcciones donde se almacena cada una de las instrucciones. Como las instrucciones son siempre de 4 bytes (32-bits) estas direcciones siempre serán múltiplos de 4

Así es como queda la tabla que nos piden:
| Direccion (alineada) | Instrucción en código máq. |
|---|---|
| 0x00400000 | 00000293 |
| 0x00400004 | 00000313 |
| 0x00400008 | 00128293 |
| 0x0040000c | 00530333 |
| 0x00400010 | ff9ff06f |
- Lo que nos piden es que indiquemos qué byte es el que está almacenado en cada una de las posiciones de memoria. Dado que el byte es la unidad mínima de información en Informática, las memorias siempre tienen granularidad de bytes: es decir, que aunque almacenemos números mayores de 8-bits, siempre podemos acceder a los bytes individuales
Para completar la tabla tanemos que saber que el procesador RISC-V utiliza una ordenación de tipo Little-endian, lo que significa que el byte de menor peso de la instruccion siempre se almacena en la dirección más baja
Así es como queda la tabla pedida:
| Dirección | Byte |
|---|---|
| 0x004000 | 93 |
| 0x004001 | 02 |
| 0x004002 | 00 |
| 0x004003 | 00 |
| 0x004004 | 13 |
| 0x004005 | 03 |
| 0x004006 | 00 |
| 0x004007 | 00 |
| 0x004008 | 93 |
| 0x004009 | 82 |
| 0x00400a | 12 |
| 0x00400b | 00 |
| 0x00400c | 33 |
| 0x00400d | 03 |
| 0x00400e | 53 |
| 0x00400f | 00 |
| 0x004010 | 6f |
| 0x004011 | f0 |
| 0x004012 | 9f |
| 0x004013 | ff |
- El objetivo de este ejercicio es que practiques ejecutando el programa paso a paso. Pero para facilitar la depuración de estos programas, resulta muy útil colocar un Breakpoint en la instrucción
jy ver lo que ocurre en la pasada número 25. Basta con darle al botón de play hasta que veamos que el registrox5toma el valor25. El resultado acumulado hasta el momento lo tenemos enx6, cuyo valor es de 325

- Este es el programa que calcula la suma de los enteros pares
- Fichero: L2-sol-02.s
#-- Solucion al ejercicio 2
#-- Calcular la suma de los numeros pares
#-- 2 + 4 + 6 + 8 + 10 + ....
.text
#-- Inicializamos los registros x5,x6 a 0
addi x5, x0, 0
addi x6, x0, 0
#-- Bucle principal
bucle:
#-- Incrementar contador principal en dos unidades
addi x5, x5, 2 #-- x5 = x5 + 2
#-- Obtener termino i-esimo
add x6, x6, x5 #-- x6 = x6 + x5
#-- Repetir el bucle
j bucle-
El número de instrucciones varía de una implementación a otra (Tu programa puede tener un número diferente). Este tiene 5 instrucciones
-
Tiene 5 instrucciones. Cada instrucción ocupa 4 bytes. El tamaño que ocupa es de 5 * 4 = 20 bytes
-
La tabla con las instrucciones en código máquina, y en qué dirección se encuentra cada una se muestra en esta tabla. Esta es la tabla del programa implementado en el punto 1 (tu programa puede tener otras instrucciones diferentes)
| Direccion (alineada) | Instrucción en código máq. |
|---|---|
| 0x00400000 | 00000293 |
| 0x00400004 | 00000313 |
| 0x00400008 | 00228293 |
| 0x0040000c | 00530333 |
| 0x00400010 | ff9ff06f |
- El valor obtenido es: 650
- Programa que calcula la sucesión de Fibonacci:
- Fichero: L2-sol-03-fibonacci.s
# Sesion L2
#-- Solucion al ejercicio 3
#-- Calculo de la serie de fibonacci: 0, 1, 1, 2, 3, 5, 8, 21...
#-- La serie se puede ver en el registro x7
#-- x5 y x6 se utilizan para los calculos intermedios
.text
#-- Valores iniciales, 1, 1
addi x5, x0, 0
addi x6, x0, 1
bucle:
#-- Calcular siguiente término en t2
add x7, x5, x6 # x7 = x5 + x6
#-- Actualizar registros
add x5, x6, x0 #-- x5 = x6
add x6, x7, zero #-- x6 = x7
j bucle-
El valor del término 10 de fibonacci es 55 (Se obtiene cuando el bucle ha dado 8 vueltas porque en la primera se tiene el término 3. Los términos 1 y 2 son 0 y 1 respectivamente, que son los valores iniciales)
-
Esta implementación del programa tiene 6 instrucciones. La tuya puede tener un número diferente
-
Como tiene 6 instrucciones, y cada instrucción ocupa 4 bytes, el tamaño del programa es de 6 * 4 = 24 Bytes
-
Tabla con el código máquina:
| Direccion (alineada) | Instrucción en código máq. |
|---|---|
| 0x00400000 | 0x00000293 |
| 0x00400004 | 0x00100313 |
| 0x00400008 | 0x006283b3 |
| 0x0040000c | 0x000302b3 |
| 0x00400010 | 0x00038333 |
| 0x00400014 | 9xff5ff06f |
- Tabla con los bytes del programa
| Dirección | Byte |
|---|---|
| 0x004000 | 93 |
| 0x004001 | 02 |
| 0x004002 | 00 |
| 0x004003 | 00 |
| 0x004004 | 13 |
| 0x004005 | 03 |
| 0x004006 | 10 |
| 0x004007 | 00 |
| 0x004008 | b3 |
| 0x004009 | 83 |
| 0x00400a | 62 |
| 0x00400b | 00 |
| 0x00400c | b3 |
| 0x00400d | 02 |
| 0x00400e | 03 |
| 0x00400f | 00 |
| 0x004010 | 33 |
| 0x004011 | 83 |
| 0x004012 | 03 |
| 0x004013 | 00 |
| 0x004014 | 6f |
| 0x004015 | f0 |
| 0x004016 | 5f |
| 0x004017 | ff |
- Fichero: L2-sol-04.s
# Sesion L2
## Programa para calcular la expresion:
## f = (a + b + c) - [(d - a) + (e + 3) - 30]
## Valores iniciales de prueba: a=2, b=4, c=6, d=8, e=10
.text
#-- Valores iniciales
addi x5,x0,2 #-- x5 = a = 2
addi x6,x0,4 #-- x6 = b = 4
addi x7,x0,6 #-- x7 = c = 6
addi x8,x0,8 #-- x8 = d = 8
addi x9,x0,10 #-- x9 = e = 10
#-- Calcular la expresion. Resultado en X10
add x11, x5, x6 #-- x11 = a + b
add x11, x11,x7 #-- x11 = (a + b + c)
sub x12, x8, x5 #-- x12 = (d - a)
addi x13, x9, 3 #-- x13 = (e + 3)
addi x14, x13, -30 #-- x14 = (e + 3) - 30
add x15, x12, x14 #-- x15 = [(d - a) + (e + 3) - 30]
#-- Resultado final
sub x10, x11, x15 #-- x10 = (a + b + c) - [(d - a) + (e + 3) - 30]
#-- Terminar
li a7, 10
ecallPara el valor de las variables a=2, b=4, c=6, d=8, e=10, se obtiene que f = 23
- La expresión que se calcula es: x10 = 2x5 + 4x6 - (x7 - x8) + 15
El término 2*x5 se obtiene porque se suma x5 con x5:
add x5, x5, x5 #-- x5 = X5 + X5 = 2*x5El término 4*x6 se obtiene por estas dos instrucciones:
add x6, x6, x6 #-- x6 = 2*x6
add x6, x6, x6 #-- x6 = 2* (2*x6)Si asignamos las variables a los registros de esta forma: x10 = f, x5=a, x6=b, x7=c, x8=d, tenemos que la expreión es: f = 2a + 4b - (c - d) + 15
-
Se prueba con los valores a=3, b=5, c=7, d=9, que son los que se utilizan al comienzo para inicializar los registros x5,x6,x7 y x8
-
El resultado es 43
-
El valor de la posición de memoria 0x00400015 es 03. Lo comprobamos muy fácilmente buscando la palabra alineada inferior (Dirección 0x00400014) y aplicando el criterio Little endian sacamos el valor

- El programa tiene 13 instrucciones. Cada instrucción es de 4 bytes. Por tanto ocupa 13 * 4 = 52 bytes
- Obtener el código máquina de las instrucciones es muy sencillo usando directamente el ensamblador. Las copiamos al RARs, las ensamblamos y obtenemos el código máquina:

Estas son las dos instrucciones en código máquina
addi x0, x0, 0 -----> 0x00000013
addi x0, x0, 0xFA ---> 0x0FA00013- Solo se diferencian en los caracteres hexadecimales FA. Parece
que esos bits codifican el valor inmediato de la instrucción addi
Si eso es cierto, el código máquina de la instruccio addi x0,x0,0xBB seria 0x0BB00013. Vamos a comprobarlo con el simulador:

¡Exacto! ¡es esa misma! 😄
- Obtenemos el código máquina de las dos instrucciones, usando el simulador:
addi x0, x1, 0 --> 0x00008013 --> 0000 0000 0000 0000 1000 0000 0001 0011
addi x0, x2, 0 --> 0x00010013 --> 0000 0000 0000 0001 0000 0000 0001 0011
==== ==== ==== ===x x=== ==== ==== ====Solo se diferencian en 2 bits: el 15 y el 16. Parece que esos bits codifican el número de registro
- Obtenemos el código máquina de las dos instrucciones, con el simulador:
addi x0, x0, 0 ---> 0x00000013 --> 0000 0000 0000 0000 0000 0000 0001 0011
addi x31, x0, 0 --> 0x00000F93 --> 0000 0000 0000 0000 0000 1111 1001 0011
==== ==== ==== ==== ==== xxxx x=== ====Parece que el número de registro se codifica los bits 7-11 (5 bits)
El registro 0 tiene esos 5 bits a 0: 00000
El registro 31 tiene esos 5 bits a 1: 11111
Por definición, la etiqueta es un símbolo que se corresponde con una dirección de memoria. Los humanos, en vez de trabajar con direcciones numéricas, que nos resultan complejas, trabajamos con etiquetas. Es el ensamblador el que tiene una tabla de símbolos en la que hace la conversion de humano a máquina
| Etiqueta | Dirección |
|---|---|
| ini | 0x00400000 |
| a | 0x00400000 |
| b | 0x0040000C |
| c | 0x0040001C |
| d | 0x00400028 |
| fin | 0x00400030 |
| last | 0x00400034 |
El PC vale 0x0040000C. Esto significa que la siguiente instrucción que
se ejecutará será la que esté en esa dirección... que es: addi x8, x8, 9
Podemos ver rápidamente qué instrucción está en cada dirección ensamblando el programa y viendo la instrucción de la dirección 0x0040000C

Como la etiqueta vale 0x00502020, sabemos que esa es la direccion
de la primera instrucción del fragmento. A partir de ese valor
podemos calcular las demás:
| Etiqueta | Direccion |
|---|---|
| b | 0x00502020 |
| c | 0x00502030 |
| d | 0x0050203C |
| fin | 0x00502044 |
#-- Programa en ensamblador para calcular la expresion:
#-- f = (d - c) + 15 - (a + b)
#-- Probarlos con las siguientes secuencias de valores:
#-- a=1,2,3,4,5...
#-- b=2,3,4,5,6..
#-- c=3,4,5,6,7..
#-- d=4,5,6,7,8..
.text
#--- Inicializacion
addi x5,x0,1 #-- x5 = a
addi x6,x0,2 #-- x6 = b
addi x7,x0,3 #-- x7 = c
addi x8,x0,4 #-- x8 = d
bucle:
#-- calcular la expresion
sub x11, x8, x7 #-- x11 = (d - c)
addi x11,x11,15 #-- x11 = (d - c) + 15
add x12,x5,x6 #-- x12 = (a + b)
sub x13, x11,x12 #-- x13 = (d - c) + 15 - (a + b)
nop #-- No hace nada. Se usa para poner aqui el Breakpoint
#-- Incrementar x5,x6,x7 y x8
addi x5,x5,1 #-- a = a+1
addi x6,x6,1 #-- b = b+1
addi x7,x7,1 #-- c = c+1
addi x8,x8,1 #-- d = d+1
#-- Repetir. Siguiente iteraccion
j bucleEn la decima iteracion, los valores iniciales son:
a=10,
b=11,
c=12,
d=13
El valor calculado es -5, que es correcto
- Juan González-Gómez (Obijuan)
- Katia Leal Algara
- Miguel Ángel de Miguel Paraíso
- Javier Macias del Campo
L1: El simulador RARs
L2: Calculando expresiones
L3: Práctica 1-3. Variables
L4: Pract 2-1. E/S mapeada
L5: Práctica 2-2: Inst. ecall
L6: Prác 2-3: Cadenas
L7: Práct 3-1: Bucles y saltos
L8: Práct 3-2: Cadenas II
L9: Pract 4-1: Subrut. Nivel-1
L10: Pract 4-2: La pila
L11: Pract 4-3: Recursividad
L12: Pract 5-1. Heap. Listas
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 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
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