miércoles, 25 de mayo de 2016

Desensamblemos (continuación): revolcándose en bits

Veamos cómo termina esta historia del "bajo mundo" binario. Habíamos llegado a desensamblar hasta aquí:

$C000 7F 00 03         CLR $0003
$C003 7f 00 04         CLR $0004
$C006 de 00            LDX $00
$C008 4F               CLRA
$C009 E6 00            LDAB 0,x
$C00B

y teníamos aun esta porción por procesar:

$C00B: d3 03 dd 03 08 7a 00 02 26 f3 20 fe

El procedimiento se repite: buscamos D3 en el set de instrucciones, en la columna de códigos de operación. 


Corresponde a la instrucción ADDD en modo directo, por tanto el byte que sigue es la parte baja de la dirección (dd). Completemos el programa:

$C000 7F 00 03         CLR $0003
$C003 7f 00 04         CLR $0004
$C006 de 00            LDX $00
$C008 4F               CLRA
$C009 E6 00            LDAB 0,x
$C00B D3 03            ADDD $03
$C00D

ya nos queda menos:

$C00D: dd 03 08 7a 00 02 26 f3 20 fe

Un par de comentarios: no debemos olvidar que las direcciones se expresan en hexadecimal, mucha atencn a eso. Tampoco debemos confundir los modos de direccionamiento. El modo directo permite expresar los operandos con la parte baja de su dirección real, asumiendo que la parte alta es 00. Por tanto en esta instrucción el operando se encuentra en $0003, pero expresamos solo $03, porque justamente lo que el modo directo permite es mantener implícito el $00 de la parte alta (que sería la página cero).
Continuemos, ahora tenemos el código de operación DD:
Sería la instrucción STD en modo directo. Así que el 03 que sigue es el operando. Eso significa que 08 es el siguiente código de operación, de la instrucción INX (modo inherente). Pasemos en limpio:
$C000 7F 00 03         CLR  $0003
$C003 7f 00 04         CLR  $0004
$C006 de 00            LDX  $00
$C008 4F               CLRA
$C009 E6 00            LDAB 0,x
$C00B D3 03            ADDD $03
$C00D DD 03            STD  $03
$C00F 08               INX
$C010 
ya nos queda menos:

$C010: 7a 00 02 26 f3 20 fe

El código de operación -CodOp- 7A lo encontramos en DEC para modo extendido. Así que los dos bytes siguientes son la dirección del operando (00 y 02). Por tanto 26 es un CodOp, el de BNE. Dado que los saltos operan solo en modo relativo, F3 es el offset del salto. Eso nos deja como siguiente CodOp 20, que corresponde a BRA. Por lo tanto FE es el offset de este último salto relativo. Completemos el programa:

$C000 7F 00 03         CLR  $0003
$C003 7f 00 04         CLR  $0004
$C006 de 00            LDX  $00
$C008 4F               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  $F3
$C015 20 FE            BRA  $FE
¡Desensamblamos el programa! Ahora nos faltan tres cosas:
  1. Asignar etiquetas de acuerdo a los saltos que pudieran existir
  2. Asignar nombres a las direcciones de memoria de los operandos.
  3. Discernir qué hace el programa 
Hay dos saltos: en $C013 aplica el offset $F3 y en $C015 el offset $FE. Hay al menos dos maneras de determinar a dónde salta. Primero necesitamos interpretar ambos números, vamos primero con F3. Expresémoslo en binario:

 F    3 
1111 0011

De un vistazo nos damos cuenta que es negativo, ya que el bit más significativo (el primero de la izquierda) es un uno. Para determinar su magnitud aplicamos entonces lo que sabemos sobre negativos en complemento a la base. Sumemos los pesos que tienen un uno en su posición, recordando como vimos en Cómo expresar negativos en Cb que el peso del más significativo es negativo. Sería:

       F            3 
    1  1  1  1    0 0 1 1   
-128 64 32 16        2 1

Aunque la cuenta parece horrible, no lo es (tanto). Comience sumando los dos primeros:
-128 + 64 = -64
siga con el tercero:
-64 + 32 = -32
el cuarto:
-32 + 16 = -16
y finalmente le sumamos 2+1
-16 + 3 = -13 
¿No fue tan difícil, no?

El valor que obtuvimos en decimal (-13) es lo que debiéramos aplicar al PC luego de leer la instrucción de salto (C015). Si su primera respuesta fue C002, le cuento que está mal porque C015 es una magnitud hexadecimal. Podemos hacer la cuenta en hexadecimal (-13 sería -D):

C015 - D =  C008. De modo que el salto apunta a la instrucción que hay en C008. Verificamos que en C008 hay un código de operación (porque si hubiera un operando algo hicimos mal):


   $C000 7F 00 03         CLR  $0003
   $C003 7f 00 04         CLR  $0004
   $C006 de 00            LDX  $00
-> $C008 4F               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  $F3
   $C015 20 FE            BRA  $FE

De modo que podríamos poner una etiqueta (por ejemplo "bucle" para no ser originales) en la dirección C008 y reemplazar BNE $F3 por BNE bucle:
 
   $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            BRA  $FE

Si hacer la resta en hexadecimal le resulta algo desafiante, puede contar los bytes, aprovechando que sobre el margen izquierdo está ensamblado. Cuente desde el C015 hacia atrás. En la imagen marqué los bytes de cada línea desde C015 y anoté la cantidad de bytes de cada una. 
Los 13 bytes hacia atrás (el salto F3 = -13) los debemos contar desde el valor que tendrá el PC después de la instrucción de salto. (Este es tal vez el punto más importante a comprender y recordar). Retrocediendo 13 bytes llegamos a C008, que es la posición en la que pusimos la etiqueta.

El segundo salto del programa es la última línea: BRA $FE. ¿Qué valor decimal está representado en Cb como FE? Pasemos FE a binario:
   F    E 
1111 1110

Sumando los valores de los pesos (nuevamente recordando que el MSB es -128), sería:
-128 + 64 +32 + 16 + 8 + 4 + 2 = -2.
Partiendo del valor C017 y restando llegamos a C015. Esto significa que el último salto apunta a sí mismo, es el clásico FIN BRA FIN del programa. Llegamos a esto:


   $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
En la próxima entrega intentaremos asignar nombres a las posiciones de memoria que usa el programa, intentaremos determinar qué hace, y veremos cómo cargarlo en el simulador.

1 comentario:

  1. Muy buena explicación profe,ahora si entendí como calcular os saltos.gracias

    ResponderBorrar

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