Académique Documents
Professionnel Documents
Culture Documents
Departamento de Automática.
Universidad de Alcalá.
Se trata de una utilidad muy poco amigable, sin menús y -sólo en versiones recientes- con ayuda
mínima, pero una vez aprendidos unos cuantos comandos es extremadamente potente. Hay quien
lo considera como el mejor programa que ha hecho Microsoft.
Debug, invocado sin parámetros, se carga y pasa a mostrar un lacónico guión, a la espera de
órdenes del usuario. Todas -a excepción de las relativas a operaciones con memoria expandida,
que no se verán aquí- constan de una única letra seguida o no de parámetros. Si se va a
desensamblar un programa, se le puede indicar a debug que lo cargue también tras cargarse él
escribiendo:
En la siguiente línea aparecerá un guión, éste es el indicador del Debug, en este momento se
pueden introducir las instrucciones del Debug. Utilizando los comandos:
A: ASSEMBLE
Cuando se utiliza este comando se le puede dar como parámetro la dirección donde se desea que
se inicie el ensamblado, si se omite el parámetro el ensamblado se iniciará en la localización
especificada por CS:IP, usualmente 0100H, que es la localización donde deben iniciar los
programas con extensión .COM, y será la localización que utilizaremos debido a que debug solo
puede crear este tipo específico de programas.
También se le puede decir qué zona se desea ver con a <direccion> pudiendo ser la dirección
absoluta (a segmento:desplazamiento) o relativa al segmento de código actual (a
desplazamiento).
Parámetros: <dir_comienzo>
Ejemplo: Vamos a usar la instrucción MOV, que como veremos más adelante, sirve para copiar
datos de la memoria a los registros y viceversa, además de copiar datos entre registros, que es
justo lo que vamos a usar en el ejemplo.
-a
2048:0106 mov ax,bx
Como veremos más adelante, la instrucción 'U' sirve para hacer volcados de memoria, pero no
viendo el contenido de la misma, sino interpretándola como instrucciones en lenguaje
ensamblador.
; Ejemplo 2
-r cs
CS 2048
:2050
-a 200
2050:0200 mov ax,bx
2050:0202
-u 200 200
2050:0200 89D8 MOV AX,BX
D: DUMP
Parámetros: <dir_1> ; Dirección de comienzo del volcado [<dir_2>] ; Dirección final del
volcado.
Resultado: Presenta por pantalla el contenido de las direcciones de memoria entre DS:<dir_1> y
DS:<dir_2> ( si no se ha especificado el segundo parámetro, nos hace un volcado desde <dir_1>
Ejemplo:
-d 100
2048:0100 92 D3 3D 64 00 77 0B 3D-50 00 73 03 05 64 00 05 ..=d.w.=P.s..d..
2048:0110 6C 07 A3 BF E1 E8 4C 00-B0 08 F8 5F 34 00 37 20 l.....L...._4.7
2048:0120 FF EB F8 33 C0 51 B9 0A-00 80 3C 30 72 12 80 3C ...3.Q....<0r..<
2048:0130 39 77 0D F6 E1 02 04 80-D4 00 2D 30 00 46 EB E9 9w........-0.F..
2048:0140 59 C3 AC 3A 06 2B E1 74-0E 3C 2F 74 0A 3C 2D 74 Y..:.+.t.<-t
2048:0150 06 3C 2E 74 02 F9 C3 80-3C 30 72 F9 80 3C 39 77 .<.t....<0r..<9w
2048:0160 F4 F8 EB F2 50 53 8B 1E-8E D3 B8 C6 DB E8 31 FE ....PS........1.
2048:0170 3B 77 09 77 03 5B 58 C3-FF 06 8E D3 8B 1E 8E D3 ;w.w.[X.........
-d 100 110
2048:0100 92 D3 3D 64 00 77 0B 3D-50 00 73 03 05 64 00 05 ..=d.w.=P.s..d..
2048:0110 6C l
E DIRECCION: EDIT
Permite editar, byte por byte, una zona de memoria. Muestra -en hexadecimal- el byte de esa
posición 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 edición se pulsa INTRO.
Ejemplo:
-e 100 00 01 02
-d 100 102
2048:0100 00 01 02 ...
; Ejemplo 2
-e 100
2048:0100 00. 01.04 02.05 64.
-d 100 103
2048:0100 00 04 05 64 ...d
F: FILL
Llena una zona de memoria con un valor determinado. Como al terminar un programa la zona de
memoria en que se residía no se borra (poniéndola a cero, por ejemplo), a menudo es útil para
distinguir entre lo que son datos del programa actual y lo que es basura del anterior.
Ejemplo:
-f 100 105 66
-d 100 105
2048:0100 66 66 66 66 66 66 ffffff
Ejemplo:
-f 100 FFFF 0
Llena de ceros lo que hay desde la posición 100 (hexadecimal) hasta el final del segmento.
G: GO
Sin parámetros, empieza a ejecutar desde la posición cs:ip hasta que se acabe el programa. Si la
orden es "g <direccion>", la ejecución empieza en cs:ip y termina (debug pone un break point)
justo antes de ejecutar la instrucción que se encuentra en <direccion>.
Ejemplo: Vamos a usar una interrupción de MS-DOS para presentar una letra por pantalla, esta
subrutina es el servicio 02h de la interrupción 21h, y pasándole como parámetro el valor
hexadecimal del carácter ASCII a.
-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 92 XCHG DX,AX
-a 100 2048:0100 mov ax,0200
2048:0103 mov dl,61
2048:0105 int 21
2048:0107
-g 107
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
Muestra por pantalla el resultado (en hexadecimal) de las operaciones num1+num2 y num1-
num2.
Uso: la instrucción "H <op_1> <op_2>" nos devuelve la suma y la resta ( en complemento a dos
) de los dos operandos suministrados
Ejemplo:
-h 0003 0002
0005 0001
-h 0000 0001
0001 FFFF
L: LOAD
Ejemplo: voy a leer el sector 0 del disco A y lo vuelco a partir de la dirección DS:100, ( ESTO
NO QUIERE DECIR QUE OS TENGA QUE SALIR LO MISMO EN VUESTRO VOLCADO )
-l 100 0 0 1
-d 100 300
2048:0100 EB 3E 90 29 79 3B 46 5D-49 48 43 00 02 01 01 00 .>.)y;F]IHC.....
2048:0110 02 E0 00 40 0B F0 09 00-12 00 02 00 00 00 00 00 ...@............
2048:0120 00 00 00 00 00 00 29 5D-46 DB 1C 4E 4F 20 4E 41 ......)]F..NO NA
2048:0130 4D 45 20 20 20 20 46 41-54 31 32 20 20 20 F1 7D ME FAT12 .}
2048:0140 FA 33 C9 8E D1 BC FC 7B-16 07 BD 78 00 C5 76 00 .3.....{...x..v.
2048:0150 1E 56 16 55 BF 22 05 89-7E 00 89 4E 02 B1 0B FC .V.U."..~..N....
2048:0160 F3 A4 06 1F BD 00 7C C6-45 FE 0F 8B 46 18 88 45 ......|.E...F..E
2048:0170 F9 FB 38 66 24 7C 04 CD-13 72 3C 8A 46 10 98 F7 ..8f$|...r<.F...
2048:0180 66 16 03 46 1C 13 56 1E-03 46 0E 13 D1 50 52 89 f..F..V..F...PR.
2048:0190 46 FC 89 56 FE B8 20 00-8B 76 11 F7 E6 8B 5E 0B F..V.. ..v....^.
2048:01A0 03 C3 48 F7 F3 01 46 FC-11 4E FE 5A 58 BB 00 07 ..H...F..N.ZX...
2048:01B0 8B FB B1 01 E8 94 00 72-47 38 2D 74 19 B1 0B 56 .......rG8-t...V
2048:01C0 8B 76 3E F3 A6 5E 74 4A-4E 74 0B 03 F9 83 C7 15 .v>..^tJNt......
2048:01D0 3B FB 72 E5 EB D7 2B C9-B8 D8 7D 87 46 3E 3C D8 ;.r...+...}.F><.
2048:01E0 75 99 BE 80 7D AC 98 03-F0 AC 84 C0 74 17 3C FF u...}.......t.<.
2048:01F0 74 09 B4 0E BB 07 00 CD-10 EB EE BE 83 7D EB E5 t............}..
2048:0200 BE 81 7D EB E0 33 C0 CD-16 5E 1F 8F 04 8F 44 02 ..}..3...^....D.
2048:0210 CD 19 BE 82 7D 8B 7D 0F-83 FF 02 72 C8 8B C7 48 ....}.}....r...H
2048:0220 48 8A 4E 0D F7 E1 03 46-FC 13 56 FE BB 00 07 53 H.N....F..V....S
2048:0230 B1 04 E8 16 00 5B 72 C8-81 3F 4D 5A 75 A7 81 BF .....[r..?MZu...
2048:0240 00 02 42 4A 75 9F EA 00-02 70 00 50 52 51 91 92 ..BJu....p.PRQ..
2048:0250 33 D2 F7 76 18 91 F7 76-18 42 87 CA F7 76 1A 8A 3..v...v.B...v..
2048:0260 F2 8A 56 24 8A E8 D0 CC-D0 CC 0A CC B8 01 02 CD ..V$............
2048:0270 13 59 5A 58 72 09 40 75-01 42 03 5E 0B E2 CC C3 .YZXr.@u.B.^....
2048:0280 03 18 01 27 0D 0A 44 69-73 63 6F 20 69 6E 63 6F ...'..Disco inco
2048:0290 72 72 65 63 74 6F 20 20-20 FF 0D 0A 45 72 72 6F rrecto ...Erro
2048:02A0 72 20 45 2F 53 20 20 20-20 20 FF 0D 0A 43 61 6D r E/S ...Cam
2048:02B0 62 69 65 20 65 6C 20 64-69 73 63 6F 20 79 20 70 bie el disco y p
2048:02C0 72 65 73 69 6F 6E 65 20-75 6E 61 20 74 65 63 6C resione una tecl
2048:02D0 61 20 20 20 20 0D 0A 00-49 4F 20 20 20 20 20 20 a ...IO
2048:02E0 53 59 53 4D 53 44 4F 53-20 20 20 53 59 53 80 01 SYSMSDOS SYS..
2048:02F0 00 57 49 4E 42 4F 4F 54-20 53 59 53 00 00 55 AA .WINBOOT SYS..U.
2048:0300 BE .
P: STEP
Trace puede ser incómodo si no se quiere depurar el código de las rutinas de interrupción , o si ya
se sabe el código que hay en las subrutinas y tan sólo interesa seguir avanzando sin entrar en
ellas. En estos casos se usa p.
Resultados: es como el comando 'T' sin embargo si llamamos a una subrutina y usáramos el
comando 'T' entraríamos dentro del código de la subrutina, por lo que si ejecutamos una
interrupción de MS-DOS no sabríamos 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
Q: QUIT
R: REGISTERS
Sin parámetros, muestra el contenido de los registros de la CPU, así como la próxima instrucción
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 más lo deja como estaba.
Parámetros: [registro]
Registro de flags: Para poder cambiar el registro de flags, hay que usar el comando "H F" y
aparecerá algo tal que así:
Desbordamiento ( si/no)
Poner: OV Quitar: NV
Direccion(reducción / incremento)
poner: DN quitar UP
Interrupción(activar/desactivar)
poner: EI quitar: DI
Cero ( sí / no)
poner: ZR quitar: NZ
Acarrero Auxiliar ( sí / no )
poner: AC quitar: NA
Acarreo (sí / no )
poner: CY quitar: NC
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 92 XCHG DX,AX
; Ejemplo 2
-r ax
AX 0000
:01
-r
AX=0001 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 92 XCHG DX,AX
S: SEARCH
Busca una secuencia de bytes o una cadena en el rango especificado, mostrando la dirección en
que aparece en pantalla. s 100 500 cd 13 Busca todas las llamadas a la interrupción 13h
(código máquina cdh 13h). s 100:0 ffff "virus" muestra las zonas de memoria del segmento
100h en que aparece la palabra "virus".
T: TRACE
Ejecuta la instrucción apuntada por cs:ip y vuelve a debug. Permite ejecutar paso a paso un
programa y observar en cada instrucción el efecto producido. Si haciendo "trace" se llega a una
subrutina (CALL) o a una interrupción (INT) la siguiente instrucción que se ejecutará será la
primera de la subrutina o la primera de la rutina de atención de la interrupción correspondiente.
Parámetros: [< =dirección>] ; Dirección a partir de la cual se quiere que se tracee (OJO: HAY
QUE PONER EL '=' ) <num_instrucciones> ; Número de instrucciones que hay que ejecutar
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
U : UNASSEMBLE
Ejemplo:
-u 100 11e
2050:0100 7403 JZ 0105
2050:0102 E97F00 JMP 0184
2050:0105 8B4EFA MOV CX,[BP-06]
2050:0108 E303 JCXZ 010D
2050:010A B90200 MOV CX,0002
2050:010D 83C108 ADD CX,+08
2050:0110 B82871 MOV AX,7128
2050:0113 50 PUSH AX
2050:0114 51 PUSH CX
2050:0115 9A1A025D2F CALL 2F5D:021A
2050:011A 0BC0 OR AX,AX
2050:011C 7463 JZ 0181
2050:011E 8B3E2A71 MOV DI,[712A]
; Ejemplo 2
-u 100
2050:0100 7403 JZ 0105
2050:0102 E97F00 JMP 0184
2050:0105 8B4EFA MOV CX,[BP-06]
2050:0108 E303 JCXZ 010D
2050:010A B90200 MOV CX,0002
2050:010D 83C108 ADD CX,+08
2050:0110 B82871 MOV AX,7128
2050:0113 50 PUSH AX
2050:0114 51 PUSH CX
2050:0115 9A1A025D2F CALL 2F5D:021A
2050:011A 0BC0 OR AX,AX
2050:011C 7463 JZ 0181
2050:011E 8B3E2A71 MOV DI,[712A]
W: WRITE
La sintaxis completa es w [dirección] [unidad] [sector] [n sectores] Con todos los parámetros
escribe en la unidad y sectores dados el contenido de la dirección de memoria.
Pasándole sólo la dirección escribe en el fichero definido con n tantos bytes como determinen el
par de registros BX:CX a partir de la posición de memoria dada.
?: AYUDA?
Existen algunas órdenes más para tratar con memoria expandida y otras operaciones que no serán
de especial relevancia para el tema que nos ocupa.
Es posible cambiar el valor del registro de banderas, así como utilizarlo como estructura de
control en nuestros programas como se verá mas adelante. Cada bit del registro tiene un nombre y
significado especial, la lista dada a continuación describe el valor de cada bit, tanto apagado
como prendido y su relación con las operaciones del procesador:
Overflow
NV = no hay desbordamiento;
OV = sí lo hay
Direction
UP = hacia adelante;
DN = hacia atras;
Interrupts
DI = desactivadas;
EI = activadas
Sign
PL = positivo;
NG = negativo
Zero
NZ = no es cero;
ZR = sí lo es
Auxiliary Carry
NA = no hay acarreo auxiliar;
AC = hay acarreo auxiliar
Parity
PO = paridad non;
PE = paridad par;
Carry
NC = no hay acarreo;
CY = Sí lo hay
Para asentar ideas y de paso aprender algunos pasos útiles a los que se hará referencia varias
veces, unos ejemplos.
Ejemplo completo:
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
106E:014C 50 PUSH AX
-t
-a153
106E:0153 add al,7
-u140 (por sea caso).
…. (con instrucción 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
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 después ejecuta el programa desde la dirección actual (CS:IP). Notar que la
parada del programa no se garantiza (si el programa no ejecuta la instrucción de CS:159 no
hay garantía que va a parar. Además 159 puede estar incluso en la mitad de una instrucción.
106E:0200 41 35 A5
Menos mal – el segundo carácter es 5 de ‘B5’ – es correcto.
-t
Estamos antes de ejecutar INT 21h con AH=9 y DX=200. Tenemos que ejecutar esta instrucción
pero no nos interesa entrar en DOS. Por esto ejecutamos INT 21 no con t pero con p. El
comando p sustituye la siguiente instrucción con INT 3 (que en este caso es también INT 3) y
ejecuta el programa como si entramos G.
-p
A5
Ejecutamos
-g=100 107 ; esta parte ya la sabemos
Un poco mas despacio con la nueva parte.
106E:0180 1E PUSH DS
-t
-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...
….
Lo hemos conseguido. Lo único malo de este ‘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 dirección 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 código 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 el programa SEE378.COM, tal como empieza en 100h, es menos de 32K y el
fichero tiene extensión .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.
-? – 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 instrucción sin entrar en ella (CALL o INT).
-g – Ejecutar desde una dirección con paradas (breakpoints).
-r – Ver/cambiar registro.
-n – Dar nombre de fichero.
-w – Escribir en un fichero.