Una vez que el programa
está en ejecución, el indicador ("prompt") es un
guión "-", indicando que el "Shell" ( ) espera
recibir órdenes. Para salir basta pulsar una
Q. Como muchos programas de su
género,
sus comandos empiezan
por una letra o combinación de ellas (pueden usarse
indistintamente mayúsculas o minúsculas) y ciertos
parámetros opcionales (no es imprescindible separar la
letra de opción de los parámetros opcionales que
siguen). La opción más sencilla es la
interrogación ?, cuyo resultado es una lista
resumida de las opciones disponibles:
ensamblar A [dirección]
comparar C dirección de
intervalo
volcar D
[intervalo]
escribir E dirección [lista
de valores]
llenar F lista de
intervalos
ir
G [=dirección] [direcciones]
hex H
valor1 valor2
entrada I puerto
cargar L
[dirección] [unidad] [primer_sector] [número]
mover M
dirección de intervalo
nombre N [nombre_ruta]
[lista_argumentos]
salida O byte de
puerto
proceder P [=dirección]
[número]
salir Q
registrar R [registrar]
buscar S lista de
intervalos
seguimiento T [=dirección] [valor]
desensamblar U [intervalo]
escribir W [dirección]
[unidad] [primer_sector] [número]
asignar memoria
expandida
XA [#páginas]
desasignar memoria
expandida
XD [identificador]
asignar páginas de memoria expandida XM
[Lpágina] [Ppágina] [identificador]
mostrar estado de
la memoria
expandida XS
La mayoría de los comandos de debug ejecutan una
acción
y vuelven al indicador del shell, pero si es un comando largo,
como puede ser mostrar un trozo grande de código,
puede detenerse pulsando CTRL-Pausa o interrumpirse con CTRL-C
para volver al shell.
Una característica poco conocida, es que debug
puede aceptar entradas desde un fichero "Script", que puede ser
un simple fichero de texto ASCII en el que
cada comando esté separado del anterior por un
INTRO. Después del último, que debe ser una
"Q" para salir de debug, es conveniente dejar una
línea en blanco pulsando INTRO dos veces. Las
líneas pueden contener comentarios. Cualquier cosa a
partir del carácter punto y coma (;) hasta el
final de la línea, será ignorado.
; esto es un comentario
D ; aquí se mostrará algo…
Suponiendo que tengamos un fichero "Script" de nombre
Ordenes.txt, puede ser utilizado como entrada para
debug mediante un comando de redirección en la
siguiente forma:
DEBUG < Ordenes.txt
También puede conseguirse que el programa redireccione
la salida hacia un fichero que puede ser inspeccionado más
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 podría obtenerse un fichero Result.txt con el
siguiente comando:
DEBUG < Ordenes.txt > Result.txt
§3
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.
§4 Entradas
& Salidas
DEBUG asume que los datos
numéricos proporcionados son hexadecimales, y cuando se
trate de direcciones de memoria, deben introducirse en forma
segmentada (
H5.1). A su vez, los resultados son mostrados
también 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:
177C:0180 01 21 10 03 41 10 05 61-10 07 81 10 09 A1 10
0B .!..A..a……..
177C:0190 C1 10 0D E1 10 0F 01 11-11 21 11 13 41 11 15
61 ………!..A..a
177C:01A0 11 17 81 11 19 A1 11 1B-C1 11 1D E1 11 1F 01
12 …………….
177C:01B0 21 21 12 23 41 12 25 61-12 27 81 12 29 A1 12
2B !!.#A.%a.'..)..+
177C:01C0 C1 12 2D E1 12 2F 01 13-31 21 13 33 41 13 35
61 ..-../..1!.3A.5a
177C:01D0 13 37 81 13 39 A1 13 3B-C1 13 3D E1 13 3F 01
14 .7..9..;..=..?..
177C:01E0 41 21 14 43 41 14 45 61-14 47 81 14 49 A1 14
4B A!.CA.Ea.G..I..K
177C:01F0 C1 14 4D E1 14 4F 01 15-51 21 15 53 41 15 55
61 ..M..O..Q!.SA.Ua
Cada fila muestra 16 posiciones de memoria a partir de la
posición señalada por las columnas de la izquierda,
que las muestran como desplazamiento:segmento. El bloque
central muestra el contenido hexadecimal de cada byte, mientras
que el bloque derecho contiene la representación
ASCII. Por ejemplo, la 5ª fila muestra el contenido de
las posiciones 177C:01C0 a 177C:01CF (ambas inclusive). Sus
dos últimos bytes contienen respectivamente los caracteres
5 y a, que corresponden a las cantidades 35h y 61h
del bloque central. Que como sabemos ( E2.2.1a), equivalen a
los decimales 53 y 97, que son precisamente los valores
ASCII de los caracteres mencionados.
Nota: Por razón de que éste tipo de
salida pueda ser listado a impresora, el
bloque derecho no contiene en realidad la
representación ASCII de todos los caracteres (algunos ni
siquiera tienen una representación 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
carácter imprimible. Esto no significa que
dichas posiciones representen efectivamente tales valores para la
aplicación que las utiliza. Por ejemplo, puede que en
realidad, las dos posiciones de memoria mencionadas (dos
octetos), en vez de los caracteres 5 y a,
representen una palabra de 16 bits en formato Little Endian
( E2.2.6a), que a su vez
representan una cantidad entera (un número).
§5
Comandos
Aunque su descripción completa llenaría todo
un capítulo [2], a
continuación comentamos algunas de las opciones más
interesantes relativas a inspección del código y de
contenidos de memoria.
§5.1 La opción D ("Dump")
permite obtener un volcado del contenido de la memoria (de
debug). La sintaxis acepta dos formas:
D [dirección-inicial] [L
posiciones-desde-dirección-inicial]
D [direccion-inicial][direccion-final]
Naturalmente, para que exista algo en el bufer de
memoria (al principio quizás solo contiene basura) es
preciso indicarle que lea algo. Este algo puede ser un
rango de direcciones de memoria RAM; una
dirección absoluta de disco (sector); un fichero, o el
contenido de los registros del
procesador.
Para empezar puede indicársele que cargue un fichero
xxx.xyz, que tenemos en el directorio actual o en el PATH, cuyo
contenido queremos ver.
C:> debug xxx.xyz
-D
aquí se obtendría una salida análoga a la
comentada .
Hemos visto un ejemplo al tratar de los servicios de
interrupciones del PC ( Servicios-BIOS),
aquí mostraremos otro. Sabemos que el punto de
inicio de la BIOS es la
dirección F000:FFF0 ( H4.1), y que desde
esta posición 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 mi equipo es:
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 línea 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 dirección
suficientemente alejada del final de la memoria, sin indicar
ningún número de posiciones, por defecto se toma el
valor 128 (8 filas de 16 posiciones). Si desea una cantidad
distinta, hay que añadir una L ("Long") y el
número de posiciones, hasta un máximo de 64 KB
(FFFF). Todos los números 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:
FE00:0000 41 77 61 72 64 20 53 6F-66 74 77 61 72 65 49
42 Award SoftwareIB
FE00:0010 4D 20 43 4F 4D 50 41 54-49 42 4C 45 20 34 38
36 M COMPATIBLE 486
FE00:0020 20 42 49 4F 53 20 43 4F-50 59 52 49 47 48 54
20 BIOS COPYRIGHT .
FE00:0030 41 77 61 72 64 20 53 6F-66 74 77 61 72 65 20
49 Award Software I
FE00:0040 6E 63 2E 6F 66 74 77 61-72 65 20 49 6E 63 2E
20 nc.oftware Inc. .
FE00:0050 41 77 03 0C 04 01 01 6F-66 74 77 E9 12 14 20
43 Aw…..oftw… C
FE00:0060 1C 41 77 61 72 64 20 4D-6F 64 75 6C 61 72 20
42 .Award Modular B
FE00:0070 49 4F 53 20 76 34 2E 35-31 50 47 4D 00 8E 32
EC IOS v4.51PGM..2.
Sabemos que esta zona corresponde al área de la
BIOS del Sistema…
§5.2 Otra opción muy interesante nos
permite buscar determinados contenidos a través de la
memoria utilizando el prefijo S ("Search"). Existen
dos sintaxis alternativas:
S direccion-de-inicio L longitud-a-explorar
contenido-a-buscar
S direccion-de-inicio direccion-final L contenido-a-buscar
El contenido debe ser proporcionado en hexadecimal (tal como
aparecería en la columna central del ejemplo anterior) o
entre comillas si es un texto ASCII. Por ejemplo, en un
equipo IBM, deseo ver algunas características de la
BIOS. Se que estos datos se alojan a partir de la
posición F000:0000 hasta el final de la memoria. Es
decir, una longitud de 64 Kbytes (FFFF) a partir de la
posición de inicio, y que seguramente, los datos buscados
estarán cerca de la identificación de la propia
BIOS (la cadena "IBM"). Por lo que utilizo la siguiente
sintaxis [3]:
-s f000:0000 L ffff "IBM"
y obtengo la siguiente salida:
F000:3A0C
F000:3A70
F000:3B13
F000:4839
F000:48BA
F000:492A
F000:499A
F000:4A0A
con las direcciones donde se ha encontrado la ocurrencia
buscada. A continuación puedo explorar las
proximidades de cada posición. Por ejemplo para la
primera:
-D f000:3a00
F000:3A00 61 73 65 20 36 2E 30 20-66 6F 72 20 49 42 4D
20 ase 6.0 for IBM
F000:3A10 54 68 69 6E 6B 50 61 64-00 20 20 20 20 20 00
43 ThinkPad. .C
F000:3A20 6F 70 79 72 69 67 68 74-20 31 39 38 35 2D 31
39 opyright 1985-19
F000:3A30 39 39 20 50 68 6F 65 6E-69 78 20 54 65 63 68
6E 99 Phoenix Techn
F000:3A40 6F 6C 6F 67 69 65 73 20-4C 74 64 2E 0D 41 6C
6C ologies Ltd..All
F000:3A50 20 52 69 67 68 74 73 20-52 65 73 65 72 76 65
64 Rights Reserved
F000:3A60 0D 0D 28 43 29 20 43 4F-50 59 52 49 47 48 54
20 ..(C) COPYRIGHT
F000:3A70 49 42 4D 20 43 4F 52 50-4F 52 41 54 49 4F 4E
20 IBM CORPORATION
§5.3 Si lo que se busca está en un
fichero, primero hay que cargarlo. Lo que se puede hacer de
dos formas: en la propia invocación de debug,
o mediante los comandos N y L. Por ejemplo,
si queremos inspeccionar el contenido del fichero
more.com, podemos utilizar dos formas:
C:WINDOWS>debug c:windowscommandmore.com
C:WINDOWS>debug
– N c:windowscommandmore.com
– L
La sintaxis para el prefijo N es:
N [path-name]nombre-de-fichero
En ambos casos el contenido del fichero será cargado en
memoria y podrá ser utilizado. Atención: después de la orden L
("Load"), debug le avisará si no encuentra el
fichero, pero seguirá su funcionamiento. En tal caso
simplemente piensa que N señala el nombre de un
nuevo fichero que creará, con el contenido de la memoria
-de debug-, cuando posteriormente seleccione la
opción escribir W ("Write").
Nota: Como ya habrá deducido, debug
permite leer un fichero, realizar modificaciones en él
(con la opción E) y escribir el fichero modificado
bajo otro nombre con N/W.
A continuación podemos comprobar el tamaño
del fichero cargado. Para ello usamos la opción
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, señala el
tamaño del fichero en bytes. También
podíamos haber utilizado directamente el comando R CX que
nos proporciona el valor de dicho registro:
-R CX
CX 2917
:
–
Nota: A continuación del valor
correspondiente, debug muestra dos puntos (:),
señalando que puede cambiar el valor del registro
introduciendo un nuevo número. Pulse INTRO para
dejar las cosas como están y volver al "prompt" (-) de
debug.
Al llegar a este punto, es importante señalar que, a
excepción de los ficheros .exe, debug carga
los ficheros a partir de la dirección 100h (256d) de "su"
memoria. De forma que el primer octeto del fichero se carga
en la dirección 100; el segundo en 101; etc. En
nuestro caso, el fichero se extenderá desde la
posición 100h hasta 2A17h (100h + 2917h).
A continuación, para buscar la cadena "Microsoft" en
el fichero, utilizamos cualquiera de los siguientes comandos:
– S 100 L 2917 "Microsoft"
– S 100 2a17 "Microsoft"
El primer comando señala el punto de inicio y el
tamaño de la zona a buscar; el segundo utiliza los
puntos inicial y final de la exploración. 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 ficheros (como es su imagen en el
disco), debe hacer una copia del fichero; renombrarlo con
cualquier otra terminación (o sin ella) y cargar esta
copia. En caso contrario, debug se preparará
para funcionar como un verdadero depurador de tiempo de
ejecución (run-time), para lo que cargará el
fichero 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 fichero .exe
cargándolo con debug de las dos formas (busque en
su sistema un .exe lo más pequeño posible).
§5.4 Además de la capacidad de leer
ficheros antes mencionada, quizás una de las opciones
más 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 [Dirección] [Unidad] [Primer_sector]
[Número]
W [Dirección] [Unidad] [Primer_sector]
[Número]
El significado de los parámetros es como sigue:
- Dirección: Posición de la memoria
de debug, a partir de la cual se instalarán los datos
leídos del disco, o se tomarán para el proceso de
escritura
(aquí se utiliza generalmente el valor 100h). - Unidad: Valor numérico que indica la
lógica 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. - Número: Número de sectores que se
desea cargar/escribir. Como debug no puede leer/escribir
más de 64 Kbytes (216 = 65536) y los
sectores de disco son de 512 bytes, el máximo
número de sectores es 128 (80h). Así pues,
el valor máximo 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 fichero (más adelante nos
servirá para otro propósito). Para ello
creamos un fichero script.txt con el siguiente contenido (dos
INTRO después de la "Q"):
L 100 0 0 1
D 100 L 200 Q
A continuación invocamos debug con el
comando
C:WINDOWS>debug < D:buzonscript.txt >
D:buzonresultad.txt
Autor:
José Luis Peñaloza Gallegos
México
11 de Septiembre de 2008
Página anterior | Volver al principio del trabajo | Página siguiente |