sábado, 28 de mayo de 2016

Desensamblando (conclusión): armemos el rompecabezas binario

Llegamos a la tercera parte de esta novela de romance y bits. ¿Que dónde está el romance? Mmm... ¿no lo viste? Seguí practicando hasta que veas la danza binaria entre acumuladores...

Este es el programa desensamblado:

   $C000 7F 00 03         CLR  $0003
   $C003 7f 00 04         CLR  $0004
   $C006 de 00            LDX  $00
   $C008 4F       bucle   CLRA
   $C009 E6 00            LDAB 0,x
   $C00B D3 03            ADDD $03
   $C00D DD 03            STD  $03
   $C00F 08               INX
   $C010 7A 00 02         DEC  $0002
   $C013 26 F3            BNE  bucle
   $C015 20 FE    fin     BRA  fin

Con esto nos podemos dar una idea de cuál es su propósito, pero el trabajo aun no termina: había una porción de memoria que aun no procesamos:

$0000: 00 06 05 01 02 03 04 99 54 65 32  

Además en el programa estamos usando direcciones de memoria para acceder los operandos cuando quedaría más prolijo y claro utilizar etiquetas. En primer lugar veamos cómo deducir el tamaño y cantidad de los operandos:

Las instrucciones con operandos de 8 bits están marcadas en rojo. Las que manejan operandos de 16 en azul. ¡Cuidado! No debemos confundir operandos de 8 o 16 bits con direcciones de 8 o 16 bits. En modo directo solo manejamos la parte baja de la dirección, o sea 8 bits de ella, y en modo extendido los 16 bits de la dirección. Pero, podemos emplear modo directo y trabajar con 16 bits (por ejemplo, ADDD $03) o trabajar en modo extendido y operar con 8 bits (por ejemplo DEC $0002).
Empecemos con las marcadas en azul, las de 16 bits. Se carga IX con lo que hay en $0000 (es modo directo, por tanto la dirección completa es $0000). Podemos por tanto determinar que en $0000 hay una dirección de 16 bits, llamémosla dir1. 
También se realiza una suma de 16 bits con almacenado en $0003 (por lo tanto ocupa $0003 y $0004). Ahí tenemos un operando de 16 bits, podemos llamarlo double1.
Nos quedan los operandos de 8 bits. Pero observe que aunque los dos primeros CLR del programa trabajan en 8 bits, realmente se está limpiando el double1 en mitades.
Queda entonces la carga del elemento apuntado por IX, que se realiza leyendo 8 bits y cargándolo en el acumulador B. Por tanto lidiamos con un vector de elementos de 8 bits.
El último operando de 8 bits es el que utilizamos con la instrucción DEC $0002. Llamémosle byte1. Note que luego de cada decremento se verifica si llegó a cero, y en caso de que eso no ocurra se repite el bucle. De esto se desprende que se trata de un contador, que inicialmente contendría la cantidad de elementos del vector.
Pasemos en limpio las reservas de memoria y comparémoslo con el contenido de la memmoria a partir de $0000:


$0000 00 06     dir1    RMB   2 <- direccion inicial del vector
$0002 05        byte1   RMB   1 <- cantidad de elementos del vector
$0003 01 02     double1 RMB   2 <- ¿ya te diste cuenta?
$0005 03 04 99 54 65 32         

La dirección inicial del vector es $0006 ¿qué hay en la dirección $0005? Solo una posición de memoria sin usar. Llamémosle caza pichones. Lo mismo aplica al contenido inicial de double1. El vector tiene los elementos (04,99,54,65,32), ya que la dirección dir1 y la cantidad byte1 así lo marcan.

Empleando los nombres de los símbolos nos queda esto:

   $C000 7F 00 03         CLR  double1
   $C003 7f 00 04         CLR  double1 +1
   $C006 de 00            LDX  dir1
   $C008 4F       bucle   CLRA
   $C009 E6 00            LDAB 0,x
   $C00B D3 03            ADDD double1
   $C00D DD 03            STD  double1
   $C00F 08               INX
   $C010 7A 00 02         DEC byte1 // cantidad
   $C013 26 F3            BNE  bucle
   $C015 20 FE    fin     BRA  fin
 

Queda la frutilla del postre: ¿qué hace el programa? Tomese un momento para repasar:
Sabemos que: 
  • procesa un vector de elementos de 8 bits, del que se conocen dirección inicial y cantidad de elementos
  • efectúa una sumatoria en 16 bits
  • guarda un resultado de 16 bits
Tal vez el único detalle hasta ahora no esclarecido es que los elementos se leen en 8 bits en el AccB y justo antes se limpia AccA, de esta forma cada operando de 8 bits se puede manejar como de 16. En lenguaje C hablaríamos de un cast.
¡Resuelto! Tomó un rato pero lo logramos.

Uso de THRSim para desensamblar

¿Cómo podríamos utilizar el simulador para verificar que estamos en lo correcto? Relativamente fácil: utilice la opción Memory Dump para cargar las dos porciones de memoria provistas inicialmente. Tendría que quedar así (combiné dos capturas de la ventana Memory Dump):

Paso importantísimo: verifique el valor del PC, debiera ser $C000. Ahora vamos al menú View -> Dissassemble:

Se presentará entonces esta ventana:

¡Así es mucho más fácil! Un detalle para tomar en cuenta: el THRSim presenta la dirección de destino junto a los saltos (BNE y BRA) pero no inventa ninguna etiqueta. 

Pan comido, no?

4 comentarios:

  1. Buenas profe.
    Intente primero resolver el ejercicio con lo visto en clase y después verificarlo leyendo el resto del blog. Me salio (gran explicacion)y estuvo bueno verificarlo (acá también era todo muy entendible), pero no tuve en cuenta esta ultima parte. Como las otras dos partes muy bueno! Pero le pido me de una mano mas XD
    me quede con dos dudas: -¿como entender que el vector empieza en la pos &06? y -¿Como se que LDX es de 16 bits?
    Desde ya gracias!!
    - Ezequiel Otto Krause

    ResponderBorrar
  2. Hola Ezequiel! Gracias por tu comentario. LDX carga el registro índice IX. Dado que el registro índice tiene el tamaño del bus de direcciones, es de 16 bits. Fijate que el CodOp "DE" corresponde a LDX en modo directo, por lo tanto el campo de operandos es de 8 bits. Es el paginado a página 00 del HC11. Por lo tanto cargará IX con el contenido de la posición de memoria 0000 (justo el operando es cero tambien).
    Ahora bien, si en IX cargás lo que hay en 0000, y en esa posición tenes el valor 0006 (recordar que carga 16 bits, asi que el contenido de 0000 y 0001 van a parar a IX), entonces en definitiva IX se carga con 0006. Si luego recorre posiciones consecutivas de memoria partiendo de ese valor, entonces desde 0006 está el vector. Se entiende?

    ResponderBorrar

Aunque no es obligatorio, es de buena educación firmar los comentarios.