Está en la página 1de 30

El comando DEBUG

By Benji
Colima 2007 V3.0 Mxico





Un Poco de Historia

En 1980, Tim Paterson con 24 aos de edad, basndose en el CP/M (Control Program for
Microcomputers, escrito por Gary Kildall) comenz a trabajar en un Sistema Operativo llamado
QDOS (Quick and Dirty Operating System, sistema operativo rpido y sucio) para el
microprocesador 8086 de 16-bit incorporado en una tarjeta tipo S-100 que haba diseado para
SCP (Seattle Computer Products) un ao anterior. Para ayudar a conseguir que QDOS (ms
tarde llamado 86-DOS Disk Operating System, sistema operativo de disco) funcionara
correctamente, Tim cre un depurador en un chip ROM, la versin del cdigo se publico como
de dominio pblico. Ms tarde, Tim adapto el cdigo para que se ejecutara como un programa
.COM en el QDOS y tambin le aadi la posibilidad de desensamblar cdigo maquina del
8086. Mientras tanto, IBM haba encargado un sistema operativo para su IBM-PC a Microsoft,
al cual ya se le terminaba el plazo de entrega estipulado y no dispona an del software, por lo
cual Bill Gates y Paul Allen decidieron comprar los derechos por $50 000 dlares (primero una
licencia parcial y ms tarde una licencia completa) del sistema creado por Tim Paterson y
contrataron a ste (en mayo de 1981) para reescribir el QDOS y adaptarlo al microprocesador
usado en el IBM-PC, el 8088 de Intel. El resultado fue vendido como PC-DOS (Personal
Computer Disk Operating System) a IBM y ms tarde comercializado como MS-DOS (Micro
Soft Disk Operating System) a las computadoras clones que surgiran tras el xito de IBM-PC.

En la versin del DOS 1.00 de 1981, el programa DEBUG.COM se encuentra incluido como un
componente ms del DOS. Toda la funcionalidad que Tim pone en DEBUG est todava all y
poco se ha aadido a ella [1] .

Tim fue contratado por Microsoft en diversos periodos de su vida y trabaj en el desarrollo de
Visual Basic. Algn tiempo despus tambin recibi algunas acciones de la misma.
Actualmente tiene una compaa de hardware Paterson Tech.


Introduccin

El "DEBUG.EXE" es una utilidad de MS-DOS (Microsoft Disk Operating System) que permite
visualizar el contenido de la memoria, introducir programas en ella y rastrear su ejecucin. Una
caracterstica de DEBUG.EXE es que despliega todo el cdigo del programa en formato
hexadecimal. Otra utilidad es que se puede utilizar tambin para el desarrollo de pequeas
aplicaciones en ensamblador [2].

Usando DEBUG es posible observar el comportamiento de las instrucciones, la forma en cmo
stas afectan a las banderas, los contenidos de la memoria, el cdigo de las instrucciones;
adems permite ensamblar cdigo elemental usando los mnemotcnicos del 8086.


Nota: "Bug" significa fallo, defecto en un programa; "DEBUG" significa depurar
(escrutar y eliminar fallos). La palabra ha quedado como verbo (depurar), de la
que han derivado otras. Por ejemplo: "DEBUGger" (depurador). Por extensin,
todos los programas y utilidades que sirven para escudriar los datos y el cdigo
a bajo nivel, se identifican genricamente con esta denominacin.


Se trata de una utilidad interactiva de exploracin de bajo nivel, pero que tambin puede
utilizarse para ciertas funciones. Por ejemplo, como un rudimentario traductor de sentencias
ensamblador a lenguaje mquina. Como todos los programas de su tipo, debe utilizarse con
cierto cuidado. En especial si utiliza el comando W (se puede borrar todo un disco duro con un
simple comando errneo). Para utilizarlo basta invocarlo desde MS-DOS o desde una ventana
DOS de Windows. Aunque en este ltimo caso algunas de sus funcionalidades ms
interesantes no se pueden ejecutar (limitadas por Windows).

Como se dijo anteriormente, el DEBUG es un programa de utilera del Sistema Operativo DOS
y Windows; Es til para:


Ensamblar pocas lneas de cdigo ensamblador
Des-ensamblar cdigo en RAM, ROM y Archivos ejecutables
Correr paso-a-paso programas
Desplegar datos en memoria
Verificar estado de los registros del CPU



Nota: Es importante recordar que muchos usos de estas utilidades de bajo nivel,
requieren un funcionamiento stand-alone. Es decir, fuera de un Sistema
Operativo multiusuario, ya que stos encapsulan y ocultan (virtualizan) muchos
aspectos del hardware.


El Microprocesador 8088 tiene 14 registros internos, cada uno de 16 bits. Los primeros cuatro,
AX, BX, CX, y DX son registros de uso general y tambin pueden ser utilizados como registros
de 8 bits, para utilizarlos como tales es necesario referirse a ellos como por ejemplo: AH y AL,
que son los bytes alto (high) y bajo (low) del registro AX. Esta nomenclatura es aplicable
tambin a los registros BX, CX y DX.






Arquitectura del microprocesador 8088


El registro AX


Todos los registros ocupan dos bytes de longitud (16 bits). Los registros de propsito general
se pueden utilizar divididos en dos partes de un byte de longitud respectivamente, por
consiguiente, AX se divide en AH y AL, donde AL es la parte LOW o Baja del registro AX,
mientras que AH es la parte HIGH o parte Alta del registro AX.


AX
|------------------------|
11010110 10111000
AH AL


Si se almacena en AL un dato (de 8 bits por supuesto), la parte alta AH no se modifica y
viceversa.

Los registros son conocidos por sus nombres especficos:


AX Acumulador
BX Registro base
CX Registro contador
DX Registro de datos
DS Registro del segmento de datos
ES Registro del segmento extra
SS Registro del segmento de pila
CS Registro del segmento de cdigo
BP Registro de apuntadores base
SI Registro ndice fuente
DI Registro ndice destino
SP Registro del apuntador de la pila
IP Registro de apuntador de siguiente instruccin
F Registro de banderas








Registro AX
Este registro es el acumulador principal, implicado en gran parte de las operaciones de
aritmticas y de E/S.


Registro BX
Recibe el nombre de registro base ya que es el nico registro de propsito general que se usa
como un ndice en el direccionamiento indexado. Se suele utilizar para clculos aritmticos.

Registro CX
Es conocido como registro contador ya que puede contener un valor para controlar el nmero
de veces que se repite una cierta operacin.

Registro DX
Se conoce como registro de datos. Algunas operaciones de E/S requieren su uso, y las
operaciones de multiplicacin y divisin con cifras grandes suponen que el DX y el AX
trabajando juntos.

Registro CS
Registro Segmento de Cdigo. Establece el rea de memoria dnde est el programa durante
su ejecucin.

Registro DS
Registro Segmento de Datos. Especifica la zona donde los programas leen y escriben sus
datos.

Registro SS
Registro Segmento de Pila. Permite la colocacin en memoria de una pila, para
almacenamiento temporal de direcciones y datos.

Registro ES
Registro Segmento Extra. Se suele utilizar en algunas operaciones con cadenas de caracteres
para direccionar la memoria.

Registro SP
Proporciona un valor de desplazamiento que se refiere a la palabra actual que est siendo
procesada en la pila.

Registro BP
Facilita la referencia a los parmetros de las rutinas, los cuales son datos y direcciones
transmitidos va la pila.

Registro SI
Registro ndice fuente requerido en algunas operaciones con cadenas de caracteres. Este
registro est asociado con el registro DS.

Registro DI
Registro ndice destino requerido tambin en determinadas operaciones con cadenas de
caracteres. Est asociado al registro DS o ES.

Registro Apuntador de Instrucciones (IP).
Se trata de un registro de 16 bits que contiene el desplazamiento de la direccin de la siguiente
instruccin que se ejecutar. Est asociado con el registro CS en el sentido de que IP indica el
desplazamiento de la siguiente instruccin a ejecutar dentro del segmento de cdigo
determinado por CS:

Registro de banderas, FLAGS, o registro de estado (FL).
Es un registro de 16 bits, pero slo se utilizan nueve de ellos. Sirven para indicar el estado
actual de la mquina y el resultado del procesamiento. La mayor parte de las instrucciones de
comparacin y aritmticas modifican este registro. Algunas instrucciones pueden realizar
pruebas sobre este registro para determinar la accin siguiente.






OF (O) Bit de Overflow o desbordamiento. Indica desbordamiento de un bit de orden alto (ms
a la izquierda), despus de una operacin aritmtica.

DF (D) Bit de Direccin. Designa la direccin, creciente (0) o decreciente (1), en operaciones
con cadenas de caracteres.

IF (I) Bit de Interrupcin. Indica que una interrupcin externa, como la entrada desde el teclado,
sea procesada o ignorada.

TF (T) Bit de Trap o Desvo. Procesa o ignora la interrupcin interna de trace (procesamiento
paso a paso).

SF (S) Bit de Signo. Indica el valor del bit ms significativo del registro despus de una
operacin aritmtica o de desplazamiento.

ZF (Z) Bit Cero. Se pone a 1 si una operacin produce 0 como resultado.

AF (A) Bit de Carry Auxiliar. Se pone a 1 si una operacin aritmtica produce un acarreo del bit
3 al 4. Se usa para aritmtica especializada (ajuste BCD).

PF (P) Bit de Paridad. Se activa si el resultado de una operacin tiene paridad par.

CF (C) Bit de Acarreo. Contiene el acarreo de una operacin aritmtica o de desplazamiento de
bits.


Cargando el DEBUG en memoria

Es posible visualizar los valores de los registros internos del microprocesador utilizando el
programa DEBUG. Para empezar a trabajar con DEBUG escriba en el prompt del DOS de la
computadora:


C:\> DEBUG [Enter]


Una vez que el programa est en ejecucin, el indicador ("prompt") es un guin "-", indicando
que el "Shell" espera recibir rdenes. Para salir basta pulsar una Q. Como muchos programas
de su gnero, sus comandos empiezan por una letra o combinacin de ellas (pueden usarse
indistintamente maysculas o minsculas) y ciertos parmetros opcionales (no es
imprescindible separar la letra de opcin de los parmetros opcionales que siguen). La opcin
ms sencilla es la interrogacin (?), cuyo resultado es una lista resumida de las opciones
disponibles:





Ensamblar A [direccin]
Comparar C direccin de intervalo
Volcar D [intervalo]
Escribir E direccin [lista de valores]
Llenar F lista de intervalos
Ir G [=direccin] [direcciones]
Hex H valor1 valor2
Entrada I puerto
Cargar L [direccin] [unidad] [primer_sector] [nmero]
Mover M direccin de intervalo
Nombre N [nombre_ruta] [lista_argumentos]
Salida O byte de puerto
Proceder P [=direccin] [nmero]
Salir Q
Registro R [registro]
Buscar S lista de intervalos
Seguimiento T [=direccin] [valor]
Desensamblar U [intervalo]
Escribir W [direccin] [unidad] [primer_sector] [nmero]
Asignar memoria expandida XA [#pginas]
Desasignar memoria expandida XD [identificador]
Asignar pginas de memoria expandida XM [Lpgina] [Ppgina] [identificador]
Mostrar estado de la memoria expandida XS


En particular, obsrvese lo siguiente:


a) DEBUG opera bajo el sistema operativo DOS.
b) Cuando se invoca (como en el ejemplo) sin argumentos, el contenido de la
memoria es arbitrario.
c) Si se invoca desde el DOS con argumentos, como por ejemplo: DEBUG
EJEMPLO.COM, entonces carga a EJEMPLO.COM en memoria a partir de la
direccin 0100h.





Comandos del DEBUG

D: DUMP
D <direccin1> <direccin2>

Muestra el contenido de una zona de memoria en hexadecimal y en ASCII. Sin parmetros
muestra los primeros 128 bytes a partir de la posicin a la que se lleg en el ltimo "d". Si se le
da un rango, mostrar ese rango.

Ambas direcciones son opcionales. La 1ra es la direccin de inicio de despliegue; la 2da es la
direccin de fin.

Ejemplo:







NOTA: El contenido de la memoria seguramente no coincide con el que
otra persona obtenga.


E: EDIT
E <direccin><lista>

Permite editar, byte por byte, una zona de memoria. Muestra -en hexadecimal- el byte de esa
posicin y permite escribir otro valor para cambiarlo. Pulsando espacio pasa al byte siguiente,
dejando como estaba el anterior si no se ha cambiado, o guardando los cambios si s se ha
hecho. Para terminar la edicin se pulsa INTRO.

Los cambios pueden ser especificados en la lnea de comandos en cualquier combinacin de
nmeros hexadecimales o caracteres ASCII; los caracteres ASCII deben estar entre comillas
simples o dobles.

Por ejemplo:

E 100 'Benjamin Iglesias

Establece el patrn "42 65 6E 6A 61 6D 69 6E 20 49 67 6C 65 73 69 61 73" en memoria a partir
de la localidad 100H. Cuando no se especifica <lista> se entra en un modo especial en el que
DEBUG despliega los valores de <direccin>. Entonces es posible teclear nuevos valores que
reemplacen a los que se muestran. Si se teclea "-" DEBUG regresa a la localidad anterior. Si se
activa la barra espaciadora, DEBUG pasa a la siguiente localidad.


R: REGISTERS
R <registro>

Sin parmetros, muestra el contenido de los registros de la CPU, as como la prxima
instruccin a ejecutar."R [REGISTRO]" muestra el contenido del registro especificado y cambia
el prompt de "-" a ":" invitando a que se cambie su valor. Pulsando Enter sin ms lo deja como
estaba.

Ejemplo:

R <registro>
Donde <registro> es el nombre opcional y puede ser alguno de los siguientes: AX, BX, CX, DX,
SP, BP, SI, DI, DS, ES, SS, CS, IP, PC o F. IP y PC son sinnimos.


A: ASSEMBLE
A <direccin>

Sin parmetros ensambla las instrucciones que se introduzcan, guardndolas en la direccin
siguiente a la que se lleg en el ltimo "a". Cuando se utiliza este comando se le puede dar
como parmetro la direccin donde se desea que se inicie el ensamblado, si se omite el
parmetro el ensamblado se iniciar en la localizacin especificada por CS:IP, usualmente
0100H, que es la localizacin donde deben iniciar los programas con extensin .COM, y ser la
localizacin que utilizaremos debido a que DEBUG solo puede crear este tipo especfico de
programas.

La sintaxis es

A <direccin>

Prcticamente cualquier mnemotcnico es soportado por DEBUG, incluyendo los
especificadores de "override" de segmento (CS:, DS:, ES:, SS:). Una excepcin es que DEBUG
no puede diferenciar entre NEAR y FAR returns; asume que RET es "near" y RETF es "far".

Ejemplo: Vamos a usar la instruccin MOV, que como veremos ms adelante, sirve para copiar
datos de la memoria a los registros y viceversa, adems de copiar datos entre registros, que es
justo lo que vamos a usar en el ejemplo.


-a
2048:0106 mov ax,bx
2048:0108 mov bx,cx
2048:010A <RET>
-u 106 108
2048:0106 89D8 MOV AX,BX
2048:0108 89CB MOV BX,CX


Como veremos ms adelante, la instruccin 'U' sirve para hacer volcados de memoria, pero no
viendo el contenido de la misma, sino interpretndola como instrucciones en lenguaje
ensamblador.

; Ejemplo 2


-r cs
CS 2048
:2050
-a 200
2050:0200 mov ax,bx
2050:0202 <RET>
-u 200 200
2050:0200 89D8 MOV AX,BX


F: FILL
F <bloque> <valor de relleno>

Este comando llena un bloque de memoria con un valor especfico o una serie de valores.

La sintaxis es:

F <bloque> <valor de relleno>

<bloque> es la direccin de inicio y final o , si se preceden con "L", la direccin de inicio y la
longitud del bloque; <valor de relleno> es(son) el(los) valor(es) con los que debe de llenarse el
bloque. Si <valor de relleno> representa menor bytes que los que se necesitan para llenar el
bloque, la serie se repite hasta llenar el bloque.

Por ejemplo, cualquiera de las siguientes dos lneas llena (con 0s) el bloque DS:00FF:


F DS:0000 DS:00FF 0
DS:0000 LFF 0


Ejemplo:


-f 100 105 66
-d 100 105
2048:0100 66 66 66 66 66 66 ffffff


Q: QUIT
Q

Salir de DEBUG y volver al DOS.


P: PROCEED
P <=direccin><nmero>

Similar al comando T, pero al encontrarse un CALL o INT lo ejecuta de golpe sin entrar en su
interior (ojo, esto ltimo falla al tracear sobre memoria ROM!).

Trace puede ser incmodo si no se quiere depurar el cdigo de las rutinas de interrupcin o si
ya se sabe el cdigo que hay en las subrutinas y tan slo interesa seguir avanzando sin entrar
en ellas. En estos casos se usa p, por lo que si ejecutamos una interrupcin de MS-DOS no
sabramos que estamos haciendo

Ejemplo:


-r
AX=0261 BX=0000 CX=0000 DX=0061 SP=FFEE BP=0000 SI=0000 DI=0000 DS=2048
ES=2048 SS=2048 CS=2048 IP=0107 NV UP EI PL NZ NA PO NC 2048:0107 3D5000 CMP
AX,0050
-a 100
2048:0100 mov ax,0200
2048:0103 mov dl,61
2048:0105 int 21
2048:0107
-p =100 3
AX=0200 BX=0000 CX=0000 DX=0061 SP=FFEE BP=0000 SI=0000 DI=0000 DS=2048
ES=2048 SS=2048 CS=2048 IP=0103 NV UP EI PL NZ NA PO NC 2048:0103 B261 MOV
DL,61
AX=0200 BX=0000 CX=0000 DX=0061 SP=FFEE BP=0000 SI=0000 DI=0000 DS=2048
ES=2048 SS=2048 CS=2048 IP=0105 NV UP EI PL NZ NA PO NC 2048:0105 CD21 INT 21
a
AX=0261 BX=0000 CX=0000 DX=0061 SP=FFEE BP=0000 SI=0000 DI=0000 DS=2048
ES=2048 SS=2048 CS=2048 IP=0107 NV UP EI PL NZ NA PO NC 2048:0107 3D5000 CMP
AX,0050


T: TRACE
T <=direccin> <valor>

Ejecuta una instruccin del programa (a partir de CS:IP) mostrando a continuacin el estado de
los registros y la siguiente instruccin. Ejecutar T10 equivaldra a ejecutar 16 veces el comando
T. Si la instruccin es CALL o INT, se ejecutar como tal introducindose en la subrutina o
tabla de de interrupciones.

Ejemplo:


-r
AX=0000 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=2048
ES=2048 SS=2048 CS=2048 IP=0100 NV UP EI PL NZ NA PO NC 2048:0100 3D0000 CMP
AX,0000
-r bx
BX 0000
:2
-a 100
2048:0100 mov ax,bx
2048:0102
-t
AX=0002 BX=0002 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=2048
ES=2048 SS=2048 CS=2048 IP=0102 NV UP EI PL NZ NA PO NC 2048:0102 00AC01D8 ADD
[SI+D801],CH DS:D801=74


; Ejemplo 2


-r
AX=0000 BX=0007 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=2048
ES=2048 SS=2048 CS=2048 IP=0100 NV UP EI PL NZ NA PO NC 2048:0100 3D0000 CMP
AX,0000
-a 100
2048:0100 mov ax,bx
2048:0102 mov cx,bx
2048:0104
-t 2
AX=0007 BX=0007 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=2048
ES=2048 SS=2048 CS=2048 IP=0102 NV UP EI PL NZ NA PO NC 2048:0102 89D9 MOV
CX,BX
AX=0007 BX=0007 CX=0007 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=2048
ES=2048 SS=2048 CS=2048 IP=0104 NV UP EI PL NZ NA PO NC 2048:0104 01D8 ADD
AX,BX




N: NAME
N <nombre_archivo>

Se asigna un nombre al programa que est siendo creado o modificado. Se puede indicar la
trayectoria de directorios.


L: LOAD
L <buffer> <numdisco> <sectorini> <numsector>

<buffer> es la direccin en donde se carga la informacin; <numdisco> es el nmero (opcional)
del disco de donde se leer la informacin (0=A, 1=B, 2=C, etc.); <sectorini> es el sector de
disco absoluto (en hexadecimal) a leer; <numsector> es la cantidad de sectores a leer. No se
pueden leer ms de 80H (128) sectores. Si no se suministra la combinacin <numdisco>
<sectorini> <numsector> DEBUG presume que se desea leer un archivo. En este caso <buffer>
es opcional.

Debe usarse el comando N (ver ms adelante) para especificar el archivo a leer. ste se carga
en CS:0100.

Ejemplo: Se va a leer el sector 0 del disco A y se vuelca a partir de la direccin DS:100, como
se puede observar, el disco contiene mucha informacin ( ESTO NO QUIERE DECIR QUE
TENGA QUE SALIR LO MISMO EN SU VOLCADO )


l 100 0 0 1
-d 100 300






W: WRITE
W <direccin>

Graba el contenido de una zona de memoria a disco. Si no se indica la direccin, se graba
desde CS:100h hasta CS:100h+nmero_bytes; el nmero de bytes se indica en BX:CX (no es
una direccin segmentada sino un valor de 32 bits). Si se trata de un EXE no se permitir
grabarlo (para modificarlos, hay que renombrarles para cambiarles la extensin, aunque de
esta manera no sern montados al cargarlos).

La sintaxis es:

W <buffer> <numdisco> <sectorini> <numsector>

<buffer> es la direccin de donde se carga la informacin; <numdisco> es el nmero (opcional)
del disco en donde se escribir la informacin (0=A, 1=B, 2=C, etc.); <sectorini> es el sector de
disco absoluto (en hexadecimal) en donde empieza la escritura; <numsector> es la cantidad de
sectores a leer. No se pueden escribir ms de 80H (128) sectores. Si no se suministra la
combinacin <numdisco> <sectorini> <numsector> DEBUG presume que el inicio de archivo es
CS:100. En este caso <buffer> es opcional. Debe usarse el comando N (ver arriba) para
especificar el archivo a escribir.

Antes de escribir BX:CX debe ajustarse al nmero de bytes que desean grabarse. W no puede
escribir a archivos con la extensin EXE o HEX. [5]

Ejemplo:


N <nomarchivo>
BX:CX <--- 2000
W


S: SEARCH

S <rango> <lista>
Busca una cadena de bytes por la memoria. Para buscar la cadena "PEPE" terminada por cero
en un rea de 512 bytes desde DS:100 se hara: S 100 L 200 "PEPE",0 (por defecto se busca
en DS:). No se encontrara sin embargo "pepe" (en minsculas).


C: COMPARE
C <rango> <direccin>

Compara dos zonas de memoria mostrando las diferencias. Por ejemplo, para comparar 5
bytes de DS:100 y DS:200 se hace: C 100 L 5 200.


M: MOVE
M <rango> <direccin>

Ms que mover, copia una zona de memoria en otra de manera inteligente (controlando los
posibles solapamientos de los bloques).


I: INPUT
I <puerto>

Visualiza la lectura del puerto de E/S indicado.


O: OUTPUT
O <puerto> <valor>

Enva un valor a un puerto de E/S.


H: HEX
H <valor1> <valor2>

Muestra la suma y resta de valor1 y valor2, ambos operandos de un mximo de 16 bits (si hay
desbordamiento se trunca el resultado, que tampoco excede los 16 bits).

Resultado: <resultado_1> ; Es la suma ( <valor1> + <valor2>), <resultado_2> ; es la resta
(<valor1> - <valor2> )

Ejemplo:


-h 0003 0002
0005 0001
-h 0000 0001
0001 FFFF


como se observa, el resultado de la segunda operacin es FFFF que es el equivalente en
complemento a 2 de -1


G: GO
G =<inicio> <quiebre1> <quiebre2> ... <quiebre10>

Este comando ejecuta el cdigo en memoria. Si se est depurando un programa, permite
ejecutar el cdigo cargado en memoria. Tambin permite establecer puntos de quiebre
(breakpoints) que son direcciones en las que se detiene la ejecucin del programa.
La sintaxis es:

G =<inicio> <quiebre1> <quiebre2> ... <quiebre10>

<inicio> es la direccin de inicio de ejecucin; <quiebre1> hasta <quiebre10> son direcciones
opcionales de paro del programa. Si no se especifica <inicio>, Go inicia con la direccin
contenida en CS:IP. Para lograr los quiebres, DEBUG reemplaza el cdigo en las direcciones
de quiebre por el valor hexadecimal CC, que es el cdigo de interrupcin. Si DEBUG llega a
CC todos los puntos de quiebre son restituidos, los registros se despliegan (como con el
comando R [vase adelante]) y se para la ejecucin.

U: UNASSEMBLE

U <rango>

Este comando desensambla el contenido de la memoria a partir de la posicin actual.

Registros y Banderas del DEBUG

La mayora de los comandos de DEBUG ejecutan una accin y vuelven al indicador del shell,
pero si es un comando largo, como puede ser mostrar un trozo grande de cdigo, puede
detenerse pulsando CTRL-Pausa o interrumpirse con CTRL-C para volver al shell.

Por ejemplo, al teclear lo siguiente:

- r [Enter]


-R
AX=0000 BX=0000 CX=2917 DX=0000 SP=FFFE BP=0000 SI=0000 DI=0000
DS=17A7 ES=17A7 SS=17A7 CS=17A7 IP=0100 NV UP EI PL NZ NA PO NC
17A7:0100 E8CD0F CALL 10D0
-

Se desplegaran todos los contenidos de los registros internos del microprocesador; una forma
alternativa de mostrarlos es usar el comando "r" utilizando como parmetro el nombre del
registro cuyo valor se quiera visualizar. Por ejemplo:


- r bx


Esta instruccin desplegar nicamente el contenido del registro BX y cambia el indicador del
DEBUG de " - " a " : "

Estando as el prompt es posible cambiar el valor del registro que se visualiz tecleando el
nuevo valor y a continuacin [Enter], o se puede dejar el valor anterior presionando [Enter] sin
teclear ningn valor.

Es posible cambiar el valor del registro de banderas, as como utilizarlo como estructura de
control en nuestros programas como se ver ms adelante.

Cada bit del registro tiene un nombre y significado especial, la lista dada a continuacin
describe el valor de cada bit, tanto apagado como prendido y su relacin con las operaciones
del microprocesador:






Overflow (O)
NV = no hay desbordamiento;
OV = si lo hay

Direction (D)
UP = hacia adelante;
DN = hacia atrs;

Interrupts (I)
DI = desactivadas;
EI = activadas

Sign (S)
PL = positivo;
NG = negativo

Zero (Z)
NZ = no es cero;
ZR = s' lo es

Auxiliary Carry (A)
NA = no hay acarreo auxiliar;
AC = hay acarreo auxiliar

Parity (P)
PO = paridad non;
PE = paridad par;

Carry (C)
NC = no hay acarreo;
CY = Si lo hay



La estructura del ensamblador

En el lenguaje ensamblador las lneas de cdigo constan de dos partes, la primera es el
nombre de la instruccin que se va a ejecutar y la segunda son los parmetros del comando u
operandos. Por ejemplo:


add ah,bh


Aqu "add" es el comando a ejecutar (en este caso una adicin) y tanto "ah" como "bh" son los
parmetros.

El nombre de las instrucciones en este lenguaje est formado por dos, tres o cuatro letras, a
estas instrucciones tambin se les llama nombres mnemnicos o cdigos de operacin, ya que
representan alguna funcin que habr de realizar el microprocesador.

Existen algunos comandos que no requieren parmetros para su operacin, as como otros que
requieren solo un parmetro.

Algunas veces se utilizarn las instrucciones como sigue:


add al,[170]


Los corchetes en el segundo parmetro nos indican que vamos a trabajar con el contenido de
la posicin de memoria nmero 170 y no con el valor 170, a esto se le conoce como
direccionamiento directo.


Primer programa en ensamblador con el DEBUG

Vamos a crear un programa que sirva para ilustrar lo que hemos estado viendo, lo que
haremos ser una suma de dos valores que introduciremos directamente en el programa:

El primer paso es iniciar el DEBUG, este paso consiste nicamente en teclear DEBUG [Enter]
en el prompt del sistema operativo.

Para ensamblar un programa en el DEBUG se utiliza el comando "a" (assemble); cuando se
utiliza este comando se le puede dar como parmetro la direccin donde se desea que se inicie
el ensamblado.

Si se omite el parmetro el ensamblado se iniciar en la localidad especificada por CS:IP,
usualmente 0100H, que es la localidad donde deben iniciar los programas con extensin .COM,
y ser la localidad que utilizaremos debido a que DEBUG solo puede crear este tipo especfico
de programas.

Aunque en este momento no es necesario darle un parmetro al comando "a" es recomendable
hacerlo para evitar problemas una vez que se haga uso de los registros CS:IP, por lo tanto
tecleamos:

- a 100 [Enter]

Al hacer esto aparecer en la pantalla algo como: 0C1B:0100 y el cursor se posiciona a la
derecha de estos nmeros, ntese que los primeros cuatro dgitos (en sistema hexadecimal)
pueden ser diferentes, pero los ltimos cuatro deben ser 0100, ya que es la direccin que
indicamos como inicio.

Ahora podemos introducir las instrucciones:


0C1B:0100 mov ax,0002 ;coloca el valor 0002 en el registro ax
0C1B:0103 mov bx,0004 ;coloca el valor 0004 en el registro bx
0C1B:0106 add ax,bx ;le adiciona al contenido de ax el contenido de bx
0C1B:0108 int 20 ;provoca la terminacin del programa.
0C1B:010A


No es necesario escribir los comentarios que van despus del ";". Una vez escrito el ltimo
comando, int 20, se le da [Enter] sin escribir nada ms, para volver al prompt del DEBUG.

La ltima lnea escrita no es propiamente una instruccin de ensamblador, es una llamada a
una interrupcin del sistema operativo, estas interrupciones sern tratadas ms a fondo en un
captulo posterior, por el momento solo es necesario saber que nos ahorran un gran nmero de
lneas y son muy tiles para accesar a funciones del sistema operativo.

Para ejecutar el programa que escribimos se utiliza el comando "g", al utilizarlo veremos que
aparece un mensaje que dice: "Program terminated normally". Naturalmente con un mensaje
como ste no podemos estar seguros que el programa haya hecho la suma, pero existe una
forma sencilla de verificarlo, utilizando el comando "r" del DEBUG podemos ver los contenidos
de todos los registros del microprocesador, simplemente teclee:


- r [Enter]


Aparecer en pantalla cada registro con su respectivo valor actual:

-R
AX=0006 BX=0004 CX=0000 DX=0000 SP=FFFE BP=0000 SI=0000 DI=0000
DS=0C1B ES=0C1B SS=0C1B CS=0C1B IP=010A NV UP EI PL NZ NA PO NC
17A7:0100 E8CD0F CALL 10D0
-

Existe la posibilidad de que los registros contengan valores diferentes, pero AX y BX deben ser
los mismos, ya que son los que acabamos de modificar.

Otra forma de ver los valores, mientras se ejecuta el programa es utilizando como parmetro
para "g" la direccin donde queremos que termine la ejecucin y muestre los valores de los
registros, en este caso ser: g108, esta instruccin ejecuta el programa, se detiene en la
direccin 108 y muestra los contenidos de los registros.

Tambin se puede llevar un seguimiento de lo que pasa en los registros utilizando el comando
"t" (trace), la funcin de este comando es ejecutar lnea por lnea lo que se ensambl
mostrando cada vez los contenidos de los registros.

Para salir del DEBUG se utiliza el comando "q" (quit).





Guardar y cargar los programas

No sera prctico tener que escribir todo un programa cada vez que se necesite, para evitar eso
es posible guardar un programa en el disco, con la enorme ventaja de que ya ensamblado no
ser necesario correr de nuevo DEBUG para ejecutarlo, ya que cuando el DEBUG guardo
nuestro programa en el disco, ste se guardo en binario (archivo con la extensin .com).

Los pasos a seguir para guardar un programa ya almacenado en la memoria son:

Obtener la longitud del programa restando la direccin
final de la direccin inicial, naturalmente en sistema
hexadecimal.
Darle un nombre al programa y una extensin
Poner la longitud del programa en el registro CX
Ordenar a DEBUG que escriba el programa en el disco.

Utilizando como ejemplo el programa del ejemplo anterior tendremos una idea ms clara de
cmo llevar estos pasos:

Al terminar de ensamblar el programa se vera as:


0C1B:0100 mov ax,0002
0C1B:0103 mov bx,0004
0C1B:0106 add ax,bx
0C1B:0108 int 20
0C1B:010A


Para almacenarlo en el disco, hacemos lo siguiente:


- h 10a 100
020a 000a
- n prueba.com
- r cx
CX 0000
:000a
-w
Writing 000A bytes


Para obtener la longitud de un programa se utiliza el comando "h", el cual nos muestra la suma
y resta de dos nmeros en hexadecimal. Para obtener la longitud del programa, le
proporcionamos como parmetros el valor de la direccin final de nuestro programa (10A) y el
valor de la direccin inicial (0100). El primer resultado que nos muestra el comando es la suma
de los parmetros y el segundo es la resta.

El comando "n" nos permite poner un nombre al programa.

El comando "r cx" nos permite cambiar el contenido del registro CX al valor que obtuvimos del
tamao del archivo con "h", en este caso 000a, ya que nos interesa el resultado de la resta de
la direccin inicial a la direccin final.

Por ltimo el comando w escribe nuestro programa en el disco, indicndonos cuantos bytes
escribi.



NOTA: Si se trabaja en una ventana de DOS de Windows Vista o 7, es probable
que al momento de guardar su programa el DEBUG escriba mas cdigo que el
sealado por el registro CX, por consiguiente ser necesario limpiar el registro BX,
esto es, ponerlo a ceros y despus utilizar el comando w. Por ejemplo:


_r bx
BX 000E

: 0000

w



Para cargar un archivo ya guardado son necesarios dos pasos:


Proporcionar el nombre del archivo que se cargar a memoria.
Cargarlo utilizando el comando "l" (load).

Para obtener el resultado correcto de los siguientes pasos es necesario que previamente se
haya creado el programa anterior.

Dentro del DEBUG escribimos lo siguiente:


- n prueba.com
- l
- u 100 109
0C3D:0100 B80200 MOV AX,0002
0C3D:0103 BB0400 MOV BX,0004
0C3D:0106 01D8 ADD AX,BX
0C3D:0108 CD20 INT 20


El ltimo comando, "u", se utiliza para verificar que el programa se carg en memoria, lo que
hace es desensamblar el cdigo y mostrarlo ya desensamblado. Los parmetros le indican a
DEBUG desde donde y hasta donde desensamblar.

DEBUG siempre carga los programas en memoria en la direccin 100H, a menos que se le
indique alguna otra.


Un programa que realiza un conteo en pantalla

Con el DEBUG es posible escribir un programa que realice un conteo en pantalla, por razones
de comprensin, nuestro programa solo realizara un conteo de 9 a 0 (conteo descendente).


0B3B:0100 B90A00 MOV CX,000A ; CX=10 en decimal
0B3B:0103 88CA MOV DL,CL
0B3B:0105 80C22F ADD DL,2F ; sumamos 02Fh a DL
0B3B:0108 B402 MOV AH,02 ; funcin 02 de INT 21 para imprimir un caracter
0B3B:010A CD21 INT 21
0B3B:010C E2F5 LOOP 0103 ; CX=0? Si no, salta a 0103
0B3B:010E CD20 INT 20 ; termina el programa


En la lnea 0103 se puede observar que el valor del registro CX en su parte baja (en CL) se
almacena en el registro DL. Si se omitiera la lnea 0105, entonces cuando se ejecutara la lnea
010A solo se imprimira en pantalla el cdigo ASCII del valor que contenga DL (el cdigo ASCII
de 0Ah que es 10 en decimal es un carcter especial no imprimible). Para conseguir el efecto
de que el programa realiza el conteo en decimal se hace un corrimiento de 02F (47 en
decimal). Por ejemplo, cuando se ejecuta la lnea 0105, DL tendra el valor de 39h=57d
(02Fh+0Ah=39h=57d) y el cdigo ASCII de 57d es el carcter 9.

El sentencia LOOP decrementa CX en 1, si CX es diferente a 0 salta a la lnea 0103. El
proceso se repite y el programa imprime en pantalla 9876543210.

Sera interesante que el programa anterior fuera modificado para que la numeracin se
imprimiera de la siguiente manera: 9, 8, 7, 6, 5, 4, 3, 2, 1, 0.


NOTA: Como se dijo anteriormente, cuando el DEBUG almacena un
programa en el disco, este archivo se graba en binario, esto es en ejecutable.
Por lo tanto no es necesario cargar el DEBUG para volver a ejecutar nuestro
programa, sino que se hace de manera directa desde DOS. El problema
surge cuando al ejecutar nuestro programa el resultado no se puede observar
porque el DOS borra la pantalla despus de terminar de ejecutar el programa.
Para evitar el borrado automtico ser necesario agregarle a nuestro
programa antes de la INT 20h una instruccin para la lectura de un carcter
desde el teclado. Para tal efecto utilizaremos la funcin 08 de la INT 21h (un
buen truco para que el programa haga una pausa), as el programa esperara
hasta que el usuario presiona una tecla, permitiendo observar el resultado.

Ejemplo

mov ah,08
Int 21
Int 20


Condiciones, ciclos y bifurcaciones

Estas estructuras, o formas de control le dan a la mquina un cierto grado de decisin basado
en la informacin que recibe.

La forma ms sencilla de comprender este tema es por medio de ejemplos.

Vamos a crear tres programas que hagan lo mismo: desplegar un nmero determinado de
veces una cadena de caracteres en la pantalla.


- a100
0C1B:0100 jmp 125 ; salta a la direccin 125H
0C1B:0102 [Enter]
- e 102 'Cadena a visualizar 15 veces' 0d 0a '$'
- a125
0C1B:0125 MOV CX,000F ; veces que se desplegara la cadena
0C1B:0128 MOV DX,0102 ; copia cadena al registro DX
0C1B:012B MOV AH,09 ; copia valor 09 al registro AH
0C1B:012D INT 21 ; despliega cadena
0C1B:012F LOOP 012D ; si CX>0 salta a 012D
0C1B:0131 INT 20 ; termina el programa.


Por medio del comando "e" es posible introducir una cadena de caracteres en una determinada
localidad de memoria, dada como parmetro, la cadena se introduce entre comillas, le sigue un
espacio, luego el valor hexadecimal del retorno de carro, un espacio, el valor de lnea nueva y
por ltimo el smbolo '$' que el ensamblador interpreta como final de la cadena. La interrupcin
21 utiliza el valor almacenado en el registro AH para ejecutar una determinada funcin, en este
caso mostrar la cadena en pantalla, la cadena que muestra es la que est almacenada en el
registro DX. La instruccin LOOP decrementa automticamente el registro CX en uno y si no
ha llegado el valor de este registro a cero salta a la posicin de memoria indicada como
parmetro, lo cual crea un ciclo que se repite el nmero de veces especificado por el valor de
CX. La interrupcin 20 termina la ejecucin del programa.

Otra forma de realizar la misma funcin pero sin utilizar el comando LOOP es la siguiente:

- a100
0C1B:0100 jmp 125 ; salta a la direccin 125H
0C1B:0102 [Enter]
- e 102 'Cadena a visualizar 15 veces' 0d 0a '$'
- a125
0C1B:0125 MOV BX,000F ; veces que se desplegara la cadena
0C1B:0128 MOV DX,0102 ; copia cadena al registro DX
0C1B:012B MOV AH,09 ; copia valor 09 al registro AH
0C1B:012D INT 21 ; despliega cadena
0C1B:012F DEC BX ; decrementa en 1 a BX
0C1B:0130 JNZ 012D ; si BX es diferente a 0 salta a 012D
0C1B:0132 INT 20 ; termina el programa.


En este caso se utiliza el registro BX como contador para el programa, y por medio de la
instruccin "DEC" se disminuye su valor en 1. La instruccin "JNZ" verifica si el valor de BX es
diferente a 0, esto con base en la bandera NZ, en caso afirmativo salta hacia la direccin 012D.
En caso contrario contina la ejecucin normal del programa y por lo tanto se termina.

Una ltima variante del programa es utilizando de nuevo a CX como contador, pero en lugar de
utilizar LOOP utilizaremos decrementos a CX y comparacin de CX a 0.


- a100
0C1B:0100 jmp 125 ; salta a la direccin 125H
0C1B:0102 [Enter]
- e 102 'Cadena a visualizar 15 veces' 0d 0a '$'
- a125
0C1B:0125 MOV DX,0102 ; copia cadena al registro DX
0C1B:0128 MOV CX,000F ; veces que se desplegara la cadena
0C1B:012B MOV AH,09 ; copia valor 09 al registro AH
0C1B:012D INT 21 ; despliega cadena
0C1B:012F DEC CX ; decrementa en 1 a CX
0C1B:0130 JCXZ 0134 ; si CX es igual a 0 salta a 0134
0C1B:0132 JMP 012D ; salta a la direccin 012D
0C1B:0134 INT 20 ; termina el programa


En este ejemplo se us la instruccin JCXZ para controlar la condicin de salto, el significado
de tal funcin es: salta si CX=0

El tipo de control a utilizar depender de las necesidades de programacin en determinado
momento.






Manipulacin de Posiciones de Memoria

Con el DEBUG es posible almacenar y recuperar datos numricos en memoria por medio de un
programa a travs de los registros del microprocesador. Por ejemplo, el siguiente programa
almacena previamente dos valores numricos en la posicin 0300h y 0400h respectivamente,
despus el programa los recupera, realiza la operacin de suma con esos valores y el
resultado lo almacena en la posicin 0500h.


-a 100
0B1C:0100 mov ax,0002 ;ax=2
0B1C:0103 mov [0300],ax ;almacenamos 2 en la direccin 0300h
0B1C:0106 mov ax,0004 ;ax=4
0B1C:0109 mov [0400],ax ;almacenamos 4 en la direccin 0400h
0B1C:010C mov ax,[0300] ;recuperamos el dato1 en AX
0B1C:010F mov bx,[0400] ;recuperamos el dato2 en BX
0B1C:0113 add ax,bx ;hacemos la operacin de suma en AX
0B1C:0115 mov [0500],ax ;almacenamos el 6 en la direccin 0500h
0B1C:0118 int 21
0B1C:011A
-


Un nmero entre corchetes [numero_hex] indica una posicin de memoria, y su manejo se
hace a travs de registros, ya que no es posible almacenar valores numricos de manera
directa.


Ejecutamos el programa


-g 118

AX=0006 BX=0004 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
DS=0B1C ES=0B1C SS=0B1C CS=0B1C IP=0118 NV UP EI PL NZ NA PE NC
0B1C:0118 CD21 INT 21
-


Para ver si el resultado se almaceno en la direccin correcta, hacemos:





Como se puede observar en la direccin 0B1C:0500 se encuentra el 06 y en 0B1C:0501 se
encuentra el 00, que es el resultado de la operacin 2+4. Pero.

Porque aparece el 06 y despus el 00, parecera que el resultado fue de 0600, pero no es as,
lo que sucedes que los datos se almacenan en memoria de la siguiente manera:

Como se hizo la operacin AX=AX+BX, entonces el resultado es de 16 bits (dos bytes).


AX=6, entonces AX=0000 0000 0000 0110 (16 bits), por lo tanto los 8 bits de menor peso de
AX son 0000 0110 y deben almacenarse en la direccin 0500 y en la direccin 0501 se
almacena 0000 0000.

0 0 0 0 0 1 1 0 0500
0 0 0 0 0 0 0 0 0501
x x x x x x x x 0502
x x x x x x x x 0503
x x x x x x x x 0504
x x x x x x x x 0505



Interrupciones

Definicin de interrupcin:


Una interrupcin es una instruccin que detiene la ejecucin de un programa
para permitir el uso del microprocesador en un proceso prioritario. Una vez
concluido este ltimo proceso se devuelve el control a la aplicacin anterior.



Por ejemplo, cuando estamos trabajando con un procesador de palabras y en ese momento
llega un aviso de uno de los puertos de comunicaciones, se detiene temporalmente la
aplicacin que estbamos utilizando para permitir el uso del microprocesador al manejo de la
informacin que est llegando en ese momento. Una vez terminada la transferencia de
informacin se reanudan las funciones normales del procesador de palabras.

Las interrupciones ocurren muy seguido, sencillamente la interrupcin que actualiza la hora del
da ocurre aproximadamente 18 veces por segundo. Para lograr administrar todas estas
interrupciones, la computadora cuenta con un espacio de memoria, llamado memoria baja,
donde se almacenan las direcciones de cierta localidad de memoria donde se encuentran un
juego de instrucciones que el microprocesador ejecutar para despus regresar a la aplicacin
que estaba en proceso.

En los programas anteriores hicimos uso de la interrupcin nmero 20H para terminar la
ejecucin de nuestros programas y en otros ejemplos, utilizamos otra interrupcin para mostrar
informacin en pantalla (INT 21h):

Utilizando DEBUG tecleamos:


- a100
2C1B:0100 JMP 011D
2C1B:0102 [ENTER]
- E 102 'Hola, como estas.' 0D 0A '$'
- A011D
2C1B:011D MOV DX,0102
2C1B:0120 MOV AH,09
2C1B:0122 INT 21
2C1B:0123 INT 20


Orden
creciente
de la
memoria
En este programa la interrupcin 21h manda al monitor la cadena localizada en la direccin a la
que apunta el registro DX.

El valor que se le da a AH determina cual de las opciones de la interrupcin 21h ser utilizada,
ya que esta interrupcin cuenta con varias opciones.

El manejo directo de interrupciones es una de las partes ms fuertes del lenguaje ensamblador,
ya que con ellas es posible controlar eficientemente todos los dispositivos internos y externos
de una computadora gracias al completo control que se tiene sobre operaciones de entrada y
salida.


Ms del DEBUG

Una caracterstica poco conocida, es que DEBUG puede aceptar entradas desde un archivo
"Script", que puede ser un simple archivo de texto ASCII en el que cada comando est
separado del anterior por un INTRO. Despus del ltimo, que debe ser una "Q" para salir de
DEBUG, es conveniente dejar una lnea en blanco pulsando INTRO dos veces. Las lneas
pueden contener comentarios. Cualquier cosa a partir del caracter punto y coma (;) hasta el
final de la lnea, ser ignorado.


; esto es un comentario
D ; aqu se mostrar algo...


Suponiendo que tengamos un archivo "Script" de nombre Ordenes.txt, puede ser utilizado
como entrada para DEBUG mediante un comando de redireccin en la siguiente forma:


DEBUG < ordenes.txt


Tambin puede conseguirse que el programa redireccione la salida hacia un archivo que puede
ser inspeccionado ms tarde. Aunque tiene la dificultad de tener que trabajar "a ciegas",
puede ser de utilidad en determinadas circunstancias. Por ejemplo, cuando se desea un
volcado de determinadas zonas de la memoria. En el caso anterior podra obtenerse un
archivo Result.txt con el siguiente comando:


DEBUG < ordenes.txt > Result.txt


Errores

Cuando DEBUG no sabe interpretar un comando, muestra un mensaje de error y un indicador
"^" debajo del sitio del comando donde est el error.


Entradas y Salidas

DEBUG asume que los datos numricos proporcionados son hexadecimales, y cuando se trate
de direcciones de memoria, deben introducirse en forma segmentada. A su vez, los resultados
son mostrados tambin en formato hexadecimal cuando se refieren a direcciones de memoria.
Cuando se trata simplemente del contenido de ciertas posiciones de memoria, el resultado es
mostrado en formato hexadecimal y en ASCII. Por ejemplo, una salida puede presentar el
siguiente aspecto:





Cada fila muestra 16 posiciones de memoria a partir de la posicin sealada por las columnas
de la izquierda, que las muestran como segmento:desplazamiento. El bloque central muestra
el contenido hexadecimal de cada byte, mientras que el bloque derecho contiene la
representacin ASCII. Por ejemplo, la 3ra fila muestra el contenido de las posiciones
0B77:0120 a 0B77:012F (ambas inclusive). Sus tres ltimos bytes contienen respectivamente
los caracteres r, 9 y 2, que corresponden a las cantidades 72h 39h y 32h del bloque central.
Que como sabemos, equivalen a los decimales 114, 57 y 50, que son precisamente los valores
ASCII de los caracteres r, 9, y 2 anteriormente mencionados.


Nota: Por razn de que ste tipo de salida pueda ser listado a impresora, el bloque
derecho no contiene en realidad la representacin ASCII de todos los caracteres
(algunos ni siquiera tienen una representacin imprimible). En realidad solo se
muestran los caracteres imprimibles del primer bloque (US-ASCII). El resto est
representado por un punto.


No perder de vista que, a pesar de que algunas posiciones de memoria puedan contener
valores cuya equivalencia ASCII sea un carcter imprimible. Esto no significa que dichas
posiciones representen efectivamente tales valores para la aplicacin que las utiliza. Por
ejemplo, puede que en realidad, las dos posiciones de memoria mencionadas (dos octetos o
bytes), en vez de los caracteres 5 y a, representen una palabra de 16 bits en formato Little
Endian, que a su vez representan una cantidad entera (un nmero).


Comandos

Aunque su descripcin completa llenara todo un captulo, a continuacin comentamos algunas
de las opciones ms interesantes relativas a inspeccin del cdigo y de contenidos de
memoria.

La opcin D ("Dump") permite obtener un volcado del contenido de la memoria (de DEBUG).
La sintaxis acepta dos formas:


D [direccin-inicial] [L posiciones-desde-direccin-inicial ]
D [direccin-inicial][direccin-final]


Naturalmente, para que exista algo en el bfer de memoria (al principio quizs solo contiene
basura) es preciso indicarle que lea algo. Este algo puede ser un rango de direcciones de
memoria RAM; una direccin absoluta de disco (sector); un archivo, o el contenido de los
registros del procesador. Para empezar puede indicrsele que cargue un archivo xxx.xyz, que
tenemos en el directorio actual o en el PATH, cuyo contenido queremos ver.


C:\> DEBUG xxx.xyz
-D


aqu se obtendra una salida anloga a la comentada.

Hemos visto un ejemplo al tratar de los servicios de interrupciones del PC, aqu mostraremos
otro. Sabemos que el punto de inicio de la BIOS es la direccin F000:FFF0, y que desde sta
posicin hasta el final de la memoria DOS hay 16 bytes. Puede obtenerse un volcado de estas
posiciones con el siguiente comando:


-D F000:FFF0


La salida en un equipo puede ser:

F000:FFF0 CD 19 E0 00 F0 30 36 2F-33 30 2F 39 37 00 FC 38 .....06/30/97..8


En este caso el comando solo muestra una lnea porque ha alcanzado el final de la memoria.
Puede verse que la fecha de la BIOS del sistema ocupa las ltimas posiciones.

Si se ordena el volcado de una direccin suficientemente alejada del final de la memoria, sin
indicar ningn nmero de posiciones, por defecto se toma el valor 128 (8 filas de 16
posiciones). Si desea una cantidad distinta, hay que aadir una L ("Long") y el nmero de
posiciones, hasta un mximo de 64 KB (FFFF). Todos los nmeros deben ser expresados en
hexadecimal. Por consiguiente los dos comandos que siguen son equivalentes (recuerde que
80 es el equivalente hexadecimal de 128):

D FE00:0000
D FE00:0000 L 80


He aqu el resultado:





Sabemos que esta zona corresponde al rea de la BIOS del Sistema...

Otra opcin muy interesante nos permite buscar determinados contenidos a travs de la
memoria utilizando el prefijo S ("Search"). Existen dos sintaxis alternativas:


S direccin-de-inicio L longitud-a-explorar contenido-a-buscar
S direccin-de-inicio direccin-final L contenido-a-buscar


El contenido debe ser proporcionado en hexadecimal (tal como aparecera en la columna
central del ejemplo anterior) o entre comillas si es un texto ASCII. Por ejemplo, en un equipo
IBM, deseo ver algunas caractersticas de la BIOS. S que estos datos se alojan a partir de la
posicin F000:0000 hasta el final de la memoria. Es decir, una longitud de 64 Kbytes (FFFF) a
partir de la posicin de inicio, y que seguramente, los datos buscados estarn cerca de la
identificacin de la propia BIOS (la cadena "IBM"). Por lo que se utiliza la siguiente sintaxis [3]:


-s f000:0000 L ffff "IBM"


y se obtiene la siguiente salida:


F000:E00E
F000:E111


con las direcciones donde se ha encontrado la ocurrencia buscada. A continuacin puedo
explorar las proximidades de cada posicin. Por ejemplo para la primera:

-D f000:e000



Si lo que se busca est en un archivo, primero hay que cargarlo. Lo que se puede hacer de
dos formas: en la propia invocacin de DEBUG, o mediante los comandos N y L. Por ejemplo,
si queremos inspeccionar el contenido del archivo more.com, podemos utilizar dos formas:


C:\WINDOWS>DEBUG c:\windows\command\more.com
C:\WINDOWS>DEBUG
- N c:\windows\command\more.com
- L


La sintaxis para el prefijo N es:


N [path-name]nombre-de-archivo


En ambos casos el contenido del archivo ser cargado en memoria y podr ser utilizado.

Atencin: despus de la orden L ("Load"), DEBUG le avisar si no encuentra el archivo, pero
seguir su funcionamiento. En tal caso simplemente piensa que N seala el nombre de un
nuevo archivo que crear, con el contenido de la memoria -de DEBUG-, cuando posteriormente
seleccione la opcin escribir W ("Write")[4].


Nota: Como ya habr deducido, DEBUG permite leer un archivo, realizar
modificaciones en l (con la opcin E) y escribir el archivo modificado bajo otro
nombre con N/W.


A continuacin podemos comprobar el tamao del archivo cargado. Para ello usamos la
opcin R (ver estado de los registros) y obtenemos el siguiente resultado:


-R
AX=0000 BX=0000 CX=2917 DX=0000 SP=FFFE BP=0000 SI=0000 DI=0000
DS=17A7 ES=17A7 SS=17A7 CS=17A7 IP=0100 NV UP EI PL NZ NA PO NC
17A7:0100 E8CD0F CALL 10D0
-


Aqu nos interesa especialmente el contenido del registro CX, cuyo valor, 2917h (1519d) en
este caso, seala el tamao del archivo en bytes. Tambin podamos haber utilizado
directamente el comando R CX que nos proporciona el valor de dicho registro:


-R CX
CX 2917
:
-


Nota: A continuacin del valor correspondiente, DEBUG muestra dos puntos (:),
sealando que puede cambiar el valor del registro introduciendo un nuevo nmero.
Pulse INTRO para dejar las cosas como estn y volver al "prompt" (-) de DEBUG.


Al llegar a este punto, es importante sealar que, a excepcin de los archivos .exe, DEBUG
carga los archivos a partir de la direccin 100h (256d) de "su" memoria. De forma que el primer
octeto del archivo se carga en la direccin 100; el segundo en 101; etc. En nuestro caso, el
archivo se extender desde la posicin 100h hasta 2A17h (100h + 2917h).

A continuacin, para buscar la cadena "Microsoft" en el archivo, utilizamos cualquiera de los
siguientes comandos:

- S 100 L 2917 "Microsoft"
- S 100 2a17 "Microsoft"


El primer comando seala el punto de inicio y el tamao de la zona a buscar; el segundo utiliza
los puntos inicial y final de la exploracin. Con ambos se obtiene la misma respuesta:


17A7:1083
17A7:10B2


Truco: Debido a la forma especial en que se cargan los ejecutables .exe, si quiere
inspeccionar la forma nativa de uno de estos archivos (como es su imagen en el
disco), debe hacer una copia del archivo; renombrarlo con cualquier otra
terminacin (o sin ella) y cargar esta copia. En caso contrario, DEBUG se preparar
para funcionar como un verdadero depurador de tiempo de ejecucin (run-time),
para lo que cargar el archivo y lo acomodar en memoria de forma que pueda
ejecutarse [5].


Como ejercicio, compruebe las distintas longitudes y aspecto (especialmente al principio) de un
mismo archivo .exe cargndolo con DEBUG de las dos formas (busque en su sistema un .exe
lo ms pequeo posible).

Adems de la capacidad de leer archivos antes mencionada, quizs una de las opciones ms
interesantes (y peligrosas) de DEBUG es la posibilidad de leer/escribir el contenido de disco a
bajo nivel mediante los prefijos L ("Load") y W ("Write"). Se utiliza la siguiente sintaxis:


L [Direccin] [Unidad] [Primer_sector] [Nmero]
W [Direccin] [Unidad] [Primer_sector] [Nmero]


El significado de los parmetros es como sigue:

Direccin: Posicin de la memoria de DEBUG, a partir de la cual se instalarn los
datos ledos del disco, o se tomarn para el proceso de escritura (aqu se utiliza
generalmente el valor 100h).
Unidad: Valor numrico que indica la lgica a utilizar. 0 = A:; 1 = B:; 2 = C:; 3 = D:,
etc [6]
Primer sector: A partir del que se realizar la lectura, o se comenzar a escribir.
Nmero: Nmero de sectores que se desea cargar/escribir. Como DEBUG no puede
leer/escribir ms de 64 Kbytes (2
16
= 65536) y los sectores de disco son de 512 bytes,
el mximo nmero de sectores es 128 (80h). As pues, el valor mximo aqu es 80.

Ejemplo: Para obtener el contenido del sector de arranque ("Master boot sector" MBR) de un
disquete en A:, utilizaremos el comando:


C:\WINDOWS>DEBUG
- L 100 0 0 1
- D 100 L 200


Como el resultado no cabe en una pantalla, ingeniaremos un procedimiento para conservarlo
en un archivo (ms adelante nos servir para otro propsito). Para ello creamos un archivo
script.txt con el siguiente contenido (dos INTRO despus de la "Q"):

L 100 0 0 1
D 100 L 200

Q


A continuacin invocamos DEBUG con el comando


C:\WINDOWS>DEBUG < D:\buzon\script.txt > D:\buzon\resultad.txt


Despus de un breve parpadeo del disco y del disquete, vuelve el "prompt" del DOS. La
operacin ha concluido, y en el directorio correspondiente de la unidad D: tenemos el archivo
resultad.txt con el volcado del sector de arranque del disquete, adems de los "ecos" de los
comandos introducidos (los hemos mantenido para orientacin del lector).

Otra forma de poder visualizar el contenido del Sector de Arranque del disco es utilizando el
DEBUG. Por ejemplo, dentro del DEBUG tecleamos lo siguiente:


-L 100 0 0 1

-D 100 L 200

177C:0100 EB 3E 90 2B 79 73 57 29-49 48 43 00 02 01 01 00 .>.+ysW)IHC.....
177C:0110 02 E0 00 40 0B F0 09 00-12 00 02 00 00 00 00 00 ...@............
177C:0120 00 00 00 00 00 00 29 5D-3B DD 10 4E 4F 20 4E 41 ......)];..NO NA
177C:0130 4D 45 20 20 20 20 46 41-54 31 32 20 20 20 F1 7D ME FAT12 .}
177C:0140 FA 33 C9 8E D1 BC FC 7B-16 07 BD 78 00 C5 76 00 .3.....{...x..v.
177C:0150 1E 56 16 55 BF 22 05 89-7E 00 89 4E 02 B1 0B FC .V.U."..~..N....
177C:0160 F3 A4 06 1F BD 00 7C C6-45 FE 0F 8B 46 18 88 45 ......|.E...F..E
177C:0170 F9 FB 38 66 24 7C 04 CD-13 72 3C 8A 46 10 98 F7 ..8f$|...r<.F...
177C:0180 66 16 03 46 1C 13 56 1E-03 46 0E 13 D1 50 52 89 f..F..V..F...PR.
177C:0190 46 FC 89 56 FE B8 20 00-8B 76 11 F7 E6 8B 5E 0B F..V.. ..v....^.
177C:01A0 03 C3 48 F7 F3 01 46 FC-11 4E FE 5A 58 BB 00 07 ..H...F..N.ZX...
177C:01B0 8B FB B1 01 E8 94 00 72-47 38 2D 74 19 B1 0B 56 .......rG8-t...V
177C:01C0 8B 76 3E F3 A6 5E 74 4A-4E 74 0B 03 F9 83 C7 15 .v>..^tJNt......
177C:01D0 3B FB 72 E5 EB D7 2B C9-B8 D8 7D 87 46 3E 3C D8 ;.r...+...}.F><.
177C:01E0 75 99 BE 80 7D AC 98 03-F0 AC 84 C0 74 17 3C FF u...}.......t.<.
177C:01F0 74 09 B4 0E BB 07 00 CD-10 EB EE BE 83 7D EB E5 t............}..
177C:0200 BE 81 7D EB E0 33 C0 CD-16 5E 1F 8F 04 8F 44 02 ..}..3...^....D.
177C:0210 CD 19 BE 82 7D 8B 7D 0F-83 FF 02 72 C8 8B C7 48 ....}.}....r...H
177C:0220 48 8A 4E 0D F7 E1 03 46-FC 13 56 FE BB 00 07 53 H.N....F..V....S
177C:0230 B1 04 E8 16 00 5B 72 C8-81 3F 4D 5A 75 A7 81 BF .....[r..?MZu...
177C:0240 00 02 42 4A 75 9F EA 00-02 70 00 50 52 51 91 92 ..BJu....p.PRQ..
177C:0250 33 D2 F7 76 18 91 F7 76-18 42 87 CA F7 76 1A 8A 3..v...v.B...v..
177C:0260 F2 8A 56 24 8A E8 D0 CC-D0 CC 0A CC B8 01 02 CD ..V$............
177C:0270 13 59 5A 58 72 09 40 75-01 42 03 5E 0B E2 CC C3 .YZXr.@u.B.^....
177C:0280 03 18 01 27 0D 0A 44 69-73 63 6F 20 69 6E 63 6F ...'..Disco inco
177C:0290 72 72 65 63 74 6F 20 20-20 FF 0D 0A 45 72 72 6F rrecto ...Erro
177C:02A0 72 20 45 2F 53 20 20 20-20 20 FF 0D 0A 43 61 6D r E/S ...Cam
177C:02B0 62 69 65 20 65 6C 20 64-69 73 63 6F 20 79 20 70 bie el disco y p
177C:02C0 72 65 73 69 6F 6E 65 20-75 6E 61 20 74 65 63 6C resione una tecl
177C:02D0 61 20 20 20 20 0D 0A 00-49 4F 20 20 20 20 20 20 a ...IO
177C:02E0 53 59 53 4D 53 44 4F 53-20 20 20 53 59 53 80 01 SYSMSDOS SYS..
177C:02F0 00 57 49 4E 42 4F 4F 54-20 53 59 53 00 00 55 AA .WINBOOT SYS..U.
-

-Q









































FIN

[1] En las primeras versiones de MS-DOS era un modesto programita DEBUG.COM de apenas
16 KB. La versin que acompaa a Windows98 es ya un ejecutable en formato .EXE de 21
KB.

[2] En realidad DEBUG es una utilidad de enorme potencia que requerira todo un libro para
ella sola. Puede encontrarse una amplia descripcin de esta herramienta en el libro de Paul
Somerson "PC Magazine: DOS Powers Tools".

[3] Desgraciadamente no hay una convencin estndar sobre la colocacin de los datos en la
BIOS, de forma que cada fabricante sigue sus propias reglas y es imposible por tanto, utilizarla
para cualquier tipo de identificacin del sistema.

[4] En palabras del mencionado Paul Somerson: "Desgraciadamente, debido a que DEBUG es
un programa tan increblemente potente, tambin es increblemente peligroso".... "Hay un dicho
que afirma que 'El software no puede destruir el hardware'. Desgraciadamente esto no es
cierto. Adems de enviar mecanismos sensibles de la unidad de disco a tierra de nadie, es
posible hacer saltar monitores o transformadores. Repito, si sigue al pie de la letra las
instrucciones y hace caso a todos los avisos, todo ir bien."

[5] Recuerde que la imagen de un ejecutable .exe cargado en memoria es distinta de su
imagen en disco. Solo en los ejecutables .com la imagen en disco es una imagen exacta de su
disposicin en memoria.

[6] Es evidente que un pequeo error de nmero en este parmetro puede acarrear
consecuencias nefastas. Por ejemplo, si cree que est "jugando" con el disquete e
inadvertidamente se dirige al disco duro!! (relea la nota [4]).

También podría gustarte