SOLUCIONES a los ejercicios - myTeachingURJC/2019-20-LAB-AO GitHub Wiki

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

Sesión 1

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

Ejercicio 1

La instrucción para hacer una asignación a un registro es addi, usando como registro fuente el x0

# Solucion a la actividad no guiada 1
#-- Asignar los siguientes valores a los registro indicados:
#-- x3=3, x4=4, x5=5, x6=6, x7=7 y x8=8

  .text
	
  addi x3, x0, 3   # x3 = 3
  addi x4, x0, 4   # x4 = 4
  addi x5, x0, 5   # x5 = 5
  addi x6, x0, 6   # x6 = 6
  addi x7, x0, 7   # x7 = 7
  addi x8, x0, 8   # x8 = 8
	
  #-- Terminar
  li a7, 10
  ecall

Nota avanzada: En la sesión 3 vimos que estas mismas asignaciones las podemos hacer con la pseudo-instrucción li. Es el programa ensamblador el que la convierte en la instrucciónn addi equivalente. El programa sería:

# Solucion a la actividad no guiada 1
#-- También se puede usar la pseudo-instruccion li
#-- El programa queda más sencillo:

  .text
	
  li x3, 3   # x3 = 3
  li x4, 4   # x4 = 4
  li x5, 5   # x5 = 5
  li x6, 6   # x6 = 6
  li x7, 7   # x7 = 7
  li x8, 8   # x8 = 8
	
  #-- Terminar
  li a7, 10
  ecall

En ambos casos comprobamos que el programa funciona correctamente simulándolo y viendo el valor de sus registros en la parte derecha:

Ejercicio 2

Basta con sustituir la instrucción addi x5, x5, 1 por addi x5, x5, 2. De esta forma en cada vuelta del bucle se realizará la operación x5 = x5 + 2, en vez de x5 = x5 + 1

# Solucion a la actividad no guiada 2
#-- Programa contador que se incremete de dos en dos

	.text
	
	#-- Inicializar el regitro x5 a 0
	addi x5, x0, 0
	
bucle:
	#-- Incrementar x5 en dos unidades
        #-- x5 = x5 + 2
	addi x5, x5, 2
	
	#-- Repetir indefinidamente
	b bucle

Lo simulamos para comprobar que funciona correctamente. Nos fijamos en el registro x5: Efectivamente sólo toma los valores pares

Ejercicio 3

Partimos del ejemplo del contador. Es la misma estructura. Sólo hay que inicializar los tres regisros a cero y añadir los incrementos en el bucle

# Solucion a la actividad no guiada 3
# El registro x3 toma los valores 0,1,2,3,4,5...
# El x4: 0,3,6,9,12,15...
# El x5 0,5,10,15,20,25.... 
#-- Se repite indefinidamente

	.text
	
	#-- Inicializar los registros a 0
	addi x3, x0, 0
	addi x4, x0, 0
	addi x5, x0, 0 
	
bucle:
	#-- Incrementar x3 en una unidad: x3 = x3 + 1
	addi x3, x3, 1
	
	#-- Incrementar x4 en 3 unidades: x4 = x4 + 3
	addi x4, x4, 3
	
	#-- Incrementar x5 en 5 unidades: x5 = x5 + 5
	addi x5, x5, 5
	
	#-- Repetir indefinidamente
	b bucle

Al simularlo comprobamos que efectivamente está funcionando correctamente. El registro x3 se incrementa de uno en uno, empezando en 0. El x4 de 3 en 3, también empezando desde cero. Y el x5 de 5 en 5, comenzando por 0

Ejercicio 4

Las dos acciones que nos piden, inicializar y restar 1, las realizamos con la operacion de suma addi

# Solucion a la actividad no guiada 4
#  programa que ejecute las siguientes acciones:
#   * Inicializar el registro 6 a 0
#   * Restarle 1
#   * Terminar 

	.text
	
	#-- Inicializar registro 6 a 0
	addi x6, x0, 0
	
	#-- Restar 1
	addi x6, x6, -1
	
	#-- Terminar
	li a7, 10
	ecall

Para entender mejor el valor de x6 al restar 1, activamos la opción de ver los registros en hexadecimal y observamos que vale 0xFFFFFFFF (todos los bits a 1). Este es el valor de -1 en complemento a dos

Ejercicio 5

Se trata de una cuenta atrás. El registro x3 comienza en 10, se va decrementando hasta llegar a 0, y termina

Ejercicio 6

Este programa implementa la multiplicación de dos registros, utilizando sumas. En los registros x5 y x6 se introducen los dos números a multiplicar. El resultado se devuelve en x7

# Es un programa que implementa la multiplicacion
# de dos registros, usando sumas
# En los registros x5 y x6 se introducen los dos numeros 
# a multiplicar. El resultado se devuelve en x7
# Asi, el resultado de este programa es x7 = 5 * 6 = 30

Ejercicio 7

El objetivo de este ejercicio es familiarizarnos con los mensajes de error del ensamblador. Muchas veces al producirse un error es difícil encontrar a qué es debido

Al introducir el programa en el simulador y ensamblarlo, obtenemos este error:

Es debido a una errata en los comentarios. En vez del símbolo #, se ha introducido ;. La línea correcta sería esta:

beq x17,x0,fin  #-- Comprueba terminacion

Lo mismo ha ocurrido en el otro comentario. En los ensambladores de otros microprocesadores, el símbolo ; se utiliza para introducir comentarios, pero en el RISC-V se usa #

El siguiente error es una errata al escribir la instrucción addi. La última i se ha duplicado

En la línea 8 hay otra errata. La x del registro x7 se ha duplicado

https://github.com/myTeachingURJC/2019-20-LAB-AO/raw/master/wiki/Soluciones-ejercicios/Sesion-1/ej-07-4.png

El último error es por la utilización de una etiqueta NO definida: hola. Debería ser a

Ahora lo podemos simular y comprobar qué es lo que hace: calcula los múltiplos de 8, en el registro x7. Saca 10 múltiplos, por lo que en realidad es la tabla de multiplicar del 8

Sesión 2

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

Ejercicio 1

  1. 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

  1. El programa tiene 5 instrucciones. Cada instrucción ocupa 4 bytes. Por tanto, su tamaño es de 5 * 4 = 20 bytes

  2. Tabla

Direccion (alineada) Instrucción en código máq.
0x00400000 00000293
0x00400004 00000313
0x00400008 00128293
0x0040000c 00530333
0x00400010 ff9ff06f
  1. Tabla
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
  1. El valor obtenido es de 325

Ejercicio 2

  1. Este es el programa que calcula la suma de los enteros pares
#-- 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
	b bucle
  1. 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

  2. Tiene 5 instrucciones. Cada instrucción ocupa 4 bytes. El tamaño que ocupa es de 5 * 4 = 20 bytes

  3. 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
  1. El valor obtenido es: 650

Ejercicio 3

  1. Programa que calcula la sucesión de Fibonacci:
#-- 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
	
	b bucle
  1. 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)

  2. Esta implementación del programa tiene 6 instrucciones. La tuya puede tener un número diferente

  3. Como tiene *6 instrucciones, y cada instrucción ocupa 4 bytes, el tamaño del programa es de 6 * 4 = 24 Bytes

  4. 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
  1. 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

Ejercicio 4

## 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
	ecall

Para el valor de las variables a=2, b=4, c=6, d=8, e=10, se obtiene que f = 23

Ejercicio 5

  1. 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*x5

El 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

  1. 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

  2. El resultado es 43

  3. 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

  1. El programa tiene 13 instrucciones. Cada instrucción es de 4 bytes. Por tanto ocupa 13 * 4 = 52 bytes

Ejercicio 6

  1. 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
  1. 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! :smile:

  1. 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

  1. 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

Ejercicio 7

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

Ejercicio 8

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

Ejercicio 9

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

Ejercicio 10

#-- 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
	b bucle

En la decima iteracion, los valores iniciales son:

a=10,
b=11,
c=12,
d=13

El valor calculado es -5, que es correcto

Sesión 3

Solución a los ejercicios de la Sesión de laboratorio 1-3

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