Você está na página 1de 14

Paolo Arrata 00124348

Organización de computadoras

22/03/2018

Proyecto 1

Antecedentes:

Para realizar este proyecto se utilizaron pseudo instrucciones de MIPS que SPIM las
implementa, por lo tanto estas no fueron analizadas en clase. A continuación, se va a dar una
pequeña explicación de estas y de cómo se utilizan.

Pseudo Operacion Significado Expandido en MIPS


Li $t, C load 16-bit addiu $t, $zero,
immediate/ load 32- C_lo
bit immediate
La $t, C load label address lui $t, A_hi
ori $t, $t, A_lo

Por lo general se utilizan estos códigos para hacer que una variable sea igual a un número
y posteriormente utilizar esta variable con los system calls, que se usaran para imprimir y guardar
los inputs del usuario.

Además, para la realización de este proyecto se realizó una investigación sobre diferentes
formas de aplicar las funciones en código assembly.

Serie de Fibonacci

Código y explicación del código con comentarios:

Explicación corta del funcionamiento:

El código funciona con dos data type para poner los strings que se van a imprimir en consola. Además, el
código tiene una estructura lineal en la que se hacen los system calls y se llama a la función Fibonacci.
Dentro de esta función se realizan las llamadas recursivas. En Fibonacci al principio de su sección se
aumenta el tamaño de la pila y se vuelve a llamar a sí misma la misma función, al final de la función
cuando se terminan las llamadas recursivas se llama a otra función en la que se liberan las posiciones de
la pila.
Codigo

.data
string1: .asciiz "Ingresa el numero para realizar fibonaci\n"
string2: .asciiz "El valor de fibonaci es:\n"
.text
# Imprimir string1
main:li $v0, 4
la $a0, string1
syscall

# leer input
li $v0, 5
syscall

# Guardamos el valor del input en $a0


addiu $a0, $v0, 0
#Llamamos a fibonacci
jal fibonacci
#guardamos el valor de fibonacci en $a1
addiu $a1, $v0, 0

# Imprimir string2
li $v0, 4
la $a0, string2
syscall

# Imprimir resultado
li $v0, 1
addiu $a0, $a1, 0
syscall

# Exit
li $v0, 10
syscall

fibonacci:
addi $sp, $sp, -12
sw $ra, 8($sp)
sw $s0, 4($sp)
sw $s1, 0($sp)
addiu $s0, $a0, 0
li $v0, 1

#comparacion para ver si estamos en el caso base


addi $t5, $zero, 0
addi $t5, $t5, 2
slt $t6, $t5, $s0
beq $t6, $zero, fibonacciExit

#cambiamos el argumento para n-1


addi $a0, $s0, -1
jal fibonacci #llamamos a fibonacci pero ahora es f(n-1)
#guardo el valor de f(n-1) a $s1
addiu $s1, $v0, 0
#cambiamos el argumento para n-1 f(n-2)
addi $a0, $s0, -2
#llamamos a f(n-2)
jal fibonacci
# sumamos el valor de f(n-1) a v0
add $v0, $s1, $v0

fibonacciExit:
# liberamos los espacios ocupados en el heap
lw $ra, 8($sp)
lw $s0, 4($sp)
lw $s1, 0($sp)
addi $sp, $sp, 12
jr $ra
#Termina función Fibonacci

Resultado:

1. Tamaño del segmento de código y datos de usuario

Segmento de código Datos de usuario


Posición inicial 0x00400000 0x10010000
Posición final 0x004000b8 0x10010040
Tamaño 0xB8 0x40
2. Mayor tamaño que tuvo la pila

Para la siguiente sección se correrá el programa con 7 como input.


Los siguientes datos son el valor que tiene $sp a lo largo del programa

Inicial 0x7ffff2cc 25 0x7ffff290 Final 0x7ffff2cc


2 0x7ffff2c0 26 0x7ffff29c
3 0x7ffff2b4 27 0x7ffff2a8
4 0x7ffff2a8 28 0x7ffff29c
5 0x7ffff29c 29 0x7ffff2a8
6 0x7ffff290 30 0x7ffff2b4
7 0x7ffff284 31 0x7ffff2c0
8 0x7ffff290 32 0x7ffff2b4
9 0x7ffff284 33 0x7ffff2a8
10 0x7ffff290 34 0x7ffff29c
11 0x7ffff29c 35 0x7ffff290
12 0x7ffff290 36 0x7ffff29c
13 0x7ffff29c 37 0x7ffff290
14 0x7ffff2a8 38 0x7ffff29c
15 0x7ffff290 39 0x7ffff2a8
16 0x7ffff29c 40 0x7ffff29c
17 0x7ffff290 41 0x7ffff2a8
18 0x7ffff29c 42 0x7ffff2b4
19 0x7ffff2a8 43 0x7ffff2a8
20 0x7ffff2b4 44 0x7ffff29c
21 0x7ffff2a8 45 0x7ffff2a8
22 0x7ffff29c 46 0x7ffff29c
23 0x7ffff290 47 0x7ffff2b4
24 0x 7ffff29c 48 0x7ffff2c0

Analizando los datos encontrados anteriormente encontramos que el valor más pequeño que tiene $sp
es 0x7ffff284, ya que la pila crece de forma descendente el valor más pequeño será en el punto en el
que este más grande. Por lo tanto, el tamaño máximo de la pila es: 6010 o 0x3c

3. Direcciones iniciales de los segmentos de código, datos y pila


Direcciones iniciales
Segmento de código 0x00400000
Segmento de datos 0x10010000
Pila 0x7ffff2cc
Torres de Hanoi

Código y explicación del código con comentarios:

Explicación corta del código:

Para este código se basó en un código hecho en c para entender el funcionamiento y luego transferirlo a
MIPS.

# codigo en c
# if (num_of_disks == 1)
# move disk to end_peg
# else
# hanoi(num_of_disks-1, start_peg, extra_peg, end_peg)
# move disk from start_peg to end_peg
# hanoi(num_of_disks-1, extra_peg, end_peg, start_peg)

Como se ve en el código anterior se observa que las llamadas recursivas son a la misma pero los
argumentos cambian. Por lo tanto, en el codigo se van cambiando los valores de $a0, $a1, $a2, $a3
antes de hacer las llamadas recursivas.

Además se tiene dos data types string , Move, y A, también ponemos al label mande forma global.
Después se realizan una serie de system calls para imprimir y recibir los valores de input. Se tienen dos
funciones una llamada Hanoi y otra llamada Else que implementan la misma lógica que el código en C
presentado anteriormente. Dentro de estas funciones se manipula constantemente los valores de las
variables de tipo $a y también se cambian las posiciones de la pila; con los valores de la pila se van
actualizando los datos de $a en las llamadas recursivas. Finalmente se tiene un control permanente
sobre el valor de $ra. El programa termina cuando se termina la primera llamada a hanoi.

Además, en este código se utiliza la pseudo instrucción “move” que equivale a addiu $s, $a,0. Utilizar
move es más intuitivo para entender el funcionamiento.

Código

.data

string:

.asciiz "\nIngrese el numero de discos: "

Move:

.asciiz "\nMover de torre "

A:
.ascii "a"

.globl main

.text

main:

#Print string

li $v0, 4

la $a0, string

syscall

#leo el input y lo pongo en #a0

li $v0, 5

syscall

add $a0, $v0, $zero

#$a1 = torre inicio

addi $a1, $zero, 1

#$a2 = torre final

addi $a2, $zero, 3

#$a3 = extra peg

addi $a3, $zero, 2

#llamamos a hanoi

jal hanoi

li $v0, 10

syscall
hanoi:

# codigo en c

# if (num_of_disks == 1)

# move disk to end_peg

# else

# hanoi(num_of_disks-1, start_peg, extra_peg, end_peg)

# move disk from start_peg to end_peg

# hanoi(num_of_disks-1, extra_peg, end_peg, start_peg)

# if (num_of_disks == 1)

addi $t0, $a0, 0 # temp save $a0

addi $t1, $zero, 1

bne $a0, $t1, else

#imprimo move

li $v0, 4

la $a0, Move

syscall

#imprimo la torre de origen

li $v0, 1

addiu $a0, $a1,0

syscall

#imprimo A

li $v0, 4
la $a0, A

syscall

#imprimo torre destino

li $v0, 1

addiu $a0, $a2, 0

syscall

#reinicio $a0

addi $a0, $t0, 0

#regreso

jr $ra

else:

#creo espacio en la cola y guardo las varialbes

addi $sp, $sp, -20

sw $ra, 16($sp)

#torre extra

sw $a3, 12($sp)

#torre final

sw $a2, 8($sp)

#torre de origen

sw $a1, 4($sp)

#guardo el número de discos

sw $a0, 0($sp)
#hanoi(num_of_disks-1, start_peg, extra_peg, end_peg)

#Establecemos las variables para la nueva llamada a hanoi

addi $t3, $a3, 0

# torre extra = torre final

addi $a3, $a2, 0

#torre final = torre extra

addi $a2, $t3, 0

#n--

addi $a0, $a0, -1

#llamada recursiva a hanoi

jal hanoi

#Cargo los valores de la cola

lw $ra, 16($sp)

lw $a3, 12($sp)

lw $a2, 8($sp)

lw $a1, 4($sp)

lw $a0, 0($sp)

addi $t0, $a0, 0

addi $t1, $zero, 1

# print move

li $v0, 4

la $a0, Move

syscall
# imprimo torre origen

li $v0, 1

addiu $a0, $a1,0

syscall

#imrimo A

li $v0, 4

la $a0, A

syscall

#imprimo torre fianl

li $v0, 1

addiu $a0, $a2 ,0

syscall

addi $a0, $t0, 0

#hanoi(num_of_disks-1, extra_peg, end_peg, start_peg)

#Establezco las variables para la siguiente llamada de hanoi

#como lo hice anteriormente

addi $t3, $a3, 0

addi $a3, $a1, 0

addi $a1, $t3, 0

addi $a0, $a0, -1

#Llamada recursiva a hanoi

jal hanoi

#Cambio el ra
lw $ra, 16($sp)

#Limpiamos el stack

addi $sp, $sp, 20

#return

add $v0, $zero, $t5

jr $ra

Resultado

1. Tamaño del segmento de código y datos de usuario

Segmento de código Datos de usuario


Posición inicial 0x00400000 0x10010000
Posición final 0x00400144 0x10010030
Tamaño 0x144 0x30

2. Mayor tamaño que tuvo la pila

Para la siguiente sección se correrá el programa con 3 como input.


Los siguientes datos son el valor que tiene $sp a lo largo del programa

Inicial 0x 7ffff2d4
2 0x 7ffff2c0
3 0x 7ffff2ac
4 0x7ffff2c0
5 0x7ffff2ac
Final 0x7ffff2c0
Analizando los datos encontrados anteriormente encontramos que el valor más pequeño que tiene $sp
es 0x7ffff2ac, ya que la pila crece de forma descendente el valor más pequeño será en el punto en el
que este más grande. Por lo tanto, el tamaño máximo de la pila es: 4010 o 0x28

3. Direcciones iniciales de los segmentos de código, datos y pila


Direcciones iniciales
Segmento de código 0x00400000
Segmento de datos 0x10010000
Pila 0x 7ffff2d4

Para la siguiente pregunta analizo los dos programas al mismo tiempo ya que de esa manera
se ven los datos relevantes de mejor manera.

1. Cualquier información relevante sobre los segmentos de código y datos del kernel.

Kernel data

Fibonacci Torres de Hanoi


Inicio Kernel Data 0x90000000 0x90000000
Final Kernel Data 0x900001f0 0x900001f0
Tamaño de Kernel 0x1f0 0x1f0

Con los datos recolectados podemos ver que los datos de kernel siempre empiezan en el mismo
lugar y tienen el mismo tamaño. Por lo tanto, sin importar que tipo de código se realice y de qué
tamaño tenga el mismo, el kernel data nos quitara 0x1f0 de posiciones disponibles para trabajar.

Datos de usuarios:

Realizando el código de Fibonacci tuve un error en la sitanxis del nombre donde primero escribí
como fibonaci y no Fibonacci. Pero esto me hizo darme cuenta de algo interesante en la forma
en la que guardan los user data en los registros del mips.
Registro 1 posición 2 posición 3 posición 4 posición
10010020

Con error 0x6f626966 0x6963616e 0x6c4500a 0x6c617620


Corregido 0x6f626966 0x6363616e 0x45000a69 0x6176206c

Como se puede ver en el grafico anterior y en los dos screenshots, el cambio de una “C” parece
pequeño, pero es significativo. En la segunda posición se puede ver la primera diferencia la cual
es de 0x0600000. Pero en la siguiente posición ya existe un cambio de dos posiciones en el valor
hexadecimal ma63616e s significativa. Y en las demás posiciones siguen apareciendo cambios.
Además, se observa que en mips los datos se los analiza no en base a su posición en el registro
es decir 10010020 o 10010040 sino en los bytes de los que están compuestos estos registros, ya
que en el registro 10010020 hay dos tipos de “.data” en la misma posición. Es decir, “Fibonacci”
es del string1 y “El va” es del string2.

Referencias
AaronFoltz. (9 de Agosto de 2011). Towers-of-Hanoi. Obtenido de
https://github.com/AaronFoltz/Tower-of-Hanoi/blob/master/hanoi.s

libertylocked. (17 de Febrero de 2017). Obtenido de


https://gist.github.com/LibertyLocked/068b118354539a8be992

Using XSPIM. (s.f.). Obtenido de http://www.cs.utexas.edu/users/mckinley/352/xspim/getstart.html