Está en la página 1de 9

Manual muy corto de MS-DOS debug.

com
(Essential debug.com)
Propsito:
Debug.exe es un programa - depuradora de bajo nivel para uso general en el entorno de MS-DOS.
Debug.exe tiene soporte para el lenguaje de maquina (8086).
Funciones que realiza debug.exe:
Memoria y entrada salida:
- imprimir el contenido de la memoria como HEX-ASCII.
- cambiar el contenido de la memoria (entrada HEX o ASCII).
- ver el contenido de un puerto de entrada.
- emitir byte/word a un puerto de salida.
Cdigo esttico:
- entrada como mnemnicas (micro ensamblador de lenguaje de maquina)
- imprimir el contenido de la memoria como mnemnicas de 8086.
Ejecucin de programas:
- ejecucin de cdigo a partir de una direccin con hasta 16 puntos de interrupcin (sustituyendo los
puntos de interrupcin con INT 3 solo RAM).
- ejecucin de cdigo paso a paso (utilizando el bandera (FLAG)T del procesador RAM/ROM).
- Entrada del contenido de los registros del procesador.
- Impresin de los registros del procesador.
Otras funciones (no se consideran en el manual)
- leer/escribir en los discos (sector o fichero).
- Manejo de los registros de co-procesador
- .
Se consideran los comandos en base de ejemplos. El manual ni es completo ni es la manera mas eficaz de
hacer las cosas con DEBUG. Esto es solo un sub-conjunto mnimo de comandos de DEBUG, que nos
permite de utilizar DEBUG.
Ejemplo A escribir y comprobar un programa que imprime el contenido del puerto 378h como numero
hexadecimal. Las entradas del operador son en negrita. Los comentarios son en latina (no les consideras
como entrada):
C:\>debug
Como pedir ayuda de DEBUG entrar ?.
-a100

Assembly a partir de CS:100


No utilizar las direcciones CS:0 CS:100 en estas direcciones se
encuentran los PSP y COM del programa.
106E:0100 mov dx,378
106E:0103 in al,dx
106E:0104 call 140

Todos los nmeros en DEBUG son en HEX.


Tal como no hay etiquetas tenemos que utilizar direcciones absolutas.
En este punto necesitamos un programa que convierte el AL en una

cadena de caracteres (dgitos hex).


106E:0107 int 3
Este es un punto de parada (interrupcin del programa, breakpoint)
para cualquier depuradora con 8086. Lo entramos a mano (notar que no utilizamos mov AX,4c00// int 21
o int 20). Se utiliza int 3 porque ocupa solo un byte y puede remplazar cualquier instruccin.

Tal como es mas cmodo primero convertir AL en dgitos y despus imprimir la cadena (con int 21, ah=9)
corregimos el programa. Para entrar de nuevo cdigo de maquina a partir de la direccin 104 tenemos
que salir del rgimen de entrada de cdigo.
106E:0108
Salimos del ensamblador con entrada de una lnea vaca.
-a104
Ensamblador de nuevo a partir de la direccin 104 (mirar arriba)
106E:0104 mov di,200
106E:0107 call 140

; seria la direccin donde se encuentra la cadena de salida.


; el programa que convierte AL a cadena de dos caracteres

106E:010A mov dx,200 ; Escribimos en CON: sea que sea el CON:


106E:010D mov ah,9
106E:010F int 21
106E:0111 int 3
; La parada cmoda de DEBUG. Por la diferencia de INT 20h escribe el
contenido de los registros.
106E:0112
-a140
; Esto seria el programa de conversin de AL en HEX
106E:0140 cld
106E:0141 call 143
; Supongamos que a partir de la siguiente instruccin hay un programa que
convierte la parte alta de al a carcter ASCII (HEX). Calculamos (errneo la direccin de la siguiente
instruccin como 141+2-> 143).
106E:0144 rol al,1
; Nos hemos equivocado la siguiente instruccin empieza en 144.
106E:0146
; Volvemos a entrar a partir de 144.
-a141
106E:0141 call 144
106E:0144 rol al,1
106E:0146 rol al,1
106E:0148 rol al,1
106E:014A rol al,1
106E:014C push ax
106E:014D and al,0f
106E:014F cmp al,a
; Si al esta fuera del rango 0-a
; no hay caracteres
106E:0151 jna 156
; No sabemos donde saltar, porque seria muy despreciable e indigno memorizar
la longitud de todas las instrucciones y calcular direcciones en hex sentndose ante de un ordenador, pero
sabemos que esta cerca de esta direccin. Apostamos por 156
106E:0153 add al,6
; tenemos de aadir A-(9+1) que es mas o menos 6.
106E:0155 add al,a
106E:0157 stosb
106E:0158 pop ax
106E:0159 ret
Corregimos la instruccin equivocada (la direccin no es 156 pero 155).
-a151
106E:0151 jna 155
106E:0153
Todo esta listo para ejecutar:
Ultima mirada antes de ejecutar:
-u100
106E:0100 BA7803
MOV
DX,0378
106E:0103 EC
IN
AL,DX
106E:0104 BF0002
MOV
DI,0200
106E:0107 E83600
CALL
0140
106E:010A BA0002
MOV
DX,0200
106E:010D B409
MOV
AH,09
106E:010F CD21
INT
21
106E:0111 CC
INT
3

106E:0112 2BC6
muy distinto
106E:0114 8BC8
106E:0116 E87BF4
106E:0119 83F97F
106E:011C 3400
106E:011E 5D
106E:011F 1000
-u140
106E:0140 FC
106E:0141 E80000
106E:0144 D0C0
106E:0146 D0C0
106E:0148 D0C0
106E:014A D0C0
106E:014C 50
106E:014D 240F
106E:014F 3C0A
106E:0151 7602
106E:0153 0406
106E:0155 040A
106E:0157 AA
106E:0158 58
106E:0159 C3
106E:015A 215F5E

SUB

AX,SI

MOV
CALL
CMP
XOR
POP
ADC

CX,AX
F594
CX,+7F
AL,00
BP
[BX+SI],AL

CLD
CALL
ROL
ROL
ROL
ROL
PUSH
AND
CMP
JBE
ADD
ADD
STOSB
POP
RET
AND

; Esto es basura. Puede ser

0144
AL,1
AL,1
AL,1
AL,1
AX
AL,0F
AL,0A
0155
AL,06
AL,0A
AX
[BX+5E],BX

; basura

Ejecutamos paso a paso a partir de CS:100


-t=100 Significa Trace ejecutar la siguiente instruccin
(con el flag T de 8086 a partir de la direccin 100h)
AX=0000 BX=0000 CX=0000 DX=0378 SP=FFEE BP=0000 SI=0000 DI=0000
DS=106E ES=106E SS=106E CS=106E IP=0103 NV UP EI PL NZ NA PO NC
106E:0103 EC
IN
AL,DX
Despus de ejecutar la instruccin en 100 (mov dx,378) el DEBUG escribe el contenido de los registros y
la siguiente instruccin de ejecutar (IN AL,DX). Notar que DX tiene valor 378.
-t
; Sin direccin significa que se ejecuta la siguiente instruccin
AX=0000 BX=0000 CX=0000 DX=0378 SP=FFEE BP=0000 SI=0000 DI=0000
DS=106E ES=106E SS=106E CS=106E IP=0104 NV UP EI PL NZ NA PO NC
106E:0104 BF0002
MOV DI,0200
-t ; Parece trivial, tal como en el puerto 378 haba 00 (AL=00). Seria mucho mas instructivo si haba 0B5h
en AL. Cambiamos el contenido de AL con 0B5h:
-r AX
AX 0000
:00B5
AX=00B5 BX=0000 CX=0000 DX=0378 SP=FFEE BP=0000 SI=0000 DI=0200
DS=106E ES=106E SS=106E CS=106E IP=0107 NV UP EI PL NZ NA PO NC
106E:0107 E83600
CALL 0140
-t ; seguimos
AX=00B5 BX=0000 CX=0000 DX=0378 SP=FFE6 BP=0000 SI=0000 DI=0200
DS=106E ES=106E SS=106E CS=106E IP=0140 NV UP EI NG NZ AC PE CY
106E:0140 FC
CLD
-t ; Seguimos. Observamos que se prepara STOBS, pero nos hemos olvidado de ES. Por suerte ES es
igual a CS y DS.

AX=00B5 BX=0000 CX=0000 DX=0378 SP=FFE6 BP=0000 SI=0000 DI=0200


DS=106E ES=106E SS=106E CS=106E IP=0141 NV UP EI NG NZ AC PE CY
106E:0141 E80000
CALL 0144
-t ; Entramos a escribir un carcter en la memoria.
AX=00B5 BX=0000 CX=0000 DX=0378 SP=FFE4 BP=0000 SI=0000 DI=0200
DS=106E ES=106E SS=106E CS=106E IP=0144 NV UP EI NG NZ AC PE CY
106E:0144 D0C0
ROL AL,1
-t
AX=006B BX=0000 CX=0000 DX=0378 SP=FFE4 BP=0000 SI=0000 DI=0200
DS=106E ES=106E SS=106E CS=106E IP=0146 OV UP EI NG NZ AC PE CY
106E:0146 D0C0
ROL AL,1
-t
AX=00D6 BX=0000 CX=0000 DX=0378 SP=FFE4 BP=0000 SI=0000 DI=0200
DS=106E ES=106E SS=106E CS=106E IP=0148 OV UP EI NG NZ AC PE NC
106E:0148 D0C0
ROL AL,1
-t
AX=00AD BX=0000 CX=0000 DX=0378 SP=FFE4 BP=0000 SI=0000 DI=0200
DS=106E ES=106E SS=106E CS=106E IP=014A NV UP EI NG NZ AC PE CY
106E:014A D0C0
ROL AL,1
-t
AX=005B BX=0000 CX=0000 DX=0378 SP=FFE4 BP=0000 SI=0000 DI=0200
DS=106E ES=106E SS=106E CS=106E IP=014C OV UP EI NG NZ AC PE CY
106E:014C 50
PUSH AX
-t
AX=005B BX=0000 CX=0000 DX=0378 SP=FFE2 BP=0000 SI=0000 DI=0200
DS=106E ES=106E SS=106E CS=106E IP=014D OV UP EI NG NZ AC PE CY
106E:014D 240F
AND AL,0F
-t ; los nibbles (unidades de 4 bits) se han cambiado correcto)
AX=000B BX=0000 CX=0000 DX=0378 SP=FFE2 BP=0000 SI=0000 DI=0200
DS=106E ES=106E SS=106E CS=106E IP=014F NV UP EI PL NZ NA PO NC
106E:014F 3C0A
CMP AL,0A
-t ; en AL esta B el primer dgito de escribir
AX=000B BX=0000 CX=0000 DX=0378 SP=FFE2 BP=0000 SI=0000 DI=0200
DS=106E ES=106E SS=106E CS=106E IP=0151 NV UP EI PL NZ NA PO NC
106E:0151 7602
JBE 0155
-t
AX=000B BX=0000 CX=0000 DX=0378 SP=FFE2 BP=0000 SI=0000 DI=0200
DS=106E ES=106E SS=106E CS=106E IP=0153 NV UP EI PL NZ NA PO NC
106E:0153 0406
ADD AL,06
-t
AX=0011 BX=0000 CX=0000 DX=0378 SP=FFE2 BP=0000 SI=0000 DI=0200
DS=106E ES=106E SS=106E CS=106E IP=0155 NV UP EI PL NZ AC PE NC
106E:0155 0430
ADD AL,30
-t
AX=0041 BX=0000 CX=0000 DX=0378 SP=FFE2 BP=0000 SI=0000 DI=0200

DS=106E ES=106E SS=106E CS=106E IP=0157 NV UP EI PL NZ NA PE NC


106E:0157 AA
STOSB
-t
AX=0041 BX=0000 CX=0000 DX=0378 SP=FFE2 BP=0000 SI=0000 DI=0201
DS=106E ES=106E SS=106E CS=106E IP=0158 NV UP EI PL NZ NA PE NC
106E:0158 58
POP AX
Veamos que hay en la memoria es:200
-d es:200 L1 ; Dump de un byte (L1) a partir de es:200
106E:0200 41
A
--------------HEX-------------------------------COMO ASCII.
Es errneo! Queremos que escriba B de B5. Nos hemos equivocado con la instruccin ADD AL,6, que
tiene que estar ADD AL,7. Corregimos. Buscamos la instruccin:
-u140

(como antes)
-a153
106E:0153 add al,7
-u140 (por sea caso).
. (con instruccin correcta).
-r
; veamos donde estamos
AX=0041 BX=0000 CX=0000 DX=0378 SP=FFE2 BP=0000 SI=0000 DI=0201
DS=106E ES=106E SS=106E CS=106E IP=0158 NV UP EI PL NZ NA PE NC
106E:0158 58
POP AX
; Seguimos.
-t
AX=005B BX=0000 CX=0000 DX=0378 SP=FFE4 BP=0000 SI=0000 DI=0201
DS=106E ES=106E SS=106E CS=106E IP=0159 NV UP EI PL NZ NA PE NC
106E:0159 C3
RET
-t
AX=005B BX=0000 CX=0000 DX=0378 SP=FFE6 BP=0000 SI=0000 DI=0201
DS=106E ES=106E SS=106E CS=106E IP=0144 NV UP EI PL NZ NA PE NC
106E:0144 D0C0
ROL AL,1
; Esto ya lo hemos visto. Andamos un poco mas deprisa.
-u
106E:0144 D0C0
ROL
AL,1
106E:0146 D0C0
ROL
AL,1
106E:0148 D0C0
ROL
AL,1
106E:014A D0C0
ROL
AL,1
106E:014C 50
PUSH
AX
106E:014D 240F
AND
AL,0F
106E:014F 3C0A
CMP
AL,0A
106E:0151 7602
JBE
0155
106E:0153 0407
ADD
AL,07
106E:0155 0430
ADD
AL,30
106E:0157 AA
STOSB
106E:0158 58
POP
AX
106E:0159 C3
RET
; Notar que se desensambla (u de un-assembly) desde la posicin actual (CS:IP).
Vamos hasta RET. En AL es:200..201 podemos ver los caracteres que se han escrito.

-g 159 ; g de GO mas el punto de control (breakpoint) 159. El DEBUG sustituye el contenido de CS:159
con INT 3 y despus ejecuta el programa desde la direccin actual (CS:IP). Notar que la parada del
programa no se garantiza (si el programa no ejecuta la instruccin de CS:159 no hay garanta que va a
parar. Adems 159 puede ser incluso en la mita de una instruccin.
AX=00B5 BX=0000 CX=0000 DX=0378 SP=FFE6 BP=0000 SI=0000 DI=0202
DS=106E ES=106E SS=106E CS=106E IP=0159 NV UP EI PL NZ NA PE NC
106E:0159 C3
RET
-d200 201
; Utilizamos la forma de direccin 200 hasta direccin 201.
106E:0200 41 35
A5
Menos mal el segundo carcter es 5 de B5 es correcto.
-t
AX=00B5 BX=0000 CX=0000 DX=0378 SP=FFE8 BP=0000 SI=0000 DI=0202
DS=106E ES=106E SS=106E CS=106E IP=010A NV UP EI PL NZ NA PE NC
106E:010A BA0002
MOV DX,0200
-t
AX=00B5 BX=0000 CX=0000 DX=0200 SP=FFE8 BP=0000 SI=0000 DI=0202
DS=106E ES=106E SS=106E CS=106E IP=010D NV UP EI PL NZ NA PE NC
106E:010D B409
MOV AH,09
-t
AX=09B5 BX=0000 CX=0000 DX=0200 SP=FFE8 BP=0000 SI=0000 DI=0202
DS=106E ES=106E SS=106E CS=106E IP=010F NV UP EI PL NZ NA PE NC
106E:010F CD21
INT 21
; En este punto es necesario ver si todo esta correcto en la memoria DS:200.
-d200 ; Sin longitud el DEBUG nos imprime 80 bytes.
106E:0200
106E:0210
106E:0220
106E:0230
106E:0240
106E:0250
106E:0260
106E:0270

41
00
3B
D2
0B
D5
2F
D8

35
03
75
80
00
E2
E7
B0

D7
F1
F6
3E
E8
00
BB
FF

D7
E8
4E
43
59
74
40
86

C3
03
C3
04
00
F7
00
47

BE
00
1E
00
5F
1E
BA
18

BC
3C
52
75
5E
0E
01
A2

DB-8B
0D-C3
50-53
0D-F6
59-5B
1F-BE
00-33
18-00

4C
AC
51
06
58
D5
FF
C3

05
E8
56
21
5A
E2
CD
0E

8B
04
57
04
1F
E8
21
1F

74
F9
2E
FF
C3
98
1F
E8

09
75
8E
75
2E
02
72
D2

E8
04
1E
06
80
2E
0B
00

08
3C
FE
E8
3E
A1
8B
3D

A5.......L..t...
......<......u.<
;u.N..RPSQVW....
..>C..u...!..u..
...Y._^Y[XZ....>
...t............
/..@....3..!.r..
....G..........=

; ERRROOOORRR!! La cadena no termina con $. Si ejecutamos int 21 puede ocurrir cualquier cosa.
; Otro error escribimos en ES:DI pero imprimimos de DS:DI. Por suerte el DEBUG asigna el mismo
valor de todos los registros del segmento.
Cambiamos el contenido de la memoria. Aadimos CR LF y $.
-e202
106E:0202 0D.0d 0A.a
Despus de 0d tenemos de teclear espacio. Despus del ultimo byte tenemos de teclear salto de linea.
Entramos $ como smbolo:
-e204 $
Comprobamos
-d200
106E:0200 41 35 0D 0A 24 BE BC DB-8B 4C 05 8B 74 09 E8 08 A5..$....L..t...
.
Ahora esta bien.
-r ; donde estamos
AX=09B5 BX=0000 CX=0000 DX=0200 SP=FFE8 BP=0000 SI=0000 DI=0202
DS=106E ES=106E SS=106E CS=106E IP=010F NV UP EI PL NZ NA PE NC
106E:010F CD21
INT 21
Estamos antes de ejecutar INT 21h con AH=9 y DX=200. Tenemos que ejecutar esta instruccin pero no
nos interesa de entrar en DOS. Por esto ejecutamos INT 21 no con t pero con p. El comando p sustituye la

siguiente instruccin con INT 3 (que en este caso es tambin INT 3) y ejecuta el programa como si
entramos G.
-p
A5
AX=0924 BX=0000 CX=0000 DX=0200 SP=FFE8 BP=0000 SI=0000 DI=0202
DS=106E ES=106E SS=106E CS=106E IP=0111 NV UP EI PL NZ NA PE NC
106E:0111 CC
INT 3
Bien! El programa escribe A5 (despus de la lnea de p), como debe ser (casi, tal como tiene que escribir
B5).
Tal como hemos ayudando al programa a mano de conseguir su tarea, corregimos aadiendo un patch
en 180 (a partir de este momento no escribo los comandos U necesarios):
-a180
106E:0180 push ds
106E:0181 pop es
106E:0182 call 140
106E:0185 mov al,d
; el CR
106E:0187 stosb
106E:0188 mov al,a
; El LF
106E:018A stosb
106E:018B mov al,24
; El $. Podemos verlo en la memoria ES:204
106E:018D stosb
106E:018E ret
106E:018F
-a107
106E:0107 call 180
; entramos en el patch y no en 140
106E:010A
ponemos en puerto 378 el valor que vamos a escribir:
-o378 5D ; esto es equivalente al programa: MOV DX,378h // MOV al,5Dh // OUT dx,al
Comprobamos el contenido del puerto:
-i378 ; Esto es casi equivalente al nuestro programa
5D
; Correcto, tal como el puerto es un simple I/O buffer.
Ejecutamos
-g=100 107 ; esta parte ya la sabemos
Un poco mas despacio con la nueva parte.
AX=095D BX=0000 CX=0000 DX=0378 SP=FFE2 BP=0000 SI=0000 DI=0200
DS=106E ES=106E SS=106E CS=106E IP=0107 NV UP DI PL NZ NA PE NC
106E:0107 E87600
CALL 0180
-t
AX=095D BX=0000 CX=0000 DX=0378 SP=FFE0 BP=0000 SI=0000 DI=0200
DS=106E ES=106E SS=106E CS=106E IP=0180 NV UP DI PL NZ NA PE NC
106E:0180 1E
PUSH DS
-t
AX=095D BX=0000 CX=0000 DX=0378 SP=FFDE BP=0000 SI=0000 DI=0200
DS=106E ES=106E SS=106E CS=106E IP=0181 NV UP DI PL NZ NA PE NC
106E:0181 07
POP ES
-t
AX=095D BX=0000 CX=0000 DX=0378 SP=FFE0 BP=0000 SI=0000 DI=0200
DS=106E ES=106E SS=106E CS=106E IP=0182 NV UP DI PL NZ NA PE NC
106E:0182 E8BBFF
CALL 0140
Con esto a toda marcha. Ya lo sabemos.

-p
AX=095D BX=0000 CX=0000 DX=0378 SP=FFE0 BP=0000 SI=0000 DI=0202
DS=106E ES=106E SS=106E CS=106E IP=0185 NV UP DI PL NZ NA PE NC
106E:0185 B00D
MOV AL,0D
-t
AX=090D BX=0000 CX=0000 DX=0378 SP=FFE0 BP=0000 SI=0000 DI=0202
DS=106E ES=106E SS=106E CS=106E IP=0187 NV UP DI PL NZ NA PE NC
106E:0187 AA
STOSB
-t
AX=090D BX=0000 CX=0000 DX=0378 SP=FFE0 BP=0000 SI=0000 DI=0203
DS=106E ES=106E SS=106E CS=106E IP=0188 NV UP DI PL NZ NA PE NC
106E:0188 B00A
MOV AL,0A
-t
AX=090A BX=0000 CX=0000 DX=0378 SP=FFE0 BP=0000 SI=0000 DI=0203
DS=106E ES=106E SS=106E CS=106E IP=018A NV UP DI PL NZ NA PE NC
106E:018A AA
STOSB
-t
AX=090A BX=0000 CX=0000 DX=0378 SP=FFE0 BP=0000 SI=0000 DI=0204
DS=106E ES=106E SS=106E CS=106E IP=018B NV UP DI PL NZ NA PE NC
106E:018B B024
MOV AL,24
-t
AX=0924 BX=0000 CX=0000 DX=0378 SP=FFE0 BP=0000 SI=0000 DI=0204
DS=106E ES=106E SS=106E CS=106E IP=018D NV UP DI PL NZ NA PE NC
106E:018D AA
STOSB
-t
AX=0924 BX=0000 CX=0000 DX=0378 SP=FFE0 BP=0000 SI=0000 DI=0205
DS=106E ES=106E SS=106E CS=106E IP=018E NV UP DI PL NZ NA PE NC
106E:018E C3
RET
-t
Comprobamos la memoria
-d200
106E:0200 35 44 0D 0A 24 BE BC DB-8B 4C 05 8B 74 09 E8 08 5D..$....L..t...
.
Y a toda marcha hasta el final.
-g
5D
AX=0924 BX=0000 CX=0000 DX=0200 SP=FFE2 BP=0000 SI=0000 DI=0205
DS=106E ES=106E SS=106E CS=106E IP=0111 NV UP DI PL NZ NA PE NC
106E:0111 CC
INT 3
Lo hemos conseguido. Lo nico malo de esta programa de DOS es que no termina correcto.
Arreglamos el problema:
-a111
106E:0111 int 20
Ahora ejecutamos desde el principio:
-g=100 ; ejecutamos desde direccin CS:100 sin paradas.
Salvamos el programa en el disco.

-r CX ; En BX:CX 4 bytes de longitud del fichero. Cuidado con BX!


CX 0000
:100 ; Todo el cdigo nuestro esta desde 100 (por defecto) hasta 200h la longitud el de 100h bytes.
Damos un nombre (see378.com) del fichero:
-nsee378.com
Escribimos el fichero:
-w
Salimos del DEBUG:
-q
Ahora tenemos programa SEE378.COM, tal como empieza en 100h, es menos de 32K y el fichero tiene
extensin .COM. El programa que escribe el contenido del puerto 378 en la pantalla. Ejecutamos:
C:\>see378
5D
Efectivamente. Si queremos volver a manejar este programa con DEBUG, podemos ejecutar:
C:\>debug see378.com
-u100.

Lista de los comandos de DEBUG utilizados:


-q Salir del programa
-? Pedir ayuda.
-d Dump de memoria.
-e Edit (cambio) de memoria.
-a ensamblador de lenguaje de maquina 8086
-u Un - ensamblador de lenguaje de maquina 8086.
-t Ejecutar paso a paso
-p Ejecutar la siguiente instruccin sin entrar en ella (CALL o INT).
-g Ejecutar desde una direccin con paradas (breakpoints).
-r Ver/cambiar registro.
-n Dar nombre de fichero.
-w Escribir en un fichero.

También podría gustarte