Universidad Nacional de Córdoba Facultad de Ciencias Exactas, Físicas y Naturales

SISTEMAS DE COMPUTACION
Trabajo Recuperatorio Instructivo y Uso de DEBUG

Alumno: Romero, Marco Antonio Profesora: Ing. Silvia Arias

I.E.

Año 2011

los contenidos de la memoria. el código de las instrucciones. Arrancando desde una ventana DOS. Debug nos presenta el contenido actual del registro y la posibilidad de ingresar un nuevo valor para sustituirlo. para editar el contenido de CX. y en el mismo orden tenemos: V=0. I=1. pero el hecho que desde el principio haya sido provisto con el sistema operativo. saltar sobre procedimientos. P=0 y C=0 Si ponemos después de la R el nombre de un registro. la forma cómo éstas afectan a las banderas. AC=0. Usando DEBUG es posible observar el comportamiento de las instrucciones. Z=0. es posible modificar su contenido. ejecutar paso a paso. Por ejemplo. y usando el comando R (mostrar registros) nos mostrará algo similar a esto: AX=0000 BX=0000 CX=0000 DX=0000 SP=0000 BP=0000 SI=0000 DI=0000 DS=1332 ES=1332 SS=1332 CS=1332 IP=0100 NV UP EI PL NZ NA PO NC 1332:0100 C3 RET . Se puede especificar la dirección a partir de la que se desea transferir datos o bien usar el vector por defecto DS:DX. Esto muestra el contenido de los registros del procesador incluyendo varias banderas: en el ejemplo. Incluso es posible correr programas cargados en memoria utilizando breakpoints elementales. hay que poner el comando RCX. La cantidad de bytes transferida en cada operación es el contenido de BX:CX. Muchas tareas elementales pueden realizarse sin otra ayuda que el Debug y por eso vamos a ver algunos comandos básicos. . S=0. Recuérdese que los registros de esta arquitectura son un subconjunto elemental de aquellos presentes en modelos más modernos de la familia '86.USO DE DEBUG Posiblemente sea el debug el depurador más rudimentario que existe. D=0. nos permite encontrarlo hoy en cualquier máquina DOS o Windows. además permite ensamblar código elemental usando los mnemotécnicos del 8086. editar programas en hexa y muchas más cosas. Previamente es necesario darle un nombre al archivo con el comando N. Los comandos L y W se utilizan para leer y escribir en archivos de disco. Con el sistema operativo DOS (MS-DOS = Microsoft Disk Operating System) se incluye un programa para observar el comportamiento de los registros del CPU 80386.

obsérvese lo siguiente: a) DEBUG opera bajo DOS. En las siguientes secciones de hace un breve resumen de los comandos de DEBUG. b) Cuando se invoca (como en el ejemplo) sin argumentos.Todos los comandos de DEBUG se invocan usando una sola letra y son los siguientes: 01) A (assemble) 02) C (compare) 03) D (dump) 04) E (enter) 05) F (fill) 06) G (go) 07) H (aritmética hexadecimal) 08) I (input) 09) L (load) 10) M (move) 11) N (name) 12) O (output) 13) Q (quit) 14) R (register) 15) S (search) 16) T (trace) 17) U (unassemble) 18) W (write) En particular. El lector . el contenido de la memoria es arbitrario.

ES:.1. 1. asume que RET es "near" y RETF es "far". Wyatt.4. 1987. la dirección de inicio y la longitud del bloque. 1. DS:. si se preceden con "L".2. Una excepción es que DEBUG no puede diferenciar entre NEAR y FAR returns. La sintaxis es: .Interesado en detalles puede consultar. <dirección> es el inicio de otro bloque. incluyendo los especificadores de "override" de segmento (CS:. por ejemplo. SS:).3. la 2a es la dirección de fin. Se presupone que la longitud de ambos bloques es la misma. ASSEMBLE (A) El comando A se usa para introducir mnemotécnicos de ensamblador y que éstos se traduzcan directamente a lenguaje de máquina en memoria. "USING ASSEMBLY LANGUAGE" de Allen L. QUE Corporation. 1. La 1a es la dirección de inicio de despliegue. ENTER (E) Este comando permite cambiar los contenidos de localidades específicas de memoria. DUMP (D) Este comando despliega el contenido de una serie de localidades de memoriaLa sintaxis es: D <dirección1> <dirección2> Ambas direcciones son opcionales. 1. COMPARE (C) Este comando compara y reporta diferencias entre los contenidos de dos bloques de memoria. La sintaxis es: C <bloque> <dirección> <bloque> es la dirección de inicio y fin de un bloque o. La sintaxis es: A <dirección> Prácticamente cualquier mnemotécnico es soportado por DEBUG.

Si <valor de relleno> representa menor bytes que los que se necesitan para llenar el bloque. la dirección de inicio y la longitud del bloque. los caracteres ASCII deben estar entre comillas simples o dobles. Cuando no se especifica <cambios> se entra en un modo especial en el que DEBUG despliega los valores de <dirección>. si se preceden con "L". la serie se repite hasta llenar el bloque. Si se está depurando un programa.E <dirección> <cambios> <dirección> es el inicio de los cambios y <cambios> es una lista opcional de los cambios deseados.6. cualquiera de las siguientes dos líneas llena (con 0s) el bloque DS:00FF: F DS:0000 DS:00FF 0 F DS:0000 LFF 0 1. Los cambios pueden ser especificados en la línea de comandos en cualquier combinación de números hexadecimales o caracteres ASCII. <valor de relleno> es(son) el(los) valor(es) con los que debe de llenarse el bloque. La sintaxis es: . Entonces es posible teclear nuevos valores que reemplacen a los que se muestran. También permite establecer puntos de quiebre (breakpoints) que son direcciones en las que se detiene la ejecución del programa. Si se activa la barra espaciadora DEBUG pasa a la siguiente localidad. permite ejecutar el código cargado en memoria. Por ejemplo: E 100 'Buenas Tardes' Establece el patrón "42 75 65 6E 61 73 20 54 61 72 64 65 73" en memoria a partir de la localidad 100H. La sintaxis es: F <bloque> <valor de relleno> <bloque> es la dirección de inicio y final o . 1. Si se teclea "-" DEBUG regresa a la localidad anterior. Por ejemplo. FILL (F) Este comando llena un bloque de memoria con un valor específico o una serie de valores. GO (G) Este comando ejecuta el código en memoria.5.

No se pueden leer más de 80H (128) sectores. <sectorini> es el sector de disco absoluto (en hexadecimal) a leer. Si no se especifica <inicio>. LOAD (L) Este comando se usa para cargar un archivo o sectores de disco a memoria. <quiebre10> <inicio> es la dirección de inicio de ejecución. . <numsector> es la cantidad de sectores a leer. En este caso <buffer> es opcional. Go inicia con la dirección contenida en CS:IP.7. Éste se carga en CS:0100. Si no se suministra la combinación <numdisco> <sectorini> <numsector> DEBUG presume que se desea leer un archivo.. <quiebre1> hasta <quiebre10> son direcciones opcionales de paro del programa. que es el código de interrupción.9.8. <numdisco> es el número (opcional) del disco de donde se leerá la información (0=A. La sintaxis es: L <buffer> <numdisco> <sectorini> <numsector> <buffer> es la dirección en donde se carga la información. 1. 1. La sintaxis es: I <puerto> <puerto> es la dirección del puerto a leer. Si DEBUG llega a CC todos los puntos de quiebre son restituidos. La sintaxis es: H <valor1> <valor2> Como resultado de lo anterior. 2=C. Para lograr los quiebres.G =<inicio> <quiebre1> <quiebre2> . Se lee el dato y se despliega en pantalla. los registros se despliegan (como con el comando R [véase adelante]) y se usan para la ejecución. Aritmética Hexadecimal (H) Este comando ejecuta restas y suma hexadecimales. 1. Debe usarse el comando N (ver más adelante) para especificar el archivo a leer. etc.).. INPUT (I) Este comando "jala" un byte de un puerto. DEBUG reemplaza el código en las direcciones de quiebre por el valor hexadecimal CC. DEBUG regresa dos valores: la suma y la resta de los argumentos en hexa. 1=B.

REGISTER (R) Este comando despliega los registros del CPU y los valores de las banderas. <nomarch2> es la especificación de archivo que será colocada en CS:006C. OUTPUT (O) Este comando pone un byte en el puerto especificado. La sintaxis es: R <registro> <registro> es el nombre opcional y puede ser alguno de los siguientes: AX. 1. PC o F. CX.1. IP y PC son sinónimos. 1. DX.1.13. CS.11. La sintaxis es: O <puerto< <valor> <valor> es el byte hexadecimal a escribir en <puerto>. BX. MOVE (M) Este comando mueve un bloque de memoria de una localidad a otra. IP. <dirección> es la dirección destino. DI. El bloque de origen y la dirección destino pueden traslaparse. SI. QUIT (Q) Este comando se usa para salir de DEBUG. ES.). SP. precedida por el número de bytes tecleados.10. 1. NAME (N) Este comando se usa para especificar el nombre del archivo usado por los comandos LOAD y WRITE. La sintaxis es: N <nomarch1< <nomarch2> <nomarch1> es la especificación de archivo completa que será "parseada" y colocada en el bloque de control en CS:005C. La sintaxis es: M <bloque> <dirección> <bloque> es como arriba (ver 2.14. BP. . La expresión tal cual se tecleó se almacena en CS:0081. 1. SS.5. DS.12.

WRITE (W) Este comando se usa para escribir un archivo a sectores individuales de disco a disco.). <numsector> es la cantidad de sectores a leer. <sectorini> es el sector de disco absoluto (en hexadecimal) en donde empieza la escritura. La sintaxis es: T =<inicio> <cuenta> <inicio> es la dirección de inicio de la traza <cuenta> es el número de instrucciones a trazar 1.15. <numdisco> es el número (opcional) del disco en donde se escribirá la información (0=A. que es opcional. <valor_a_buscar> es(son) el(los) valor(es) que deseamos buscar en el bloque. 1=B. UNASSEMBLE (U) Este comando decodifica los valores de un grupo de localidades de memoria a mnemotécnicos de 8086.18. si se precede con "L". No se pueden escribir más de 80H (128) sectores. etc. La sintaxis es la siguiente: U <alcance> <alcance>.16.17. Si no se suministra la combinación <numdisco> <sectorini> <numsector> DEBUG presume que el inicio . 2=C. 1. 1. La sintaxis es: S <bloque> <valor_a_buscar> <bloque> se define como antes (ver la sección 1_1). La sintaxis es: W <buffer> <numdisco> <sectorini> <numsector> <buffer> es la dirección de donde se carga la información. Después de cada instrucción se muestra el estado de los registros. la dirección de inicio y la longitud del área a desensamblar.1. TRACE (T) Este comando permite ejecución paso-a-paso de las instrucciones de máquina. es ya sea un par de direcciones de inicio y fin o. SEARCH (S) Este comando permite buscar en un bloque de memoria una secuencia específica de valores.

Para sacar algo a pantalla. Debe usarse el comando N (ver arriba) para especificar el archivo a escribir.2000 <cr> W <cr> PROGRAMA A MODO DE EJEMPLO: Usaremos el Debug para ensamblar un programa que realice algo tan útil como dejar en alguna parte de la memoria el nombre de nuestra escuela ECCE.cargamos BX con "CE" en ASCII . sean direcciones o datos. de manera que nuestro programa puede lucir así: a 100 1322:0100 1322:0103 1322:0106 1322:0109 1322:010D 1322:010F Al apretar "enter" una vez más. Nos proponemos hacer que ECCE sea escrito en memoria.de archivo es CS:100. Podemos ver algunas curiosidades del listado anterior: 1) Debug asume que los números que le damos. W no puede escribir a archivos con la extensión EXE o HEX. 4) Aunque nada se ha hablado de la INT 20.4543 mov bx. pero en la 202 (AX ocupó la 200 y 201) . 3) Las tres primeras instrucciones MOV ocuparon de memoria de programa 3 bytes cada una.cargamos el registro AX con el dato 4543 (EC en ASCII) .4345 mov [200]. nos va devolviendo la dirección de almacenamiento de la próxima instrucción que escribiremos. En este caso <buffer> es opcional. 5) Cuando hacemos mov ax. Ejemplo: N <nomarchivo> <cr> BX:CX <--. pero la cuarta ocupó 4 bytes y la INT 20 sólo ocupó 2 bytes.idem para BX.finalizar y salir a Debug . Debug nos devuelve su prompt "-" y ya estamos listos para nuestro próximo comando. Sabemos que los códigos ASCII son E=45h y C=43h. 2) A medida que vamos ingresando el programa. Antes de escribir BX:CX debe ajustarse al número de bytes que desean grabarse. que será nuestro paso siguiente. en el offset 200h de nuestro segmento de datos DS.ponemos AX en la dirección de memoria 200 .ax mov [202]. Por ahora sólo queremos practicar de manera que abramos una ventana DOS y escribamos DEBUG (enter). es lo que por el momento usaremos para terminar el programa. son hexadecimales.bx int 20 . debemos leer el tutorial de +gthorne (Greythorne the Technomancer).

Luego cargamos "CE" en BX y lo dejamos en la 202. sin importar cómo escribimos nuestro código) 1322:0100 1322:0103 1322:0106 1322:0109 1322:010D B84345 BB4543 A30002 891E0202 CD20 MOV AX. salvo que las instalaciones de software sean idénticas y en ambas estén corriendo previamente al DEBUG los mismos programas.AX MOV [202]. en una columna entre la dirección y el listado en lenguaje assembly puso unos números hexadecimales. Es muy importante saber distinguir entre la dirección y el valor almacenado en esa dirección de memoria.referencia al contenido de una posición de memoria. El prefijo "word ptr" es para que el procesador sepa que lo que moveremos a 200 es una word y no un byte o double-word. El listado es más largo. encerramos la dirección entre corchetes []. Veamos cómo se ve nuestro programa usando el comando desensamblar: -u 100 (desensamble a partir de la CS:100) (Nótese que Debug listará usando sólo mayúsculas. Debug compiló nuestro programa ingresado en assembly y produjo ese código binario con representación hexadecimal para que el Pentium lo interprete.4543 . cargar la word de memoria 200 directamente con el dato 4543 Esta instrucción ocupa 6 bytes. . ya que Debug desensambla por defecto los 20h primeros bytes desde la dirección indicada (o desde la que esté apuntando).BX INT 20 NOTA: el valor de 1322 (el contenido del registro CS) es válido para la PC donde se escribió este ensayo.4345 MOV [200]. Por lo general los valores no coinciden de una a otra PC.4543 MOV BX. Observemos: Debug no deja de sorprendernos. Nuestra lógica es muy simple: cargamos el ASCII "EC" en AX y lo dejamos en la dirección 200. pero las líneas que siguen hacia abajo son alguna cosa que estaba en memoria. de modo que no ganamos espacio poniéndola en lugar del más elíptico procedimiento de cargar AX y con éste escribir en 200. Son los códigos de operación (opcodes) que es lo que en definitiva se almacena en memoria y lo que nuestro Pentium debe interpretar y ejecutar. Tanto AX como BX han sido meros vehículos para cargar la memoria con datos y sólo a los efectos didácticos porque también está permitido : MOV word ptr [200]. y en nuestro programa sólo hemos usado 0Fh bytes (15 en decimal).

BX es la próxima instrucción. Hemos guardado AX en la dirección 200 y por lo tanto debería haber un 4543 ("EC" en ASCII) en las direcciones 200 y 201. escribamos nuevamente el comando D 200. Debemos ver las cuatro primeras filas del listado con los datos en 00. Nos debe decir que IP apunta a 0100: 1322:0100 B84345 MOV AX. Con el comando R nos aseguramos que CS:IP esté apuntando al inicio de nuestro programa (o sea a CS:0100). Como deseamos leer claramente nuestro nombre ECCE. Para estar seguros. porque hasta aquí sólo hemos cargado los registros AX y BX. tenemos que ver qué hay en la posición de memoria 200. en donde claramente nos dice CEEC) y están al revés.4345 es la próxima instrucción. Primero el comando R. Usemos al Debug para depurar.AX Ejecutemos el comando D 200 para ver qué hay en la memoria: hasta ahora 00 de la dirección 200 a la 203. Repitamos el comando F 200 23F 00 para dejar nuevamente en cero la memoria y ejecutemos nuestro programa paso a paso.Antes de correr el fabuloso programa que hemos escrito. Verifiquemos con el comando D 200: .F 200 23F 00 con lo que le indicamos a Debug que debe llenar el bloque de memoria que comienza en 200 y termina en 23F con "00". Qué habrá pasado? Será que hemos escrito BX en 200 y AX en 202?. Lo relevante es: AX=4543 e IP=0103 1322:0103 BB4543 MOV BX. Debug nos debe informar: El programa ha finalizado con normalidad. Para nuestro caso CS vale 1322.43. Todo ok. vamos a llenar este espacio con ceros usando el comando . Veamos si nuestras siglas brillan en las posiciones 200 a 203 con el comando D 200. Para ello usamos el comando D 200. Corramos el programa con el comando G. Hagamos otro T. Ejecutemos con T: 1322:0106 A30002 MOV [200]. pero como ya se ha dicho. Esperábamos los hexa 45.45 a partir de la 200 (miremos además en la columna ASCII del Debug.43. Bien! todo resulto correcto. que nos muestra la basura que hay en nuestra RAM desde DS:0200 hasta DS:027F. Estamos listos para correr nuestro programita. 1322:0109 891E0202 MOV [0202].4543 -T (comando para ejecutar una sola instrucción). puede que en otra PC tenga otro valor.

. y lo mismo para BX: a 100 1322:0100 MOV AX.. debemos rescribir nuestro programa para que en AL se almacene la primera letra ("E") y en AH la segunda ("C").....4345 1322:0103 MOV BX. que nos quedó apuntando a la mitad del programa: RIP (enter) nuestro comando IP 0109 respuesta de Debug :100 (enter) este valor lo ingresamos nosotros para decirle que queremos a IP=0100 Ejecutamos el programa nuevamente con G y examinamos la memoria con D 200 para ver nuestro sigla ECCE ya en su lugar y en el orden debido. Ahora debemos modificar el registro IP.1322:0200 43 45 00 00 ... a la porción más baja del registro (AL) la almacena en la dirección de memoria más baja (200) y a la porción más alta del registro (AH) la almacena en la dirección de memoria más alta (201). Y el procesador hace algo sumamente lógico. Por lo tanto...... ahí fue donde nos equivocamos!) desde la porción más baja hacia la más alta.... debemos acostumbrarnos a leer los registro (y a cargarlos. Si leemos la memoria en sentido de direcciones ascendentes.. CE.4543 (enter) nuevamente para salir del comando A.. Todo parece bien pero no funciona? Pero está bien tal como lo hizo Intel. Tengo "CE" en lugar de "EC". en la realidad lo debemos asumir como: En AL tengo un 43 ("C") y en AH un 45 ("E"). Resulta que lo que leemos en AX como "EC". QUE PASO???? Está al revés. .....

Sign up to vote on this title
UsefulNot useful