Bitácora C1 16/06/2015

Memoria Caché

La memoria caché es una memoria intermedia (entre la uc y la memoria principal) donde se guardan los valores o instrucciones mas accedidas. Se compone de celdas de almacenamiento que reciben el nombre de líneas (slots, ranuras). Una línea almacena un bloque de celdas de memoria principal y un tag (etiqueta)  que permite identificar al bloque.
Los bloques son divisiones conceptuales de las celdas de memoria. Por ejemplo, si tenemos una memoria principal de 256 celdas (8 bits de dirección) y una memoria caché con bloques de 4 celdas, entonces se usarán 6 bits como tag de los bloques y los 2 bits restantes se usarán como índice al querer acceder a una celda dentro del bloque almacenado en la línea de caché.
Cómo funciona:
  Para lectura de celda de memoria:
  1. La unidad de control pide el contenido de una celda.
  2. La caché verifica si tiene el contenido de esa celda. Para hacerlo, verifica que tenga guardado el bloque en el que se encuentra esa celda. Si no lo tiene (ocurre un fallo), le pide a la memoria principal el bloque y lo almacena junto con un tag que indica el número de bloque.
  3. Finalmente, es la caché la que devuelve el valor. Tomando el bloque, accede al valor de la celda a través del índice o palabra. Éste lo saca de los últimos bits de la dirección de memoria solicitada.
Para escritura en celda de memoria:
  1. La unidad de control pide una escritura de un valor en una celda de memoria.
  2. La caché verifica si está cacheada. Si no lo está, cachea el bloque correspondiente y luego lo actualiza.
  3. La caché pide la escritura del valor en la celda de memoria.

Función de correspondencia completamente asociativa

En una caché con esta función de correspondencia, cualquier bloque puede estar en cualquier línea y por lo tanto se necesita tener un tag que identifique absolutamente el contenido de esa línea.

Para verificar si una celda de memoria está cacheada, la memoria caché compara el tag de cada línea con la dirección enviada desde la UC (o parte de esa dirección), y lo hace de manera simultánea. Esta simultaneidad requiere que esté implementada con circuitos comparadores para cada línea, característica que puede resultar costosa. Existen otros enfoques (otras funciones de correspondencia) que mejoran este aspecto, pero que sacrifican otros, y que describiremos en la próxima bitácora…

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.

Bitácora C1 26/05/2015

Repaso de la clase pasada.

Vimos que la matisa puede ser entera o fraccionaria. Si queremos usar una mantisa fraccionaria de 4 bits con 1 bit implicito, donde 3 de sus bits son fraccionarios entonces la expresamos como:

SM(4+1,3)
Por ejemplo, usando el ejemplo anterior la cadena 0100 corresponde al número 2,5 ya que agregando el bit implícito nos quedaría la cadena 10100 y los últimos 3 bits son los fraccionarios.

IEEE 754

IEEE 754 es el estándar que fue creado para representar puntos flotantes. Define 2 maneras de representar un número:

Precisón simple y Presición doble.
Presición simple (32 bits): Signo – exponente – mantisa
S(1) – Exc(8,127) – SM(23+1, 23)
Presición doble (64 bits): Signo – exponente – mantisa
S(1) – Exc(11,1023) – SM(52+1,52)
Estas representaciones siguen determinadas reglas según la composición de sus partes:

Clases de números en IEEE 754

1) Normalizados:

  – exponente puede ser cualquier valor menos 00..00 y 11..11
  – mantisa es fraccionaria con bit implícito entero(o sea, 2^0)
Ejemplo en presición simple:
  0080000F = 2^-126
 Ya que 0080000F = 0000 0000 1000 0000 0000 0000 0000 1111
En negrita se ve resaltado el exponente.
Pasamos a analizar el signo (el primer bit) -> 0 -> positivo
Interpretamos mantisa (agregamos al bit implícito entero al comienzo)-> I(1000 0000 0000 0000 0000 1111) = 2^0 + 2^-20 + 2^-21 + 2^-22 + 2^-23
Interpretamos exponente -> I[Exc(8,127)](00000001) = -126

2) Cero

  Representa al valor 0
  – exponente debe ser 00..00
  – mantisa debe ser 00..00
Casos posibles: 00000000 y 80000000

3) Infinitos

  Representa al valor infinito (al positivo y al negativo)
  – exponente debe ser 11..11
  – mantisa debe ser 00..00
Casos posibles: 7FB00000 y FFB00000

4) NaN (Not a number)

  Representa valores que no se pueden representar. Comúnmente se utiliza para expresar errores.
  – exponente debe ser 11..11
  – mantisa debe 00..00
Ejemplo: 7FB00001

5) Desnormalizados

  Representa valores en el rango (-1,1) excluyendo al 0.
  – exponente debe ser 00..00 y vale 126
  – mantisa debe diferente de 00..00, y es fraccionaria con bit implícito igual a 0
Ejemplo: 0000000F

Práctica

Finalmente hicimos práctica con ejercicios de rango, resolución mínima y máxima. A prácticar este tema! Recuerden que la resolución mínima es la mínima distancia que puede haber entre 2 valores representables por nuestro sistema, y resolución máxima es la máxima distancia.
Se viene una entrega!
A saber: A no dormirse con IEEE que se complica el tema!

Bitácora-C1-12/05/2015

Repasamos punto fijo y su interpretación.
Luego vimos como representar:
  • Dado un número x a representar, operamos x*2^n donde n es la cantidad de bits fraccionarios de la cadena a representarla.

Por ejemplo, en BSS(7,3): R(5,75 * 2^3) => R(46) => 0101110
Para asegurarnos que lo hayamos hecho bien, podemos interpretar el resultado y ver que efectivamente BSS(4,3)-I(0101110) = 5,75

¿Cómo representaríamos el 0,3 en BSS(5,2)?
R(0,3) => R(0,3 * 2^2) => R(1,2) => R(1) => 00001
¿Por qué pasamos de 1,2 a 1? Porque hicimos un redondeo. Cuando calculamos la forma de representar el punto flotante, buscamos la unidad que es resultado de la multiplicación (en este último caso es el 1,2). Vemos que BSS(3,2)-I(00001) = 0,25.
Al querer representar el 0,3 obtuvimos el 0,25. Esto es por el redondeo justamente.
Entonces, si tenemos 2 bits para parte fraccionaria, ¿qué fracciones podemos representar?
Tomando el 1 por ejemplo como unidad, podemos representar el 1,00 – 1,25 – 1,50 – 1,75. Vemos que la diferencia mínima entre dos números con 2 bits fraccionarios es de 0,25.
Error absoluto: Es la diferencia entre el número que queremos representar y su representación. Por ejemplo, en el ejemplo anterior el error absoluto de 0,3 es 0,05 ya que el número que representamos (0,25) está a 0,05 de diferencia del numero a representar (0,3). Asimismo, el error absoluto de 0,2 también será 0,05.
Finalmente resolvimos entre todos el último parcialito y vimos los problemas que ocurren por no leer bien el enunciado antes de resolverlo.
Importante:
  • Sobre el parcial: Es el próximo martes y se tomarán todos los temas vistos hasta el momento (hasta error absoluto). Será a carpeta cerrada. NO se podrá usar celular ni ningún otro dispositivo electrónico similar. Se puede usar calculadora.
  • LEAN BIEN el enunciado del parcial.
  • Los miércoles de 14 a 15 Mara estará para consultar en la oficina.
  • Fede Martinez mandó por correo un parcial viejo que pueden resolver para practicar.

Bitácora-C1-05/05/2015

Motivación

Comenzamos trabajando con un hipotético sistema de cadena decimal de un dígito.
Entonces, los dígitos con los respectivos valores que interpretan son:
Cadena: 0    1    2    3    4    5    6    7    8    9
Valor:     0    1    2    3    4   -5   -4   -3   -2   -1
ruedaVemos que el rango es [-5, 4]
Lo interesante es que al sumar dos cadenas, la cadena resultante representa el valor correcto. Por ejemplo, 3 + 6 = 9. Si interpretamos esta expresión nos queda 3 + (-4) = (-1) lo cual es correcto.
Si a este sistema lo pasamos a cadena binaria de 3 dígitos nos quedará:
Cadena: 000 001 010 011 100 101 110 111
Valor:       0     1     2     3    -4    -3    -2    -1
ruedabinariaVemos que el rango es [-4,3]. Recordando que SM(3) tiene rango [-3,3], vemos que hemos ganado un valor representable (ya que tenemos una única cadena para el valor 0).

Complementación de cadenas:

Dada una cadena, si queremos obtener su complemento (cadena de misma magnitud, diferente signo) deberemos de seguir estos pasos:
  1. Invertir bits
  2. Sumar 1
Entonces, dada la cadena 001 (que representa al 1), su complemento será:
  1. Invertimos bits: 001 –> 110
  2. Sumamos 1:     110 + 1 –> 111

Efectivamente, la interpretación de 111 es (-1), que es el complemento del 1.

Interpretación

  • ¿Cómo interpretamos una cadena que empieza con 0 en CA2? Simplemente como veníamos interpretando en BSS.
    si C comienza con 0 entonces Ica2(C) = Ibss(C)
  •  ¿Cómo interpretamos una cadena que empieza con 1 en CA2? Una manera es interpretando su complemento y luego multiplicarlo por (-1) (cambiarle el signo).
    si C comienza con 1 entonces Ica2(C) = -(1) x Ibss(comp(C))

Representación

  • ¿Cómo representamos un número positivo en CA2? Simplemente como se representa en BSS. Ojo con el rango!
    si x>=0 entonces Rca2(x)= Rbss(x)
  •  ¿Cómo representamos un número negativo en CA2? Para utilizar el mecanismo de representación conocido (BSS), debemos tomar su opuesto (o valor absoluto) y luego complementar la cadena resultante.
    si x<0 entonces Rca2(x)=comp( Rbss( |x| ) )

 Para el viernes:

  1. Investigar sobre el sistema de numeración Exceso.
  2. Revisar las practicas y completar el siguiente formulario.

Bitácora-C1-28/04/2015

Comenzamos con un ejercicio individual con entrega. Éste fue tomado de un parcial anterior. Notamos muchos problemas generales a la hora de resolverlo. ¡A practicar y sacarse las dudas!
Luego a la teórica:

SM (Signo magnitud)

  ¿Cómo expresamos un número negativo?
En Q3 un número lo representaremos con una cadena de bits donde el primer bit representará al signo (0 para positivo, 1 para negativo). El resto de la cadena representará la magnitud de la cadena, es decir, el valor del número sin el signo (su valor absoluto).
O sea, la cadena 0011 es el número 3 y 1011 el número 3 ya que lo interpretamos como 1*(-1) + 0*2^2 + 1*2^1 + 1*2^0.
Entonces, ¿cuál es el rango de un SM(3)? El número más grande que podemos expresar es aquel positivo que tenga el mayor absoluto. Como el primer bit es el que usamos para el signo, los otros 2 bits nos quedarán como magnitud. Entonces, la cadena magnitud 11 es la de mayor valor que vamos a poder escribir, lo que nos quedaría junto con el signo en la cadena 011 (o sea, el 3). De esta misma forma, la cadena 111 será la más chica (o sea, el -3).
Las cadenas (con su interpretación) de menor a mayor nos quedarían:
111 (-3)
110 (-2)
101 (-1)
000 (0)
001 (1)
010 (2)
011 (3)
Luego vimos cómo sumar números con signo (tomando en cuenta si ambos operandos tienen o no diferente signo). Recordar: si los operandos tienen el mismo signo podemos sumar normalmente, maneteniendo el signo. Si son de diferente signo podemos hacer la resta entre el número de mayor magnitud y el de menor, así obteniendo el resultado con el signo del primero (de mayor valor absoluto). Al final notamos que ahora cualquier resta en bits la podemos transformar en una suma. O sea, 2 – 3 puede también ser 2 + (-3).
En la segunda parte de la clase estuvimos practicando ejercicios.
A tener en cuenta: Al final de la clase notamos que dejaron sucia el aula, con muchos papeles abandonados. Recuerden que deben dejar limpio el aula! Para la próxima clase los profes estarán atentos a los infractores.

Bitácora-C1-24/04/2015 (Pila y Q3)

Comenzamos la clase con consultas de la practica anterior, y luego se les pidió a los alumnos que en un «post-it» escribieran como creían que funcionaba el CALL y el RET.

Luego se pasó a explicar los siguientes temas:
  • Q3
  • Nueva estructura de datos: Pila
    • La pila esta guardada en una parte especial de la memoria.
    • Nos sirve para apilar y desapilar cosas
    • La operación PUSH nos permite apilar, es decir, agregar un elemento a la pila
    • La operación POP nos permite desapilar, es decir, sacar el ultimo elemento agregado a la pila.
    • El Stack Pointer (SP) nos «dice» cual es el tope de la pila.
  • Implementación del CALL y el RET: El CALL y el RET funcionan utilizando la Pila para guardar la dirección del PC, o bien, para darle una dirección guardada al PC, por lo tanto, en su implementación se usan las operaciones que permiten manejar la Pila
    • El CALL utiliza la operación PUSH, escribiendo un valor en la Pila
    • El RET utiliza la operación POP, leyendo el ultimo valor de la Pila
Para resolver los ejercicios en los que se tiene que realizar un cuadro que muestra como varía el PC, el SP, y la Pila, les recomendamos utilizar la siguiente notación:

Nótese que el PC puede tener dos estados diferentes, uno después de la búsqueda de instrucción y uno después de la ejecución de la instrucción, pero el SP y la Pila no, solo van a cambiar cuando se ejecute la instrucción y solo si la instrucción modifica la Pila, es decir, si la instrucción es CALL o RET.

Este es un ejemplo del cuadro utilizando la notación mencionada anteriormente: main empieza en 1000, rut1 en A0A0, el PC inicial es 1000, la Pila esta vacía.

rut1 : MOV R3, R2
       RET
main: CALL rut1

Para la próxima clase:

¿La arquitectura Q3 permite representar/operar con números negativos?
Si tu respuesta es Si: hacer un programa que inicialice R0 con el valor -1
Si tu respuesta es No: Proponer un mecanismo para extender Q3 y poder hacerlo

Bitácora-C1-21/04/2015 (Rutinas)

Comenzamos con la entrega de parcialitos, repartiéndolos entre los compañeros para que cada uno corrija el de otro.
Resolvimos en grupo ejercicios:
    a) Pensar un programa que calcule: R6 = (95+R1)*18 + R1/(R2+256)
    b) Hacer un programa que calcule n^5 para los números en las celdas A001, A002 y A003 y lo guarde en la misma celda.
Notamos que el primer ejercicio lo podíamos ver como 2 cuentas que se resuelven por separado y luego se suman y el segundo ejercicio como una serie de instrucciones prácticamente idénticas que teníamos que realizar 3 veces (una vez para cada celda).
Entonces, cada una de estas tareas intermedias podemos considerarla una subrutina de nuestro programa.
De esta forma los ejercicios nos quedarían:
    a)
        MOV R3, R1
        ADD R3, 0x005F
        MUL R3, 0x0012
        MOV R4, 0x0100
        ADD R4, R2
        MOV R5, R1
        DIV R5 R4
        MOV R6, R3
        ADD R6, R5
b)
        MOV R1, [0xA001]
        MUL R1, [0xA001]
        MUL R1, [0xA001]
        MUL R1, [0xA001]
        MUL R1, [0xA001]
        MOV R1, [0xA002]
        MUL R1, [0xA002]
        MUL R1, [0xA002]
        MUL R1, [0xA002]
        MUL R1, [0xA002]
        MOV R1, [0xA003]
        MUL R1, [0xA003]
        MUL R1, [0xA003]
        MUL R1, [0xA003]
        MUL R1, [0xA003]
Al separar el programa en partes lo estamos modularizando.
Vemos que el ejercicio b) tiene mucho código repetido (o muy similar). Podemos crear una subrutina más genérica y reusarla para no tener que repetir instrucciones. Para hacerlo, le asignaremos una etiqueta y utilizaremos la noción de parámetros.
Entonces, podemos crear la (sub)rutina:
    elevarA5: MOV R0, R1
                    MUL R0, R1
                    MUL R0, R1
                    MUL R0, R1
                    MUL R0, R1
                    RET
 
Las rutinas etiquetadas deben finalizar con la instrucción RET.
Uso de rutina: Llamamos a una rutina por su etiqueta utilizando la instrucción CALL.
Entonces, el ejercicio b) nos quedaría:
    MOV R1, [0xA001]
    CALL elevarA5
    MOV [0xA001], R0
    MOV R1, [0xA002]
    CALL elevarA5
    MOV [0xA002], R0
    MOV R1, [0xA003]
    CALL elevarA5
    MOV [0xA003], R0
Para utilizar la rituna elevarA5 nos tuvimos que acordar cómo funcionaba o revisar el código para ver qué hacía, qué registros modificaba y dónde devolvía el resultado. De aquí surge la necesidad de documentar nuestro código (o sea, hacer aclaraciones sobre su funcionamiento).
Documentación / Contrato: Toda la información asociada a una rutina la documentamos. La separamos en los siguientes segmentos:
    Requiere: dónde se encuentran los parámetros, cómo y cuáles son       Modifica: Qué variables adicionales modifica
    Retorna: dónde se retorna el resultado
Vimos que también debíamos de especificar cuál es el propósito de nuestra rutina.
Sobre el final de la clase se trabajó con los ejercicios 8,9,11,12,13,14.
Atención con el ejercicio 13: Debemos saber si un número es par. Una forma de conseguir esto es viendo si el resto de la división por 2 es 0. Como no tenemos el operador que nos devuelva el resto, pueden utilizar una supuesta instrucción MOD para ello (que funcionaría como DIV pero devolviendo el resto en vez del cociente).
Luego, pueden crear ustedes mismos la rutina «resto» y cambiar el ejercicio anterior usando la misma.
Entonces, ¿cómo podríamos hacer un programa que calcule el resto? Para pensar. Están advertidos que no será tarea fácil.
Ayuda (Spoilers):
x = (x DIV y) * y + resto (donde DIV es el cociente de la división)
Más ayuda (Spoiler completo):
Si queremos saber el resto de 7 / 3, entonces debemos de calcular el resultado de la división entera de 7 / 3 (que es 2) y multiplicarlo con el divisor (que es 3). Entonces, nos queda 2 * 3 => 6. La diferencia entre este resultado y el dividendo (que es 7) es el resto. O sea, 7 – 6 => 1. Volver a leer la primera ayuda para terminar de entender todo el proceso.

Bitácora-C1-17/04/2015

Se comenzó la clase con unos minutos para consulta de las prácticas

Se pasó a dar los siguientes temas:

  • Cambios en Q
    • Nuevo modo de direccionamiento: «Modo Directo»
  •  Revisión del ciclo de ejecucion de instrucción
    • Decodificación de las instrucciones
      • Registros especiales: Instruction Register (IR) y Program Counter (PC)
    • Busqueda de Operandos
    • Almacenamiento de Operandos
  • Accesos a memoria

Con lo visto en esta clase pueden y deben completar la Guía #3.

Bitácora-C1-14/04/2015

Comenzamos con una etapa de consultas.
Luego comenzamos a ver:
  • Memoria RAM
    • Qué es
    • Cómo funciona relacionada con lo que vimos hasta ahora (Unidad de Control)
    • Celdas de memoria
    • Tamaño de celda
    • Tamaño de memoria
  • Bus del sistema
    • Bus de direcciones
    • Bus de datos
    • Bus de Control
  • Registros
    • Repaso
    • Nuevos (de uso específico, no visibles al programador):
      • MBR (Memory Buffer Register)
      • MAR (Memory Address Register)
  • Q2
    • Se agregan funcionalidades a Q1
    • Nuevo modo de direccionamiento: Directo (la dirección de memoria se especifica entre [ ] en la instrucción)
  • Práctica 3: Ejercicios 2 y 3 entre todos, 4 a 6 en grupos
  • Conclusión: Hicimos un mapa conceptual con los conceptos vistos

Se recordó que debían completar todos los ejercicios de las prácticas anteriores.Para la próxima clase usaremos QSim.