Bitácora C1 12/06/2015

Se comenzó la clase armando grupos de 2, en los cuales uno de los dos tenía que haber hecho la entrega del martes. (Aunque lo tendrían que haber hecho todos)

La consigna era que la persona que realizo la entrega tenía que explicarle al otro la manera de realizar el ejercicio, para que luego pasen al pizarrón a hacerlo.

El ejercicio era el siguiente: Calcular A*B se podría realizar sumando B veces el valor A (o viceversa). Pensándolo como un programa podría ser:

  • Inicializar un acumulador R en cero.
  • Verificar si B es cero.
  • Si B es cero, salir.
  • Asignar R ← R + A ; Recordemos que la primera vez R es cero
  • Asignar B ← B 1 – 1 ; Al ir restando 1 a B nos acercamos al final del problema
  • Volver al paso 2

Usando la siguiente documentación:
;Requiere: Valores a multiplicar en R1 y R2
;Modifica: ???
;Retorna: Resultado en R1

Y se lo podría resolver con una sub-rutina como la siguiente:

mult: MOV R1, 0x0000
volver: CMP R2, 0x0000
        JE salir
ADD R1, R2
SUB R2, 0x0001
JMP volver
salir: RET

Donde la primera linea cumple con la inicialización del acumulador, la segunda y tercera con la verificación del valor de «B» y la salida de la iteración si ese valor es 0, la cuarta linea se encarga de «Asignar R ← R + A», la quinta de «Asignar B ← B 1 – 1», la sexta linea nos hace volver al «paso 2» y la séptima linea es la salida de la rutina.

Analizando nuestra sub-rutina, se puede abstraer el concepto de iteración, que puede ser usado para resolver varios problemas similares, que requieran «repetir» pasos una cierta cantidad de veces, y nos quedaría un esquema abstracto como el siguiente:

Inicializacion
arriba: Controlar condición de ciclo
Si no se cumple: 
Cuerpo del ciclo
Volver 
salir: Finalizar programa

Luego, seguimos ejercitando el tema con otro ejercicio que sigue el mismo esquema abstracto:

Escribir y documentar una rutina que calcula el factorial del valor almacenado en R5. dicho valor está representado en BSS() . El factorial de un número n es el producto de los números enteros positivos desde el 1 hasta n. Por ejemplo, el factorial de 5 = 5*4*3*2*1

Si bien también nos sirve el mismo esquema de abstracción que para el ejercicio anterior, este ejercicio en particular requiere una «vuelta de tuerca»:

factorial: CMP R5, 0x0000
           JE esCero
           MOV R1, R5
           MOV R2, R5
           SUB R2, 0x0001
     comp: CMP R2, 0x0001
           JE fin
           MUL R1, R2
           SUB R2, 0x0001
           JMP Comp
   esCero: MOV R1, 0x0001
      fin: RET

;Requiere: En R5 el valor al cual se le va a realizar el factorial
;Modifica: R1, R2, R7
;Retorna: En R1 el valor del factorial del valor de R5

Si bien sigue el esquema (A pesar de que la inicialización es bastante más amplia), tenemos el problema de que «0! = 1″, por lo que lo tenemos que tratar como caso aparte, ya que sino no vamos a poder calcularlo con un MUL (porque » 0 * x = 0 » para todo x).

Luego se siguió con un tema nuevo, Arreglos, y para hablar de Arreglos también necesitamos hablar de unos nuevos modos de direccionamiento: «Modo Indirecto» y «Modo Registro Indirecto».

Estos nuevos modos de direccionamiento nos permite utilizar el valor de un registro o una celda de memoria, es decir, el «dato» que se encuentra adentro del registro o la celda de memoria, como una dirección de memoria para ir a buscar el operando. Se lo nota agregando «[ ]» al registro o a la celda, por ejemplo, en esta instrucción se utiliza el modo de direccionamiento «Registro Indirecto»:

Suponiendo que dentro de R2 se encuentra el valor 0x0001 y dentro de la celda 0x0001 se encuentra el valor 0x0002:

ADD [R2], 0x0003

En esta instrucción se suma el valor dentro de la celda con dirección igual al valor dentro de R2, que es 0x0001 con el valor 0x0003.

De la primera parte tenemos que ir a buscar el operando a la celda 0x0001 (valor = 0x0002) y de la segunda parte tenemos el operando 0x0003, y luego hacemos la suma con estos dos operandos:

0x0002 + 0x0003 = 0x0005

Y luego, ese resultado se almacena en dentro de la celda con dirección igual al valor que se encuentra en R2, ósea, 0x0001.

Por lo que luego de la ejecución del programa nos quedan los valores así:

R2 = 0x0001

[0x0001] = 0x0005 (esta es la única celda alterada)

Y podríamos cambiarlo para usar el modo «Indirecto» cambiando [R2] por [[0x0001]] por ejemplo, por lo que tendríamos que ir a buscar nuestro «primer» operando a otra dirección de memoria, y esa dirección de memoria la conseguimos buscando el valor dentro de la celda 0x0001, dentro de esta celda se encuentra el valor 0x0002, por lo que luego tenemos que ir a la celda 0x0002 para conseguir nuestro operando. Supongamos que en la celda 0x0002 se encuentra el valor 0x0003.

Entonces tenemos los dos operandos, 0x0003 (de la celda 0x0002) y 0x0003 (de nuestra instrucción, dado que era modo «Inmediato»)

0x0003 + 0x0003 = 0x0006

Y luego, nuestro destino es [[0x0001]], por lo tanto, como en el ejemplo anterior, tenemos que guardarlo en la celda que tenga la misma dirección que el valor que se encuentra dentro de la celda 0x0001 (el valor es 0x0002), por lo tanto, el resultado se guarda en la celda 0x0002, nuestro resultado «final» es:

R2 = 0x0001

[0x0001] = 0x0002

[0x0002] = 0x0006 (es la única celda alterada)

Ahora… Para qué nos sirve todo esto? Si al final terminamos dando mil vueltas para conseguir un operando…

Estos modos nos permiten «recorrer» un Arreglo.

Ahora… Qué es un Arreglo? y para qué me sirve?

Un Arreglo es una colección de elementos contenidos en celdas consecutivas. Cada elemento del Arreglo puede ocupar 1 celda o más, pero TODOS los elementos deben ocupar la misma cantidad de celdas, es decir, si el primer elemento ocupa 3 celdas, TODOS los siguientes deben ocupar también 3 celdas.

De un Arreglo se necesitan saber 2 cosas:

  1. Cuantas celdas ocupan sus elementos.
  2. Donde termina el Arreglo.

Para saber donde termina el Arreglo tenemos dos opciones:

  1. Saber cuantos elementos tiene el Arreglo.
  2. Tener una condición de fin para el Arreglo. Por ejemplo, el Arreglo termina cuando encuentra una celda que contenga todos ceros (0x0000).

Veamos un ejemplo:

Ahora, Cómo sumo todos los valores dentro de celdas consecutivas? Acá es donde nos sirven los modos de direccionamiento que antes vimos (y los loops :D).

Si yo tengo dentro de R1 el valor de la primera celda del arreglo, entonces con el modo «Registro Indirecto» puedo acceder al primer pedido de empanada, y si quisiera acceder al siguiente pedido de empanada tendría simplemente que sumar 1 a R1, para que contenga el valor de la siguiente celda de arreglo, y así hasta que encuentre una celda que contenga el valor 0… esto es muy parecido a lo que hicimos al principio de la clase, las iteraciones, por lo que puedo usar el esquema abstracto que conseguimos:

calcularPedidos: MOV R1, 0xA000
                 MOV R2, 0x0000
       comparar: CMP [R1], 0x0000
                 JE fin
                 ADD R2, [R1]
                 ADD R1, 0x0001
                 JMP comparar
            fin: RET

;Requiere: Un Arreglo que comience en 0xA000, con elementos de 1 celda.
;Modifica: R1, R2
;Retorna: En R2 la suma de todos los elementos del Arreglo.

Donde las primeras dos lineas son para inicialización (R1 es nuestro «puntero del Arreglo», es decir, nos indica que celda del arreglo estamos usando, y R2 es nuestro acumulador, donde va a quedar nuestro resultado), en la tercera y cuarta linea nuestro «condicional», en las dos celdas que siguen el cuerpo de nuestra iteración y luego la vuelta a la condición y el fin.