El Comando DEBUG

Colima El comando DEBUG By Benji 2007 V3.0 México Un Poco de Historia En 1980, Tim Paterson con 24 años de edad, basá

Views 120 Downloads 0 File size 452KB

Report DMCA / Copyright

DOWNLOAD FILE

Recommend stories

Citation preview

Colima

El comando DEBUG By Benji 2007 V3.0

México

Un Poco de Historia En 1980, Tim Paterson con 24 años de edad, basándose 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 rápido y sucio) para el microprocesador 8086 de 16-bit incorporado en una tarjeta tipo S-100 que había diseñado para SCP (Seattle Computer Products) un año anterior. Para ayudar a conseguir que QDOS (más tarde llamado 86-DOS Disk Operating System, sistema operativo de disco) funcionara correctamente, Tim creó un depurador en un chip ROM, la versión del código se publico como de dominio público. Más tarde, Tim adapto el código para que se ejecutara como un programa .COM en el QDOS y también le añadió la posibilidad de desensamblar código maquina del 8086. Mientras tanto, IBM había encargado un sistema operativo para su IBM-PC a Microsoft, al cual ya se le terminaba el plazo de entrega estipulado y no disponía aún del software, por lo cual Bill Gates y Paul Allen decidieron comprar los derechos por $50 000 dólares (primero una licencia parcial y más 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 más tarde comercializado como MS-DOS (Micro Soft Disk Operating System) a las computadoras clones que surgirían tras el éxito de IBM-PC. En la versión del DOS 1.00 de 1981, el programa DEBUG.COM se encuentra incluido como un componente más del DOS. Toda la funcionalidad que Tim pone en DEBUG está todavía allí y poco se ha añadido a ella [1] . Tim fue contratado por Microsoft en diversos periodos de su vida y trabajó en el desarrollo de Visual Basic. Algún tiempo después también recibió algunas acciones de la misma. Actualmente tiene una compañía de hardware Paterson Tech.

Introducción 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 ejecución. Una característica de DEBUG.EXE es que despliega todo el código del programa en formato hexadecimal. Otra utilidad es que se puede utilizar también para el desarrollo de pequeñas aplicaciones en ensamblador [2]. Usando DEBUG es posible observar el comportamiento de las instrucciones, la forma en cómo éstas afectan a las banderas, los contenidos de la memoria, el código de las instrucciones; además permite ensamblar código elemental usando los mnemotécnicos 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 extensión, todos los programas y utilidades que sirven para escudriñar los datos y el código a bajo nivel, se identifican genéricamente con esta denominación.

Se trata de una utilidad interactiva de exploración de bajo nivel, pero que también puede utilizarse para ciertas funciones. Por ejemplo, como un rudimentario traductor de sentencias ensamblador a lenguaje máquina. 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 erróneo). Para utilizarlo basta invocarlo desde MS-DOS o desde una ventana DOS de Windows. Aunque en este último caso algunas de sus funcionalidades más interesantes no se pueden ejecutar (limitadas por Windows). Como se dijo anteriormente, el DEBUG es un programa de utilería del Sistema Operativo DOS y Windows; Es útil para:     

Ensamblar pocas líneas de código ensamblador Des-ensamblar código 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 también 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 también 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 propósito 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 específicos:

AX BX CX DX DS ES SS CS BP SI DI SP IP F

Acumulador Registro base Registro contador Registro de datos Registro del segmento de datos Registro del segmento extra Registro del segmento de pila Registro del segmento de código Registro de apuntadores base Registro índice fuente Registro índice destino Registro del apuntador de la pila Registro de apuntador de siguiente instrucción Registro de banderas

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

Registro BX Recibe el nombre de registro base ya que es el único registro de propósito general que se usa como un índice en el direccionamiento indexado. Se suele utilizar para cálculos aritméticos. Registro CX Es conocido como registro contador ya que puede contener un valor para controlar el número de veces que se repite una cierta operación. Registro DX Se conoce como registro de datos. Algunas operaciones de E/S requieren su uso, y las operaciones de multiplicación y división con cifras grandes suponen que el DX y el AX trabajando juntos. Registro CS Registro Segmento de Código. Establece el área de memoria dónde está el programa durante su ejecución. 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 colocación 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 parámetros de las rutinas, los cuales son datos y direcciones transmitidos vía 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 también 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 dirección de la siguiente instrucción que se ejecutará. Está asociado con el registro CS en el sentido de que IP indica el desplazamiento de la siguiente instrucción a ejecutar dentro del segmento de código determinado por CS: Registro de banderas, FLAGS, o registro de estado (FL). Es un registro de 16 bits, pero sólo se utilizan nueve de ellos. Sirven para indicar el estado actual de la máquina y el resultado del procesamiento. La mayor parte de las instrucciones de

comparación y aritméticas modifican este registro. Algunas instrucciones pueden realizar pruebas sobre este registro para determinar la acción siguiente.

OF (O) Bit de Overflow o desbordamiento. Indica desbordamiento de un bit de orden alto (más a la izquierda), después de una operación aritmética. DF (D) Bit de Dirección. Designa la dirección, creciente (0) o decreciente (1), en operaciones con cadenas de caracteres. IF (I) Bit de Interrupción. Indica que una interrupción externa, como la entrada desde el teclado, sea procesada o ignorada. TF (T) Bit de Trap o Desvío. Procesa o ignora la interrupción interna de trace (procesamiento paso a paso). SF (S) Bit de Signo. Indica el valor del bit más significativo del registro después de una operación aritmética o de desplazamiento. ZF (Z) Bit Cero. Se pone a 1 si una operación produce 0 como resultado. AF (A) Bit de Carry Auxiliar. Se pone a 1 si una operación aritmética produce un acarreo del bit 3 al 4. Se usa para aritmética especializada (ajuste BCD). PF (P) Bit de Paridad. Se activa si el resultado de una operación tiene paridad par. CF (C) Bit de Acarreo. Contiene el acarreo de una operación aritmética 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 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 Registro R [registro] 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

En particular, obsérvese 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 dirección 0100h.

Comandos del DEBUG D: DUMP D Muestra el contenido de una zona de memoria en hexadecimal y en ASCII. Sin parámetros muestra los primeros 128 bytes a partir de la posición 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 dirección de inicio de despliegue; la 2da es la dirección de fin. Ejemplo:

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

E: EDIT E 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. Los cambios pueden ser especificados en la línea de comandos en cualquier combinación de números hexadecimales o caracteres ASCII; los caracteres ASCII deben estar entre comillas simples o dobles. Por ejemplo: E 100 'Benjamin Iglesias’ Establece el patrón "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 se entra en un modo especial en el que DEBUG despliega los valores de . 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 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. Ejemplo: R Donde 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 sinónimos.

A: ASSEMBLE A Sin parámetros ensambla las instrucciones que se introduzcan, guardándolas en la dirección siguiente a la que se llegó en el último "a". 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. La sintaxis es A Prácticamente cualquier mnemotécnico es soportado por DEBUG, incluyendo los especificadores de "override" de segmento (CS:, DS:, ES:, SS:). Una excepción 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 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 2048:0108 mov bx,cx 2048:010A -u 106 108 2048:0106 89D8 MOV AX,BX 2048:0108 89CB MOV BX,CX

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

F: FILL F Este comando llena un bloque de memoria con un valor específico o una serie de valores. La sintaxis es: F es la dirección de inicio y final o , si se preceden con "L", la dirección de inicio y la longitud del bloque; es(son) el(los) valor(es) con los que debe de llenarse el bloque. Si 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 líneas llena (con 0’s) 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 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 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, 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

T: TRACE T Ejecuta una instrucción del programa (a partir de CS:IP) mostrando a continuación el estado de los registros y la siguiente instrucción. Ejecutar T10 equivaldría a ejecutar 16 veces el comando T. Si la instrucción es CALL o INT, se ejecutará como tal introduciéndose 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 Se asigna un nombre al programa que está siendo creado o modificado. Se puede indicar la trayectoria de directorios.

L: LOAD L es la dirección en donde se carga la información; es el número (opcional) del disco de donde se leerá la información (0=A, 1=B, 2=C, etc.); es el sector de disco absoluto (en hexadecimal) a leer; es la cantidad de sectores a leer. No se pueden leer más de 80H (128) sectores. Si no se suministra la combinación DEBUG presume que se desea leer un archivo. En este caso es opcional. Debe usarse el comando N (ver más 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 dirección DS:100, como se puede observar, el disco contiene mucha información ( ESTO NO QUIERE DECIR QUE TENGA QUE SALIR LO MISMO EN SU VOLCADO )

l 100 0 0 1 -d 100 300

W: WRITE W Graba el contenido de una zona de memoria a disco. Si no se indica la dirección, se graba desde CS:100h hasta CS:100h+número_bytes; el número de bytes se indica en BX:CX (no es una dirección 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 extensión, aunque de esta manera no serán montados al cargarlos). La sintaxis es: W es la dirección de donde se carga la información; es el número (opcional) del disco en donde se escribirá la información (0=A, 1=B, 2=C, etc.); es el sector de disco absoluto (en hexadecimal) en donde empieza la escritura; es la cantidad de sectores a leer. No se pueden escribir más de 80H (128) sectores. Si no se suministra la combinación DEBUG presume que el inicio de archivo es CS:100. En este caso es opcional. Debe usarse el comando N (ver arriba) para especificar el archivo a escribir. Antes de escribir BX:CX debe ajustarse al número de bytes que desean grabarse. W no puede escribir a archivos con la extensión EXE o HEX. [5] Ejemplo:

N BX:CX