viernes, 11 de enero de 2008

Ensamblador (Entrega 2)

Lenguaje Ensamblador y Debug

Para comprender las tareas que realizamos en nuestros ejemplos, tomemos en cuenta brevemente las características y funciones del programa DEBUG. Este programa, fue creado para verificar errores en los programas. El término bug en inglés significa bicho y en informática significa errores de programa, debug es entonces, un quitabichos o quitaerrores. Sin embargo, por ser un programa que permite realizar operaciones de bajo nivel (es decir, trabaja sobre la arquitectura del sistema) ya que reconoce la estructura del microprocesador, los registros, posiciones absolutas de memoria, etcétera, puede ser usado en una variedad de aplicaciones. Normalmente, DEBUG se usa en forma interactiva, o sea que se ingresa la línea de comando DEBUG o DEBUG [nombre del programa] y luego se introducen las órdenes a debug desde dentro del programa, a continuación del símbolo - (un guión).

Por ejemplo podríamos escribir el comando DEBUG EDIT.COM con lo que podríamos observar, DEBUG mediante, el código de máquina del programa EDIT. Para iniciar la sesión, ingresamos el comando DEBUG y luego oprimimos ENTRAR. El primer comando de debug que usaremos será el signo de interrogación ?. Mediante este comando obtenemos por pantalla una lista de los comandos disponibles en debug y la descripción de su aplicación.




Fig. 1 Comandos de Debug

En nuestra entrega anterior presentamos el Ejemplo 1, en esta oportunidad incluiremos una nueva instrucción de debug y veremos como cargar un registro desde una posición de memoria.

Ejemplo 2: Cargar un registro desde una posición de memoria

C:\WIND>DEBUG
-E 104 5
-A 100
3902:0100 MOV AL,[104]
3902:0103
-G 100

AX=0000BX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000
DS=3902ES=3902SS=3902CS=3902IP=0100 NV UP EI PL NZ NA PO NC
3902:0100 A00401 MOV AL,[0104]
-P

AX=0005BX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000
DS=3902ES=3902SS=3902CS=3902IP=0103 NV UP EI PL NZ NA PO NC
3902:0103 3005 XOR [DI],AL
-

El primer comando que utilizamos es E (introducir) que permite cargar una posición de memoria con un valor (cargamos el valor 5 en la dirección 104). Luego, utilizamos el comando A (ensamblar) indicandolé la dirección 100 porque debug está posicionado en la dirección 104 y comenzaría a ensamblar en la dirección siguiente. Luego, ingresamos nuestra instrucción MOV AL,[104] que carga el contenido de la dirección 104 en el registro AL (observe que la dirección debe indicarse entre corchetes). Luego de ingresar la instrucción oprimimos INTRO para retornar al guión de debug. Utilizamos el comando G 100 para ir a la dirección 100 y detener la ejecución.

AX=0000BX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000
DS=3902ES=3902SS=3902CS=3902IP=0100 NV UP EI PL NZ NA PO NC
3902:0100 A00401 MOV AL,[0104]

Luego utilizamos el comando P (continuar) para ejecutar nuestra instrucción.

AX=0005BX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000
DS=3902ES=3902SS=3902CS=3902IP=0103 NV UP EI PL NZ NA PO NC
3902:0103 3005 XOR [DI],AL

Observe la última línea que muestra la dirección actual (103), ignore la instrucción XOR (es “basura”). Observe ahora el estado del registro AX y notará el valor 5, es decir que nuestra instrucción fue ejecutada exitosamente. Otro detalle a tomar en cuenta es que la dirección de comienzo en este ejemplo es 3902:0100 y si observa en detalle DS, que es el segmento de datos dice DS=3902. Mas aún, si realizan este ejemplo es sus PC notarán que el DS es diferente de 3902 (si obtienen el mismo número, corran hasta el bingo mas cercano...).

Note que en el Ejemplo 1, la instrucción MOV se convirtió en B8, mientras que en este caso, se convirtió en A0. La razón de esta diferencia radica en el hecho que se trata de dos instrucciones de máquina distintas, la primera consiste en un MOV de un valor consecutivo al registro AX, mientras que en este ejemplo, se trata de un MOV desde una posición de memoria RAM hacia el registro AX. Sin embargo, a pesar de estas diferencias, el programador solamente tiene que usar una sola instrucción mnemotécnica, el MOV.

Ejemplo 3: Cargar un registro desde otro registro

C:\WIND>DEBUG
-A
3902:0100 MOV DX,567
3902:0103 MOV AX,DX
3902:0105
-G 100

AX=0000BX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000
DS=3902ES=3902SS=3902CS=3902IP=0100 NV UP EI PL NZ NA PO NC
3902:0100 BA6705 MOV DX,0567
-P

AX=0000BX=0000CX=0000DX=0567SP=FFEEBP=0000SI=0000DI=0000
DS=3902ES=3902SS=3902CS=3902IP=0103 NV UP EI PL NZ NA PO NC
3902:0103 89D0 MOV AX,DX
-P

AX=0567BX=0000CX=0000DX=0567SP=FFEEBP=0000SI=0000DI=0000
DS=3902ES=3902SS=3902CS=3902IP=0105 NV UP EI PL NZ NA PO NC
3902:0105 8BFF MOV DI,DI
-

En este ejemplo comenzamos por cargar un registro (DX) con un valor constante (567), en la segunda línea ingresamos la instrucción que carga un registro (AX) desde otro registro (DX). Luego mediante el comando P vemos como se modifican los contenidos de los registros, primero el registro DX y luego el registro AX.

Tomen como guía estos ejemplos, los continúen el recorrido por los demás registros.

En la próxima entrega, estudiaremos el uso de interrupciones y cómo estas facilitan la tarea del programador.

Hasta la próxima,

Sergio Otaño

1 comentarios:

David dijo...

Veo que en DEBUG, con el comando R, le aparecen todos los caracteres seguidos "AX=0000BX=0000CX=...", cuando lo normal es que haya espacios en blanco entre los datos de unos registros y otros: "AX=0000 BX=0000 CX=...".

A mí también me sucede y no sé si es un problema de DEBUG o de la configuración del MS-DOS. La verdad es que es muy molesto trabajar así con DEBUG.