El Comando DEBUG

30
El comando DEBUG By Benji Colima 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

Transcript of El Comando DEBUG

Page 1: El Comando DEBUG

El comando DEBUG By Benji

Colima 2007 V30 Meacutexico

Un Poco de Historia En 1980 Tim Paterson con 24 antildeos de edad basaacutendose en el CPM (Control Program for Microcomputers escrito por Gary Kildall) comenzoacute a trabajar en un Sistema Operativo llamado QDOS (Quick and Dirty Operating System sistema operativo raacutepido y sucio) para el microprocesador 8086 de 16-bit incorporado en una tarjeta tipo S-100 que habiacutea disentildeado para SCP (Seattle Computer Products) un antildeo anterior Para ayudar a conseguir que QDOS (maacutes tarde llamado 86-DOS Disk Operating System sistema operativo de disco) funcionara correctamente Tim creoacute un depurador en un chip ROM la versioacuten del coacutedigo se publico como de dominio puacuteblico Maacutes tarde Tim adapto el coacutedigo para que se ejecutara como un programa COM en el QDOS y tambieacuten le antildeadioacute la posibilidad de desensamblar coacutedigo maquina del 8086 Mientras tanto IBM habiacutea encargado un sistema operativo para su IBM-PC a Microsoft al cual ya se le terminaba el plazo de entrega estipulado y no disponiacutea auacuten del software por lo cual Bill Gates y Paul Allen decidieron comprar los derechos por $50 000 doacutelares (primero una licencia parcial y maacutes tarde una licencia completa) del sistema creado por Tim Paterson y contrataron a eacuteste (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 maacutes tarde comercializado como MS-DOS (Micro Soft Disk Operating System) a las computadoras clones que surgiriacutean tras el eacutexito de IBM-PC En la versioacuten del DOS 100 de 1981 el programa DEBUGCOM se encuentra incluido como un componente maacutes del DOS Toda la funcionalidad que Tim pone en DEBUG estaacute todaviacutea alliacute y poco se ha antildeadido a ella [1] Tim fue contratado por Microsoft en diversos periodos de su vida y trabajoacute en el desarrollo de Visual Basic Alguacuten tiempo despueacutes tambieacuten recibioacute algunas acciones de la misma Actualmente tiene una compantildeiacutea de hardware Paterson Tech Introduccioacuten El DEBUGEXE 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 ejecucioacuten Una caracteriacutestica de DEBUGEXE es que despliega todo el coacutedigo del programa en formato hexadecimal Otra utilidad es que se puede utilizar tambieacuten para el desarrollo de pequentildeas aplicaciones en ensamblador [2] Usando DEBUG es posible observar el comportamiento de las instrucciones la forma en coacutemo eacutestas afectan a las banderas los contenidos de la memoria el coacutedigo de las instrucciones ademaacutes permite ensamblar coacutedigo elemental usando los mnemoteacutecnicos 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 extensioacuten todos los programas y utilidades que sirven para escudrintildear los datos y el coacutedigo a bajo nivel se identifican geneacutericamente con esta denominacioacuten

Se trata de una utilidad interactiva de exploracioacuten de bajo nivel pero que tambieacuten puede utilizarse para ciertas funciones Por ejemplo como un rudimentario traductor de sentencias ensamblador a lenguaje maacutequina 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 erroacuteneo) Para utilizarlo basta invocarlo desde MS-DOS o desde una ventana DOS de Windows Aunque en este uacuteltimo caso algunas de sus funcionalidades maacutes interesantes no se pueden ejecutar (limitadas por Windows) Como se dijo anteriormente el DEBUG es un programa de utileriacutea del Sistema Operativo DOS y Windows Es uacutetil para

Ensamblar pocas liacuteneas de coacutedigo ensamblador

Des-ensamblar coacutedigo 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 eacutestos 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 tambieacuten 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 tambieacuten 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 propoacutesito 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 ldquoLOWrdquo o ldquoBajardquo del registro AX mientras que AH es la parte ldquoHIGHrdquo o parte ldquoAltardquo 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 especiacuteficos

AX Acumulador BX Registro base CX Registro contador DX Registro de datos DS Registro del segmento de datos ES Registro del segmento extra SS Registro del segmento de pila CS Registro del segmento de coacutedigo BP Registro de apuntadores base SI Registro iacutendice fuente DI Registro iacutendice destino SP Registro del apuntador de la pila IP Registro de apuntador de siguiente instruccioacuten F Registro de banderas

Registro AX Este registro es el acumulador principal implicado en gran parte de las operaciones de aritmeacuteticas y de ES Registro BX Recibe el nombre de registro base ya que es el uacutenico registro de propoacutesito general que se usa como un iacutendice en el direccionamiento indexado Se suele utilizar para caacutelculos aritmeacuteticos Registro CX Es conocido como registro contador ya que puede contener un valor para controlar el nuacutemero de veces que se repite una cierta operacioacuten Registro DX Se conoce como registro de datos Algunas operaciones de ES requieren su uso y las operaciones de multiplicacioacuten y divisioacuten con cifras grandes suponen que el DX y el AX trabajando juntos Registro CS Registro Segmento de Coacutedigo Establece el aacuterea de memoria doacutende estaacute el programa durante su ejecucioacuten 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 colocacioacuten 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 estaacute siendo procesada en la pila Registro BP Facilita la referencia a los paraacutemetros de las rutinas los cuales son datos y direcciones transmitidos viacutea la pila Registro SI Registro iacutendice fuente requerido en algunas operaciones con cadenas de caracteres Este registro estaacute asociado con el registro DS Registro DI Registro iacutendice destino requerido tambieacuten en determinadas operaciones con cadenas de caracteres Estaacute 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 direccioacuten de la siguiente instruccioacuten que se ejecutaraacute Estaacute asociado con el registro CS en el sentido de que IP indica el desplazamiento de la siguiente instruccioacuten a ejecutar dentro del segmento de coacutedigo determinado por CS Registro de banderas FLAGS o registro de estado (FL) Es un registro de 16 bits pero soacutelo se utilizan nueve de ellos Sirven para indicar el estado actual de la maacutequina y el resultado del procesamiento La mayor parte de las instrucciones de

comparacioacuten y aritmeacuteticas modifican este registro Algunas instrucciones pueden realizar pruebas sobre este registro para determinar la accioacuten siguiente

OF (O) Bit de Overflow o desbordamiento Indica desbordamiento de un bit de orden alto (maacutes a la izquierda) despueacutes de una operacioacuten aritmeacutetica DF (D) Bit de Direccioacuten Designa la direccioacuten creciente (0) o decreciente (1) en operaciones con cadenas de caracteres IF (I) Bit de Interrupcioacuten Indica que una interrupcioacuten externa como la entrada desde el teclado sea procesada o ignorada TF (T) Bit de Trap o Desviacuteo Procesa o ignora la interrupcioacuten interna de trace (procesamiento paso a paso) SF (S) Bit de Signo Indica el valor del bit maacutes significativo del registro despueacutes de una operacioacuten aritmeacutetica o de desplazamiento ZF (Z) Bit Cero Se pone a 1 si una operacioacuten produce 0 como resultado AF (A) Bit de Carry Auxiliar Se pone a 1 si una operacioacuten aritmeacutetica produce un acarreo del bit 3 al 4 Se usa para aritmeacutetica especializada (ajuste BCD) PF (P) Bit de Paridad Se activa si el resultado de una operacioacuten tiene paridad par CF (C) Bit de Acarreo Contiene el acarreo de una operacioacuten aritmeacutetica 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 Cgt DEBUG [Enter] Una vez que el programa estaacute en ejecucioacuten el indicador (prompt) es un guioacuten - indicando que el Shell espera recibir oacuterdenes Para salir basta pulsar una Q Como muchos programas de su geacutenero sus comandos empiezan por una letra o combinacioacuten de ellas (pueden usarse indistintamente mayuacutesculas o minuacutesculas) y ciertos paraacutemetros opcionales (no es imprescindible separar la letra de opcioacuten de los paraacutemetros opcionales que siguen) La opcioacuten maacutes sencilla es la interrogacioacuten () cuyo resultado es una lista resumida de las opciones disponibles

Ensamblar A [direccioacuten] Comparar C direccioacuten de intervalo Volcar D [intervalo] Escribir E direccioacuten [lista de valores] Llenar F lista de intervalos Ir G [=direccioacuten] [direcciones] Hex H valor1 valor2 Entrada I puerto Cargar L [direccioacuten] [unidad] [primer_sector] [nuacutemero] Mover M direccioacuten de intervalo Nombre N [nombre_ruta] [lista_argumentos] Salida O byte de puerto Proceder P [=direccioacuten] [nuacutemero] Salir Q Registro R [registro] Buscar S lista de intervalos Seguimiento T [=direccioacuten] [valor] Desensamblar U [intervalo] Escribir W [direccioacuten] [unidad] [primer_sector] [nuacutemero] Asignar memoria expandida XA [paacuteginas] Desasignar memoria expandida XD [identificador] Asignar paacuteginas de memoria expandida XM [Lpaacutegina] [Ppaacutegina] [identificador] Mostrar estado de la memoria expandida XS

En particular obseacutervese 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 EJEMPLOCOM entonces carga a EJEMPLOCOM en memoria a partir de la direccioacuten 0100h

Comandos del DEBUG D DUMP D ltdireccioacuten1gt ltdireccioacuten2gt Muestra el contenido de una zona de memoria en hexadecimal y en ASCII Sin paraacutemetros muestra los primeros 128 bytes a partir de la posicioacuten a la que se llegoacute en el uacuteltimo d Si se le da un rango mostraraacute ese rango Ambas direcciones son opcionales La 1ra es la direccioacuten de inicio de despliegue la 2da es la direccioacuten de fin Ejemplo

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

E EDIT E ltdireccioacutengtltlistagt Permite editar byte por byte una zona de memoria Muestra -en hexadecimal- el byte de esa posicioacuten 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 siacute se ha hecho Para terminar la edicioacuten se pulsa INTRO Los cambios pueden ser especificados en la liacutenea de comandos en cualquier combinacioacuten de nuacutemeros hexadecimales o caracteres ASCII los caracteres ASCII deben estar entre comillas simples o dobles Por ejemplo E 100 Benjamin Iglesiasrsquo Establece el patroacuten 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 ltlistagt se entra en un modo especial en el que DEBUG despliega los valores de ltdireccioacutengt 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 ltregistrogt Sin paraacutemetros muestra el contenido de los registros de la CPU asiacute como la proacutexima instruccioacuten a ejecutarR [REGISTRO] muestra el contenido del registro especificado y cambia

el prompt de - a invitando a que se cambie su valor Pulsando Enter sin maacutes lo deja como estaba Ejemplo R ltregistrogt Donde ltregistrogt 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 sinoacutenimos A ASSEMBLE A ltdireccioacutengt Sin paraacutemetros ensambla las instrucciones que se introduzcan guardaacutendolas en la direccioacuten siguiente a la que se llegoacute en el uacuteltimo a Cuando se utiliza este comando se le puede dar como paraacutemetro la direccioacuten donde se desea que se inicie el ensamblado si se omite el paraacutemetro el ensamblado se iniciaraacute en la localizacioacuten especificada por CSIP usualmente 0100H que es la localizacioacuten donde deben iniciar los programas con extensioacuten COM y seraacute la localizacioacuten que utilizaremos debido a que DEBUG solo puede crear este tipo especiacutefico de programas La sintaxis es A ltdireccioacutengt Praacutecticamente cualquier mnemoteacutecnico es soportado por DEBUG incluyendo los especificadores de override de segmento (CS DS ES SS) Una excepcioacuten 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 instruccioacuten MOV que como veremos maacutes adelante sirve para copiar datos de la memoria a los registros y viceversa ademaacutes de copiar datos entre registros que es justo lo que vamos a usar en el ejemplo -a 20480106 mov axbx 20480108 mov bxcx 2048010A ltRETgt -u 106 108 20480106 89D8 MOV AXBX 20480108 89CB MOV BXCX Como veremos maacutes adelante la instruccioacuten U sirve para hacer volcados de memoria pero no viendo el contenido de la misma sino interpretaacutendola como instrucciones en lenguaje ensamblador Ejemplo 2 -r cs CS 2048 2050 -a 200 20500200 mov axbx 20500202 ltRETgt -u 200 200 20500200 89D8 MOV AXBX

F FILL F ltbloquegt ltvalor de rellenogt Este comando llena un bloque de memoria con un valor especiacutefico o una serie de valores La sintaxis es F ltbloquegt ltvalor de rellenogt ltbloquegt es la direccioacuten de inicio y final o si se preceden con L la direccioacuten de inicio y la longitud del bloque ltvalor de rellenogt es(son) el(los) valor(es) con los que debe de llenarse el bloque Si ltvalor de rellenogt 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 liacuteneas llena (con 0rsquos) el bloque DS00FF F DS0000 DS00FF 0 DS0000 LFF 0 Ejemplo -f 100 105 66 -d 100 105 20480100 66 66 66 66 66 66 ffffff Q QUIT Q Salir de DEBUG y volver al DOS P PROCEED P lt=direccioacutengtltnuacutemerogt Similar al comando T pero al encontrarse un CALL o INT lo ejecuta de golpe sin entrar en su interior (ojo iexclesto uacuteltimo falla al tracear sobre memoria ROM) Trace puede ser incoacutemodo si no se quiere depurar el coacutedigo de las rutinas de interrupcioacuten o si ya se sabe el coacutedigo que hay en las subrutinas y tan soacutelo interesa seguir avanzando sin entrar en ellas En estos casos se usa p por lo que si ejecutamos una interrupcioacuten de MS-DOS no sabriacuteamos 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 20480107 3D5000 CMP AX0050 -a 100 20480100 mov ax0200 20480103 mov dl61 20480105 int 21 20480107 -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 20480103 B261 MOV DL61 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 20480105 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 20480107 3D5000 CMP AX0050 T TRACE T lt=direccioacutengt ltvalorgt Ejecuta una instruccioacuten del programa (a partir de CSIP) mostrando a continuacioacuten el estado de los registros y la siguiente instruccioacuten Ejecutar T10 equivaldriacutea a ejecutar 16 veces el comando T Si la instruccioacuten es CALL o INT se ejecutaraacute como tal introducieacutendose 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 20480100 3D0000 CMP AX0000 -r bx BX 0000 2 -a 100 20480100 mov axbx 20480102 -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 20480102 00AC01D8 ADD [SI+D801]CH DSD801=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 20480100 3D0000 CMP AX0000 -a 100 20480100 mov axbx 20480102 mov cxbx 20480104 -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 20480102 89D9 MOV CXBX 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 20480104 01D8 ADD AXBX

N NAME N ltnombre_archivogt Se asigna un nombre al programa que estaacute siendo creado o modificado Se puede indicar la trayectoria de directorios L LOAD L ltbuffergt ltnumdiscogt ltsectorinigt ltnumsectorgt ltbuffergt es la direccioacuten en donde se carga la informacioacuten ltnumdiscogt es el nuacutemero (opcional) del disco de donde se leeraacute la informacioacuten (0=A 1=B 2=C etc) ltsectorinigt es el sector de disco absoluto (en hexadecimal) a leer ltnumsectorgt es la cantidad de sectores a leer No se pueden leer maacutes de 80H (128) sectores Si no se suministra la combinacioacuten ltnumdiscogt ltsectorinigt ltnumsectorgt DEBUG presume que se desea leer un archivo En este caso ltbuffergt es opcional Debe usarse el comando N (ver maacutes adelante) para especificar el archivo a leer Eacuteste se carga en CS0100 Ejemplo Se va a leer el sector 0 del disco A y se vuelca a partir de la direccioacuten DS100 como se puede observar el disco contiene mucha informacioacuten ( ESTO NO QUIERE DECIR QUE TENGA QUE SALIR LO MISMO EN SU VOLCADO )

l 100 0 0 1 -d 100 300

W WRITE W ltdireccioacutengt Graba el contenido de una zona de memoria a disco Si no se indica la direccioacuten se graba desde CS100h hasta CS100h+nuacutemero_bytes el nuacutemero de bytes se indica en BXCX (no es una direccioacuten segmentada sino un valor de 32 bits) Si se trata de un EXE no se permitiraacute grabarlo (para modificarlos hay que renombrarles para cambiarles la extensioacuten aunque de esta manera no seraacuten montados al cargarlos) La sintaxis es W ltbuffergt ltnumdiscogt ltsectorinigt ltnumsectorgt ltbuffergt es la direccioacuten de donde se carga la informacioacuten ltnumdiscogt es el nuacutemero (opcional) del disco en donde se escribiraacute la informacioacuten (0=A 1=B 2=C etc) ltsectorinigt es el sector de disco absoluto (en hexadecimal) en donde empieza la escritura ltnumsectorgt es la cantidad de sectores a leer No se pueden escribir maacutes de 80H (128) sectores Si no se suministra la combinacioacuten ltnumdiscogt ltsectorinigt ltnumsectorgt DEBUG presume que el inicio de archivo es CS100 En este caso ltbuffergt es opcional Debe usarse el comando N (ver arriba) para especificar el archivo a escribir Antes de escribir BXCX debe ajustarse al nuacutemero de bytes que desean grabarse W no puede escribir a archivos con la extensioacuten EXE o HEX [5] Ejemplo

N ltnomarchivogt BXCX lt--- 2000 W

S SEARCH S ltrangogt ltlistagt Busca una cadena de bytes por la memoria Para buscar la cadena PEPE terminada por cero en un aacuterea de 512 bytes desde DS100 se hariacutea S 100 L 200 PEPE0 (por defecto se busca en DS) No se encontrariacutea sin embargo pepe (en minuacutesculas) C COMPARE C ltrangogt ltdireccioacutengt Compara dos zonas de memoria mostrando las diferencias Por ejemplo para comparar 5 bytes de DS100 y DS200 se hace C 100 L 5 200 M MOVE M ltrangogt ltdireccioacutengt Maacutes que mover copia una zona de memoria en otra de manera inteligente (controlando los posibles solapamientos de los bloques) I INPUT I ltpuertogt Visualiza la lectura del puerto de ES indicado

O OUTPUT O ltpuertogt ltvalorgt Enviacutea un valor a un puerto de ES H HEX H ltvalor1gt ltvalor2gt Muestra la suma y resta de valor1 y valor2 ambos operandos de un maacuteximo de 16 bits (si hay desbordamiento se trunca el resultado que tampoco excede los 16 bits) Resultado ltresultado_1gt Es la suma ( ltvalor1gt + ltvalor2gt) ltresultado_2gt es la resta (ltvalor1gt - ltvalor2gt ) Ejemplo -h 0003 0002 0005 0001 -h 0000 0001 0001 FFFF como se observa el resultado de la segunda operacioacuten es FFFF que es el equivalente en complemento a 2 de -1 G GO G =ltiniciogt ltquiebre1gt ltquiebre2gt ltquiebre10gt Este comando ejecuta el coacutedigo en memoria Si se estaacute depurando un programa permite ejecutar el coacutedigo cargado en memoria Tambieacuten permite establecer puntos de quiebre (breakpoints) que son direcciones en las que se detiene la ejecucioacuten del programa La sintaxis es G =ltiniciogt ltquiebre1gt ltquiebre2gt ltquiebre10gt ltiniciogt es la direccioacuten de inicio de ejecucioacuten ltquiebre1gt hasta ltquiebre10gt son direcciones opcionales de paro del programa Si no se especifica ltiniciogt Go inicia con la direccioacuten contenida en CSIP Para lograr los quiebres DEBUG reemplaza el coacutedigo en las direcciones de quiebre por el valor hexadecimal CC que es el coacutedigo de interrupcioacuten Si DEBUG llega a CC todos los puntos de quiebre son restituidos los registros se despliegan (como con el comando R [veacutease adelante]) y se para la ejecucioacuten U UNASSEMBLE U ltrangogt Este comando desensambla el contenido de la memoria a partir de la posicioacuten actual Registros y Banderas del DEBUG La mayoriacutea de los comandos de DEBUG ejecutan una accioacuten y vuelven al indicador del shell pero si es un comando largo como puede ser mostrar un trozo grande de coacutedigo puede detenerse pulsando CTRL-Pausa o interrumpirse con CTRL-C para volver al shell Por ejemplo al teclear lo siguiente

- r [Enter]

-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 17A70100 E8CD0F CALL 10D0 - Se desplegaran todos los contenidos de los registros internos del microprocesador una forma alternativa de mostrarlos es usar el comando r utilizando como paraacutemetro el nombre del registro cuyo valor se quiera visualizar Por ejemplo

- r bx Esta instruccioacuten desplegaraacute uacutenicamente el contenido del registro BX y cambia el indicador del DEBUG de - a Estando asiacute el prompt es posible cambiar el valor del registro que se visualizoacute tecleando el nuevo valor y a continuacioacuten [Enter] o se puede dejar el valor anterior presionando [Enter] sin teclear ninguacuten valor Es posible cambiar el valor del registro de banderas asiacute como utilizarlo como estructura de control en nuestros programas como se veraacute maacutes adelante Cada bit del registro tiene un nombre y significado especial la lista dada a continuacioacuten describe el valor de cada bit tanto apagado como prendido y su relacioacuten con las operaciones del microprocesador

Overflow (O) NV = no hay desbordamiento OV = si lo hay Direction (D) UP = hacia adelante DN = hacia atraacutes Interrupts (I) DI = desactivadas EI = activadas Sign (S) PL = positivo NG = negativo Zero (Z) NZ = no es cero ZR = s lo es Auxiliary Carry (A) NA = no hay acarreo auxiliar

AC = hay acarreo auxiliar Parity (P) PO = paridad non PE = paridad par Carry (C) NC = no hay acarreo CY = Si lo hay

La estructura del ensamblador En el lenguaje ensamblador las liacuteneas de coacutedigo constan de dos partes la primera es el nombre de la instruccioacuten que se va a ejecutar y la segunda son los paraacutemetros del comando u operandos Por ejemplo

add ahbh Aquiacute add es el comando a ejecutar (en este caso una adicioacuten) y tanto ah como bh son los paraacutemetros El nombre de las instrucciones en este lenguaje estaacute formado por dos tres o cuatro letras a estas instrucciones tambieacuten se les llama nombres mnemoacutenicos o coacutedigos de operacioacuten ya que representan alguna funcioacuten que habraacute de realizar el microprocesador Existen algunos comandos que no requieren paraacutemetros para su operacioacuten asiacute como otros que requieren solo un paraacutemetro Algunas veces se utilizaraacuten las instrucciones como sigue

add al[170] Los corchetes en el segundo paraacutemetro nos indican que vamos a trabajar con el contenido de la posicioacuten de memoria nuacutemero 170 y no con el valor 170 a esto se le conoce como direccionamiento directo Primer programa en ensamblador con el DEBUG Vamos a crear un programa que sirva para ilustrar lo que hemos estado viendo lo que haremos seraacute una suma de dos valores que introduciremos directamente en el programa El primer paso es iniciar el DEBUG este paso consiste uacutenicamente en teclear DEBUG [Enter] en el prompt del sistema operativo Para ensamblar un programa en el DEBUG se utiliza el comando a (assemble) cuando se utiliza este comando se le puede dar como paraacutemetro la direccioacuten donde se desea que se inicie el ensamblado Si se omite el paraacutemetro el ensamblado se iniciaraacute en la localidad especificada por CSIP usualmente 0100H que es la localidad donde deben iniciar los programas con extensioacuten COM y seraacute la localidad que utilizaremos debido a que DEBUG solo puede crear este tipo especiacutefico de programas

Aunque en este momento no es necesario darle un paraacutemetro al comando a es recomendable hacerlo para evitar problemas una vez que se haga uso de los registros CSIP por lo tanto tecleamos

- a 100 [Enter] Al hacer esto apareceraacute en la pantalla algo como 0C1B0100 y el cursor se posiciona a la derecha de estos nuacutemeros noacutetese que los primeros cuatro diacutegitos (en sistema hexadecimal) pueden ser diferentes pero los uacuteltimos cuatro deben ser 0100 ya que es la direccioacuten que indicamos como inicio Ahora podemos introducir las instrucciones

0C1B0100 mov ax0002 coloca el valor 0002 en el registro ax 0C1B0103 mov bx0004 coloca el valor 0004 en el registro bx 0C1B0106 add axbx le adiciona al contenido de ax el contenido de bx 0C1B0108 int 20 provoca la terminacioacuten del programa 0C1B010A

No es necesario escribir los comentarios que van despueacutes del Una vez escrito el uacuteltimo comando int 20 se le da [Enter] sin escribir nada maacutes para volver al prompt del DEBUG La uacuteltima liacutenea escrita no es propiamente una instruccioacuten de ensamblador es una llamada a una interrupcioacuten del sistema operativo estas interrupciones seraacuten tratadas maacutes a fondo en un capiacutetulo posterior por el momento solo es necesario saber que nos ahorran un gran nuacutemero de liacuteneas y son muy uacutetiles para accesar a funciones del sistema operativo Para ejecutar el programa que escribimos se utiliza el comando g al utilizarlo veremos que aparece un mensaje que dice Program terminated normally Naturalmente con un mensaje como eacuteste no podemos estar seguros que el programa haya hecho la suma pero existe una forma sencilla de verificarlo utilizando el comando r del DEBUG podemos ver los contenidos de todos los registros del microprocesador simplemente teclee

- r [Enter] Apareceraacute en pantalla cada registro con su respectivo valor actual -R AX=0006 BX=0004 CX=0000 DX=0000 SP=FFFE BP=0000 SI=0000 DI=0000 DS=0C1B ES=0C1B SS=0C1B CS=0C1B IP=010A NV UP EI PL NZ NA PO NC 17A70100 E8CD0F CALL 10D0 - Existe la posibilidad de que los registros contengan valores diferentes pero AX y BX deben ser los mismos ya que son los que acabamos de modificar Otra forma de ver los valores mientras se ejecuta el programa es utilizando como paraacutemetro para g la direccioacuten donde queremos que termine la ejecucioacuten y muestre los valores de los registros en este caso seraacute g108 esta instruccioacuten ejecuta el programa se detiene en la direccioacuten 108 y muestra los contenidos de los registros Tambieacuten se puede llevar un seguimiento de lo que pasa en los registros utilizando el comando t (trace) la funcioacuten de este comando es ejecutar liacutenea por liacutenea lo que se ensambloacute mostrando cada vez los contenidos de los registros Para salir del DEBUG se utiliza el comando q (quit)

Guardar y cargar los programas No seriacutea praacutectico tener que escribir todo un programa cada vez que se necesite para evitar eso es posible guardar un programa en el disco con la enorme ventaja de que ya ensamblado no seraacute necesario correr de nuevo DEBUG para ejecutarlo ya que cuando el DEBUG guardo nuestro programa en el disco eacuteste se guardo en binario (archivo con la extensioacuten com) Los pasos a seguir para guardar un programa ya almacenado en la memoria son

Obtener la longitud del programa restando la direccioacuten final de la direccioacuten inicial naturalmente en sistema hexadecimal

Darle un nombre al programa y una extensioacuten

Poner la longitud del programa en el registro CX

Ordenar a DEBUG que escriba el programa en el disco Utilizando como ejemplo el programa del ejemplo anterior tendremos una idea maacutes clara de coacutemo llevar estos pasos Al terminar de ensamblar el programa se veriacutea asiacute

0C1B0100 mov ax0002 0C1B0103 mov bx0004 0C1B0106 add axbx 0C1B0108 int 20 0C1B010A

Para almacenarlo en el disco hacemos lo siguiente - h 10a 100 020a 000a - n pruebacom - r cx CX 0000 000a -w Writing 000A bytes

Para obtener la longitud de un programa se utiliza el comando h el cual nos muestra la suma y resta de dos nuacutemeros en hexadecimal Para obtener la longitud del programa le proporcionamos como paraacutemetros el valor de la direccioacuten final de nuestro programa (10A) y el valor de la direccioacuten inicial (0100) El primer resultado que nos muestra el comando es la suma de los paraacutemetros y el segundo es la resta El comando n nos permite poner un nombre al programa El comando r cx nos permite cambiar el contenido del registro CX al valor que obtuvimos del tamantildeo del archivo con h en este caso 000a ya que nos interesa el resultado de la resta de la direccioacuten inicial a la direccioacuten final

Por uacuteltimo el comando w escribe nuestro programa en el disco indicaacutendonos cuantos bytes escribioacute

NOTA Si se trabaja en una ventana de DOS de Windows Vista o 7 es probable que al momento de guardar su programa el DEBUG escriba mas coacutedigo que el sentildealado por el registro CX por consiguiente seraacute necesario limpiar el registro BX esto es ponerlo a ceros y despueacutes utilizar el comando w Por ejemplo _r bx BX 000E 0000 w

Para cargar un archivo ya guardado son necesarios dos pasos

Proporcionar el nombre del archivo que se cargaraacute a memoria

Cargarlo utilizando el comando l (load) Para obtener el resultado correcto de los siguientes pasos es necesario que previamente se haya creado el programa anterior Dentro del DEBUG escribimos lo siguiente

- n pruebacom - l - u 100 109 0C3D0100 B80200 MOV AX0002 0C3D0103 BB0400 MOV BX0004 0C3D0106 01D8 ADD AXBX 0C3D0108 CD20 INT 20

El uacuteltimo comando u se utiliza para verificar que el programa se cargoacute en memoria lo que hace es desensamblar el coacutedigo y mostrarlo ya desensamblado Los paraacutemetros le indican a DEBUG desde donde y hasta donde desensamblar DEBUG siempre carga los programas en memoria en la direccioacuten 100H a menos que se le indique alguna otra Un programa que realiza un conteo en pantalla Con el DEBUG es posible escribir un programa que realice un conteo en pantalla por razones de comprensioacuten nuestro programa solo realizara un conteo de 9 a 0 (conteo descendente) 0B3B0100 B90A00 MOV CX000A CX=10 en decimal 0B3B0103 88CA MOV DLCL 0B3B0105 80C22F ADD DL2F sumamos 02Fh a DL 0B3B0108 B402 MOV AH02 funcioacuten 02 de INT 21 para imprimir un caracter 0B3B010A CD21 INT 21

0B3B010C E2F5 LOOP 0103 CX=0 Si no salta a 0103 0B3B010E CD20 INT 20 termina el programa En la liacutenea 0103 se puede observar que el valor del registro CX en su parte baja (en CL) se almacena en el registro DL Si se omitiera la liacutenea 0105 entonces cuando se ejecutara la liacutenea 010A solo se imprimiriacutea en pantalla el coacutedigo ASCII del valor que contenga DL (el coacutedigo ASCII de 0Ah que es 10 en decimal es un caraacutecter especial no imprimible) Para conseguir el ldquoefectordquo de que el programa realiza el conteo en decimal se hace un corrimiento de 02F (47 en decimal) Por ejemplo cuando se ejecuta la liacutenea 0105 DL tendriacutea el valor de 39h=57d (02Fh+0Ah=39h=57d) y el coacutedigo ASCII de 57d es el caraacutecter ldquo9rdquo El sentencia LOOP decrementa CX en 1 si CX es diferente a 0 salta a la liacutenea 0103 El proceso se repite y el programa imprime en pantalla 9876543210 Seriacutea interesante que el programa anterior fuera modificado para que la numeracioacuten se imprimiera de la siguiente manera 9 8 7 6 5 4 3 2 1 0

NOTA Como se dijo anteriormente cuando el DEBUG almacena un programa en el disco este archivo se graba en binario esto es en ejecutable Por lo tanto no es necesario cargar el DEBUG para volver a ejecutar nuestro programa sino que se hace de manera directa desde DOS El problema surge cuando al ejecutar nuestro programa el resultado no se puede observar porque el DOS borra la pantalla despueacutes de terminar de ejecutar el programa Para evitar el borrado automaacutetico seraacute necesario agregarle a nuestro programa antes de la INT 20h una instruccioacuten para la lectura de un caraacutecter desde el teclado Para tal efecto utilizaremos la funcioacuten 08 de la INT 21h (un buen truco para que el programa haga una pausa) asiacute el programa esperara hasta que el usuario presiona una tecla permitiendo observar el resultado Ejemplo mov ah08 Int 21 Int 20

Condiciones ciclos y bifurcaciones Estas estructuras o formas de control le dan a la maacutequina un cierto grado de decisioacuten basado en la informacioacuten que recibe La forma maacutes sencilla de comprender este tema es por medio de ejemplos Vamos a crear tres programas que hagan lo mismo desplegar un nuacutemero determinado de veces una cadena de caracteres en la pantalla

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV CX000F veces que se desplegara la cadena 0C1B0128 MOV DX0102 copia cadena al registro DX 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F LOOP 012D si CXgt0 salta a 012D 0C1B0131 INT 20 termina el programa

Por medio del comando e es posible introducir una cadena de caracteres en una determinada localidad de memoria dada como paraacutemetro la cadena se introduce entre comillas le sigue un espacio luego el valor hexadecimal del retorno de carro un espacio el valor de liacutenea nueva y por uacuteltimo el siacutembolo $ que el ensamblador interpreta como final de la cadena La interrupcioacuten 21 utiliza el valor almacenado en el registro AH para ejecutar una determinada funcioacuten en este caso mostrar la cadena en pantalla la cadena que muestra es la que estaacute almacenada en el registro DX La instruccioacuten LOOP decrementa automaacuteticamente el registro CX en uno y si no ha llegado el valor de este registro a cero salta a la posicioacuten de memoria indicada como paraacutemetro lo cual crea un ciclo que se repite el nuacutemero de veces especificado por el valor de CX La interrupcioacuten 20 termina la ejecucioacuten del programa Otra forma de realizar la misma funcioacuten pero sin utilizar el comando LOOP es la siguiente

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV BX000F veces que se desplegara la cadena 0C1B0128 MOV DX0102 copia cadena al registro DX 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F DEC BX decrementa en 1 a BX 0C1B0130 JNZ 012D si BX es diferente a 0 salta a 012D 0C1B0132 INT 20 termina el programa

En este caso se utiliza el registro BX como contador para el programa y por medio de la instruccioacuten DEC se disminuye su valor en 1 La instruccioacuten JNZ verifica si el valor de BX es diferente a 0 esto con base en la bandera NZ en caso afirmativo salta hacia la direccioacuten 012D En caso contrario continuacutea la ejecucioacuten normal del programa y por lo tanto se termina Una uacuteltima variante del programa es utilizando de nuevo a CX como contador pero en lugar de utilizar LOOP utilizaremos decrementos a CX y comparacioacuten de CX a 0

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV DX0102 copia cadena al registro DX 0C1B0128 MOV CX000F veces que se desplegara la cadena 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F DEC CX decrementa en 1 a CX 0C1B0130 JCXZ 0134 si CX es igual a 0 salta a 0134 0C1B0132 JMP 012D salta a la direccioacuten 012D 0C1B0134 INT 20 termina el programa

En este ejemplo se usoacute la instruccioacuten JCXZ para controlar la condicioacuten de salto el significado de tal funcioacuten es salta si CX=0 El tipo de control a utilizar dependeraacute de las necesidades de programacioacuten en determinado momento

Manipulacioacuten de Posiciones de Memoria Con el DEBUG es posible almacenar y recuperar datos numeacutericos en memoria por medio de un programa a traveacutes de los registros del microprocesador Por ejemplo el siguiente programa almacena previamente dos valores numeacutericos en la posicioacuten 0300h y 0400h respectivamente despueacutes el programa los recupera realiza la operacioacuten de suma con esos valores y el resultado lo almacena en la posicioacuten 0500h -a 100 0B1C0100 mov ax0002 ax=2 0B1C0103 mov [0300]ax almacenamos 2 en la direccioacuten 0300h 0B1C0106 mov ax0004 ax=4 0B1C0109 mov [0400]ax almacenamos 4 en la direccioacuten 0400h 0B1C010C mov ax[0300] recuperamos el dato1 en AX 0B1C010F mov bx[0400] recuperamos el dato2 en BX 0B1C0113 add axbx hacemos la operacioacuten de suma en AX 0B1C0115 mov [0500]ax almacenamos el 6 en la direccioacuten 0500h 0B1C0118 int 21 0B1C011A - Un nuacutemero entre corchetes [numero_hex] indica una posicioacuten de memoria y su manejo se hace a traveacutes de registros ya que no es posible almacenar valores numeacutericos de manera directa Ejecutamos el programa -g 118 AX=0006 BX=0004 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=0B1C ES=0B1C SS=0B1C CS=0B1C IP=0118 NV UP EI PL NZ NA PE NC 0B1C0118 CD21 INT 21 - Para ver si el resultado se almaceno en la direccioacuten correcta hacemos

Como se puede observar en la direccioacuten 0B1C0500 se encuentra el 06 y en 0B1C0501 se encuentra el 00 que es el resultado de la operacioacuten 2+4 Perohellip Porque aparece el 06 y despueacutes el 00 pareceriacutea que el resultado fue de 0600 pero no es asiacute lo que sucedes que los datos se almacenan en memoria de la siguiente manera

Como se hizo la operacioacuten AX=AX+BX entonces el resultado es de 16 bits (dos bytes) AX=6 entonces AX=0000 0000 0000 0110 (16 bits) por lo tanto los 8 bits de menor peso de AX son 0000 0110 y deben almacenarse en la direccioacuten 0500 y en la direccioacuten 0501 se almacena 0000 0000

0 0 0 0 0 1 1 0 0500

0 0 0 0 0 0 0 0 0501

x x x x x x x x 0502

x x x x x x x x 0503

x x x x x x x x 0504

x x x x x x x x 0505

Interrupciones Definicioacuten de interrupcioacuten

Una interrupcioacuten es una instruccioacuten que detiene la ejecucioacuten de un programa para permitir el uso del microprocesador en un proceso prioritario Una vez concluido este uacuteltimo proceso se devuelve el control a la aplicacioacuten anterior

Por ejemplo cuando estamos trabajando con un procesador de palabras y en ese momento llega un aviso de uno de los puertos de comunicaciones se detiene temporalmente la aplicacioacuten que estaacutebamos utilizando para permitir el uso del microprocesador al manejo de la informacioacuten que estaacute llegando en ese momento Una vez terminada la transferencia de informacioacuten se reanudan las funciones normales del procesador de palabras Las interrupciones ocurren muy seguido sencillamente la interrupcioacuten que actualiza la hora del diacutea ocurre aproximadamente 18 veces por segundo Para lograr administrar todas estas interrupciones la computadora cuenta con un espacio de memoria llamado memoria baja donde se almacenan las direcciones de cierta localidad de memoria donde se encuentran un juego de instrucciones que el microprocesador ejecutaraacute para despueacutes regresar a la aplicacioacuten que estaba en proceso En los programas anteriores hicimos uso de la interrupcioacuten nuacutemero 20H para terminar la ejecucioacuten de nuestros programas y en otros ejemplos utilizamos otra interrupcioacuten para mostrar informacioacuten en pantalla (INT 21h) Utilizando DEBUG tecleamos

- a100 2C1B0100 JMP 011D 2C1B0102 [ENTER] - E 102 Hola como estas 0D 0A $ - A011D 2C1B011D MOV DX0102 2C1B0120 MOV AH09 2C1B0122 INT 21 2C1B0123 INT 20

Orden

creciente

de la

memoria

En este programa la interrupcioacuten 21h manda al monitor la cadena localizada en la direccioacuten a la que apunta el registro DX El valor que se le da a AH determina cual de las opciones de la interrupcioacuten 21h seraacute utilizada ya que esta interrupcioacuten cuenta con varias opciones El manejo directo de interrupciones es una de las partes maacutes fuertes del lenguaje ensamblador ya que con ellas es posible controlar eficientemente todos los dispositivos internos y externos de una computadora gracias al completo control que se tiene sobre operaciones de entrada y salida Maacutes del DEBUG Una caracteriacutestica poco conocida es que DEBUG puede aceptar entradas desde un archivo Script que puede ser un simple archivo de texto ASCII en el que cada comando esteacute separado del anterior por un INTRO Despueacutes del uacuteltimo que debe ser una Q para salir de DEBUG es conveniente dejar una liacutenea en blanco pulsando INTRO dos veces Las liacuteneas pueden contener comentarios Cualquier cosa a partir del caracter punto y coma () hasta el final de la liacutenea seraacute ignorado esto es un comentario D aquiacute se mostraraacute algo Suponiendo que tengamos un archivo Script de nombre Ordenestxt puede ser utilizado como entrada para DEBUG mediante un comando de redireccioacuten en la siguiente forma DEBUG lt ordenestxt Tambieacuten puede conseguirse que el programa redireccione la salida hacia un archivo que puede ser inspeccionado maacutes 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 podriacutea obtenerse un archivo Resulttxt con el siguiente comando DEBUG lt ordenestxt gt Resulttxt Errores Cuando DEBUG no sabe interpretar un comando muestra un mensaje de error y un indicador ^ debajo del sitio del comando donde estaacute el error Entradas y Salidas DEBUG asume que los datos numeacutericos proporcionados son hexadecimales y cuando se trate de direcciones de memoria deben introducirse en forma segmentada A su vez los resultados son mostrados tambieacuten 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

Cada fila muestra 16 posiciones de memoria a partir de la posicioacuten sentildealada por las columnas de la izquierda que las muestran como segmentodesplazamiento El bloque central muestra el contenido hexadecimal de cada byte mientras que el bloque derecho contiene la representacioacuten ASCII Por ejemplo la 3ra fila muestra el contenido de las posiciones 0B770120 a 0B77012F (ambas inclusive) Sus tres uacuteltimos bytes contienen respectivamente los caracteres r 9 y 2 que corresponden a las cantidades 72h 39h y 32h del bloque central Que como sabemos equivalen a los decimales 114 57 y 50 que son precisamente los valores ASCII de los caracteres ldquorrdquo ldquo9rdquo y ldquo2rdquo anteriormente mencionados

Nota Por razoacuten de que eacuteste tipo de salida pueda ser listado a impresora el bloque derecho no contiene en realidad la representacioacuten ASCII de todos los caracteres (algunos ni siquiera tienen una representacioacuten imprimible) En realidad solo se muestran los caracteres imprimibles del primer bloque (US-ASCII) El resto estaacute 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 caraacutecter imprimible Esto no significa que dichas posiciones representen efectivamente tales valores para la aplicacioacuten que las utiliza Por ejemplo puede que en realidad las dos posiciones de memoria mencionadas (dos octetos o bytes) en vez de los caracteres ldquo5rdquo y ldquoardquo representen una palabra de 16 bits en formato Little Endian que a su vez representan una cantidad entera (un nuacutemero) Comandos Aunque su descripcioacuten completa llenariacutea todo un capiacutetulo a continuacioacuten comentamos algunas de las opciones maacutes interesantes relativas a inspeccioacuten del coacutedigo y de contenidos de memoria La opcioacuten D (Dump) permite obtener un volcado del contenido de la memoria (de DEBUG) La sintaxis acepta dos formas D [direccioacuten-inicial] [L posiciones-desde-direccioacuten-inicial ] D [direccioacuten-inicial][direccioacuten-final] Naturalmente para que exista algo en el buacutefer de memoria (al principio quizaacutes solo contiene basura) es preciso indicarle que lea algo Este algo puede ser un rango de direcciones de memoria RAM una direccioacuten absoluta de disco (sector) un archivo o el contenido de los registros del procesador Para empezar puede indicaacutersele que cargue un archivo xxxxyz que tenemos en el directorio actual o en el PATH cuyo contenido queremos ver Cgt DEBUG xxxxyz -D aquiacute se obtendriacutea una salida anaacuteloga a la comentada

Hemos visto un ejemplo al tratar de los servicios de interrupciones del PC aquiacute mostraremos otro Sabemos que el punto de inicio de la BIOS es la direccioacuten F000FFF0 y que desde eacutesta posicioacuten hasta el final de la memoria DOS hay 16 bytes Puede obtenerse un volcado de estas posiciones con el siguiente comando -D F000FFF0 La salida en un equipo puede ser F000FFF0 CD 19 E0 00 F0 30 36 2F-33 30 2F 39 37 00 FC 38 0630978 En este caso el comando solo muestra una liacutenea porque ha alcanzado el final de la memoria Puede verse que la fecha de la BIOS del sistema ocupa las uacuteltimas posiciones Si se ordena el volcado de una direccioacuten suficientemente alejada del final de la memoria sin indicar ninguacuten nuacutemero de posiciones por defecto se toma el valor 128 (8 filas de 16 posiciones) Si desea una cantidad distinta hay que antildeadir una L (Long) y el nuacutemero de posiciones hasta un maacuteximo de 64 KB (FFFF) Todos los nuacutemeros deben ser expresados en hexadecimal Por consiguiente los dos comandos que siguen son equivalentes (recuerde que 80 es el equivalente hexadecimal de 128) D FE000000 D FE000000 L 80 He aquiacute el resultado

Sabemos que esta zona corresponde al aacuterea de la BIOS del Sistema Otra opcioacuten muy interesante nos permite buscar determinados contenidos a traveacutes de la memoria utilizando el prefijo S (Search) Existen dos sintaxis alternativas S direccioacuten-de-inicio L longitud-a-explorar contenido-a-buscar S direccioacuten-de-inicio direccioacuten-final L contenido-a-buscar El contenido debe ser proporcionado en hexadecimal (tal como apareceriacutea en la columna central del ejemplo anterior) o entre comillas si es un texto ASCII Por ejemplo en un equipo IBM deseo ver algunas caracteriacutesticas de la BIOS Seacute que estos datos se alojan a partir de la posicioacuten F0000000 hasta el final de la memoria Es decir una longitud de 64 Kbytes (FFFF) a partir de la posicioacuten de inicio y que seguramente los datos buscados estaraacuten cerca de la identificacioacuten de la propia BIOS (la cadena IBM) Por lo que se utiliza la siguiente sintaxis [3] -s f0000000 L ffff IBM

y se obtiene la siguiente salida F000E00E F000E111 con las direcciones donde se ha encontrado la ocurrencia buscada A continuacioacuten puedo explorar las proximidades de cada posicioacuten Por ejemplo para la primera -D f000e000

Si lo que se busca estaacute en un archivo primero hay que cargarlo Lo que se puede hacer de dos formas en la propia invocacioacuten de DEBUG o mediante los comandos N y L Por ejemplo si queremos inspeccionar el contenido del archivo morecom podemos utilizar dos formas CWINDOWSgtDEBUG cwindowscommandmorecom CWINDOWSgtDEBUG - N cwindowscommandmorecom - L La sintaxis para el prefijo N es N [path-name]nombre-de-archivo En ambos casos el contenido del archivo seraacute cargado en memoria y podraacute ser utilizado Atencioacuten despueacutes de la orden L (Load) DEBUG le avisaraacute si no encuentra el archivo pero seguiraacute su funcionamiento En tal caso simplemente piensa que N sentildeala el nombre de un nuevo archivo que crearaacute con el contenido de la memoria -de DEBUG- cuando posteriormente seleccione la opcioacuten escribir W (Write)[4]

Nota Como ya habraacute deducido DEBUG permite leer un archivo realizar modificaciones en eacutel (con la opcioacuten E) y escribir el archivo modificado bajo otro nombre con NW

A continuacioacuten podemos comprobar el tamantildeo del archivo cargado Para ello usamos la opcioacuten 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 17A70100 E8CD0F CALL 10D0 -

Aquiacute nos interesa especialmente el contenido del registro CX cuyo valor 2917h (1519d) en este caso sentildeala el tamantildeo del archivo en bytes Tambieacuten podiacuteamos haber utilizado directamente el comando R CX que nos proporciona el valor de dicho registro -R CX CX 2917 -

Nota A continuacioacuten del valor correspondiente DEBUG muestra dos puntos () sentildealando que puede cambiar el valor del registro introduciendo un nuevo nuacutemero Pulse INTRO para dejar las cosas como estaacuten y volver al prompt (-) de DEBUG

Al llegar a este punto es importante sentildealar que a excepcioacuten de los archivos exe DEBUG carga los archivos a partir de la direccioacuten 100h (256d) de su memoria De forma que el primer octeto del archivo se carga en la direccioacuten 100 el segundo en 101 etc En nuestro caso el archivo se extenderaacute desde la posicioacuten 100h hasta 2A17h (100h + 2917h) A continuacioacuten para buscar la cadena Microsoft en el archivo utilizamos cualquiera de los siguientes comandos - S 100 L 2917 Microsoft - S 100 2a17 Microsoft El primer comando sentildeala el punto de inicio y el tamantildeo de la zona a buscar el segundo utiliza los puntos inicial y final de la exploracioacuten Con ambos se obtiene la misma respuesta 17A71083 17A710B2

Truco Debido a la forma especial en que se cargan los ejecutables exe si quiere inspeccionar la forma nativa de uno de estos archivos (como es su imagen en el disco) debe hacer una copia del archivo renombrarlo con cualquier otra terminacioacuten (o sin ella) y cargar esta copia En caso contrario DEBUG se prepararaacute para funcionar como un verdadero depurador de tiempo de ejecucioacuten (run-time) para lo que cargaraacute el archivo y lo acomodaraacute en memoria de forma que pueda ejecutarse [5]

Como ejercicio compruebe las distintas longitudes y aspecto (especialmente al principio) de un mismo archivo exe cargaacutendolo con DEBUG de las dos formas (busque en su sistema un exe lo maacutes pequentildeo posible) Ademaacutes de la capacidad de leer archivos antes mencionada quizaacutes una de las opciones maacutes interesantes (y peligrosas) de DEBUG es la posibilidad de leerescribir el contenido de disco a bajo nivel mediante los prefijos L (Load) y W (Write) Se utiliza la siguiente sintaxis L [Direccioacuten] [Unidad] [Primer_sector] [Nuacutemero] W [Direccioacuten] [Unidad] [Primer_sector] [Nuacutemero] El significado de los paraacutemetros es como sigue

Direccioacuten Posicioacuten de la memoria de DEBUG a partir de la cual se instalaraacuten los datos leiacutedos del disco o se tomaraacuten para el proceso de escritura (aquiacute se utiliza generalmente el valor 100h)

Unidad Valor numeacuterico que indica la loacutegica a utilizar 0 = A 1 = B 2 = C 3 = D etc [6]

Primer sector A partir del que se realizaraacute la lectura o se comenzaraacute a escribir

Nuacutemero Nuacutemero de sectores que se desea cargarescribir Como DEBUG no puede leerescribir maacutes de 64 Kbytes (2

16 = 65536) y los sectores de disco son de 512 bytes

el maacuteximo nuacutemero de sectores es 128 (80h) Asiacute pues el valor maacuteximo aquiacute es 80 Ejemplo Para obtener el contenido del sector de arranque (Master boot sector MBR) de un disquete en A utilizaremos el comando CWINDOWSgtDEBUG - L 100 0 0 1 - D 100 L 200 Como el resultado no cabe en una pantalla ingeniaremos un procedimiento para conservarlo en un archivo (maacutes adelante nos serviraacute para otro propoacutesito) Para ello creamos un archivo scripttxt con el siguiente contenido (dos INTRO despueacutes de la Q) L 100 0 0 1 D 100 L 200 Q A continuacioacuten invocamos DEBUG con el comando CWINDOWSgtDEBUG lt Dbuzonscripttxt gt Dbuzonresultadtxt Despueacutes de un breve parpadeo del disco y del disquete vuelve el prompt del DOS La operacioacuten ha concluido y en el directorio correspondiente de la unidad D tenemos el archivo resultadtxt con el volcado del sector de arranque del disquete ademaacutes de los ecos de los comandos introducidos (los hemos mantenido para orientacioacuten del lector) Otra forma de poder visualizar el contenido del Sector de Arranque del disco es utilizando el DEBUG Por ejemplo dentro del DEBUG tecleamos lo siguiente -L 100 0 0 1

-D 100 L 200

177C0100 EB 3E 90 2B 79 73 57 29-49 48 43 00 02 01 01 00 gt+ysW)IHC

177C0110 02 E0 00 40 0B F0 09 00-12 00 02 00 00 00 00 00

177C0120 00 00 00 00 00 00 29 5D-3B DD 10 4E 4F 20 4E 41 )]NO NA

177C0130 4D 45 20 20 20 20 46 41-54 31 32 20 20 20 F1 7D ME FAT12

177C0140 FA 33 C9 8E D1 BC FC 7B-16 07 BD 78 00 C5 76 00 3xv

177C0150 1E 56 16 55 BF 22 05 89-7E 00 89 4E 02 B1 0B FC VU~N

177C0160 F3 A4 06 1F BD 00 7C C6-45 FE 0F 8B 46 18 88 45 |EFE

177C0170 F9 FB 38 66 24 7C 04 CD-13 72 3C 8A 46 10 98 F7 8f$|rltF

177C0180 66 16 03 46 1C 13 56 1E-03 46 0E 13 D1 50 52 89 fFVFPR

177C0190 46 FC 89 56 FE B8 20 00-8B 76 11 F7 E6 8B 5E 0B FV v^

177C01A0 03 C3 48 F7 F3 01 46 FC-11 4E FE 5A 58 BB 00 07 HFNZX

177C01B0 8B FB B1 01 E8 94 00 72-47 38 2D 74 19 B1 0B 56 rG8-tV

177C01C0 8B 76 3E F3 A6 5E 74 4A-4E 74 0B 03 F9 83 C7 15 vgt^tJNt

177C01D0 3B FB 72 E5 EB D7 2B C9-B8 D8 7D 87 46 3E 3C D8 r+Fgtlt

177C01E0 75 99 BE 80 7D AC 98 03-F0 AC 84 C0 74 17 3C FF utlt

177C01F0 74 09 B4 0E BB 07 00 CD-10 EB EE BE 83 7D EB E5 t

177C0200 BE 81 7D EB E0 33 C0 CD-16 5E 1F 8F 04 8F 44 02 3^D

177C0210 CD 19 BE 82 7D 8B 7D 0F-83 FF 02 72 C8 8B C7 48 rH

177C0220 48 8A 4E 0D F7 E1 03 46-FC 13 56 FE BB 00 07 53 HNFVS

177C0230 B1 04 E8 16 00 5B 72 C8-81 3F 4D 5A 75 A7 81 BF [rMZu

177C0240 00 02 42 4A 75 9F EA 00-02 70 00 50 52 51 91 92 BJupPRQ

177C0250 33 D2 F7 76 18 91 F7 76-18 42 87 CA F7 76 1A 8A 3vvBv

177C0260 F2 8A 56 24 8A E8 D0 CC-D0 CC 0A CC B8 01 02 CD V$

177C0270 13 59 5A 58 72 09 40 75-01 42 03 5E 0B E2 CC C3 YZXruB^

177C0280 03 18 01 27 0D 0A 44 69-73 63 6F 20 69 6E 63 6F Disco inco

177C0290 72 72 65 63 74 6F 20 20-20 FF 0D 0A 45 72 72 6F rrecto Erro

177C02A0 72 20 45 2F 53 20 20 20-20 20 FF 0D 0A 43 61 6D r ES Cam

177C02B0 62 69 65 20 65 6C 20 64-69 73 63 6F 20 79 20 70 bie el disco y p

177C02C0 72 65 73 69 6F 6E 65 20-75 6E 61 20 74 65 63 6C resione una tecl

177C02D0 61 20 20 20 20 0D 0A 00-49 4F 20 20 20 20 20 20 a IO

177C02E0 53 59 53 4D 53 44 4F 53-20 20 20 53 59 53 80 01 SYSMSDOS SYS

177C02F0 00 57 49 4E 42 4F 4F 54-20 53 59 53 00 00 55 AA WINBOOT SYSU

-

-Q

FIN [1] En las primeras versiones de MS-DOS era un modesto programita DEBUGCOM de apenas 16 KB La versioacuten que acompantildea a Windows98 es ya un ejecutable en formato EXE de 21 KB [2] En realidad DEBUG es una utilidad de enorme potencia que requeririacutea todo un libro para ella sola Puede encontrarse una amplia descripcioacuten de esta herramienta en el libro de Paul Somerson PC Magazine DOS Powers Tools [3] Desgraciadamente no hay una convencioacuten estaacutendar sobre la colocacioacuten de los datos en la BIOS de forma que cada fabricante sigue sus propias reglas y es imposible por tanto utilizarla para cualquier tipo de identificacioacuten del sistema [4] En palabras del mencionado Paul Somerson Desgraciadamente debido a que DEBUG es un programa tan increiacuteblemente potente tambieacuten es increiacuteblemente peligroso Hay un dicho que afirma que El software no puede destruir el hardware Desgraciadamente esto no es cierto Ademaacutes de enviar mecanismos sensibles de la unidad de disco a tierra de nadie es posible hacer saltar monitores o transformadores Repito si sigue al pie de la letra las instrucciones y hace caso a todos los avisos todo iraacute bien [5] Recuerde que la imagen de un ejecutable exe cargado en memoria es distinta de su imagen en disco Solo en los ejecutables com la imagen en disco es una imagen exacta de su disposicioacuten en memoria [6] Es evidente que un pequentildeo error de nuacutemero en este paraacutemetro puede acarrear consecuencias nefastas Por ejemplo si cree que estaacute jugando con el disquete e inadvertidamente se dirige al disco duro (relea la nota [4])

Page 2: El Comando DEBUG

cierto cuidado En especial si utiliza el comando W (se puede borrar todo un disco duro con un simple comando erroacuteneo) Para utilizarlo basta invocarlo desde MS-DOS o desde una ventana DOS de Windows Aunque en este uacuteltimo caso algunas de sus funcionalidades maacutes interesantes no se pueden ejecutar (limitadas por Windows) Como se dijo anteriormente el DEBUG es un programa de utileriacutea del Sistema Operativo DOS y Windows Es uacutetil para

Ensamblar pocas liacuteneas de coacutedigo ensamblador

Des-ensamblar coacutedigo 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 eacutestos 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 tambieacuten 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 tambieacuten 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 propoacutesito 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 ldquoLOWrdquo o ldquoBajardquo del registro AX mientras que AH es la parte ldquoHIGHrdquo o parte ldquoAltardquo 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 especiacuteficos

AX Acumulador BX Registro base CX Registro contador DX Registro de datos DS Registro del segmento de datos ES Registro del segmento extra SS Registro del segmento de pila CS Registro del segmento de coacutedigo BP Registro de apuntadores base SI Registro iacutendice fuente DI Registro iacutendice destino SP Registro del apuntador de la pila IP Registro de apuntador de siguiente instruccioacuten F Registro de banderas

Registro AX Este registro es el acumulador principal implicado en gran parte de las operaciones de aritmeacuteticas y de ES Registro BX Recibe el nombre de registro base ya que es el uacutenico registro de propoacutesito general que se usa como un iacutendice en el direccionamiento indexado Se suele utilizar para caacutelculos aritmeacuteticos Registro CX Es conocido como registro contador ya que puede contener un valor para controlar el nuacutemero de veces que se repite una cierta operacioacuten Registro DX Se conoce como registro de datos Algunas operaciones de ES requieren su uso y las operaciones de multiplicacioacuten y divisioacuten con cifras grandes suponen que el DX y el AX trabajando juntos Registro CS Registro Segmento de Coacutedigo Establece el aacuterea de memoria doacutende estaacute el programa durante su ejecucioacuten 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 colocacioacuten 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 estaacute siendo procesada en la pila Registro BP Facilita la referencia a los paraacutemetros de las rutinas los cuales son datos y direcciones transmitidos viacutea la pila Registro SI Registro iacutendice fuente requerido en algunas operaciones con cadenas de caracteres Este registro estaacute asociado con el registro DS Registro DI Registro iacutendice destino requerido tambieacuten en determinadas operaciones con cadenas de caracteres Estaacute 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 direccioacuten de la siguiente instruccioacuten que se ejecutaraacute Estaacute asociado con el registro CS en el sentido de que IP indica el desplazamiento de la siguiente instruccioacuten a ejecutar dentro del segmento de coacutedigo determinado por CS Registro de banderas FLAGS o registro de estado (FL) Es un registro de 16 bits pero soacutelo se utilizan nueve de ellos Sirven para indicar el estado actual de la maacutequina y el resultado del procesamiento La mayor parte de las instrucciones de

comparacioacuten y aritmeacuteticas modifican este registro Algunas instrucciones pueden realizar pruebas sobre este registro para determinar la accioacuten siguiente

OF (O) Bit de Overflow o desbordamiento Indica desbordamiento de un bit de orden alto (maacutes a la izquierda) despueacutes de una operacioacuten aritmeacutetica DF (D) Bit de Direccioacuten Designa la direccioacuten creciente (0) o decreciente (1) en operaciones con cadenas de caracteres IF (I) Bit de Interrupcioacuten Indica que una interrupcioacuten externa como la entrada desde el teclado sea procesada o ignorada TF (T) Bit de Trap o Desviacuteo Procesa o ignora la interrupcioacuten interna de trace (procesamiento paso a paso) SF (S) Bit de Signo Indica el valor del bit maacutes significativo del registro despueacutes de una operacioacuten aritmeacutetica o de desplazamiento ZF (Z) Bit Cero Se pone a 1 si una operacioacuten produce 0 como resultado AF (A) Bit de Carry Auxiliar Se pone a 1 si una operacioacuten aritmeacutetica produce un acarreo del bit 3 al 4 Se usa para aritmeacutetica especializada (ajuste BCD) PF (P) Bit de Paridad Se activa si el resultado de una operacioacuten tiene paridad par CF (C) Bit de Acarreo Contiene el acarreo de una operacioacuten aritmeacutetica 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 Cgt DEBUG [Enter] Una vez que el programa estaacute en ejecucioacuten el indicador (prompt) es un guioacuten - indicando que el Shell espera recibir oacuterdenes Para salir basta pulsar una Q Como muchos programas de su geacutenero sus comandos empiezan por una letra o combinacioacuten de ellas (pueden usarse indistintamente mayuacutesculas o minuacutesculas) y ciertos paraacutemetros opcionales (no es imprescindible separar la letra de opcioacuten de los paraacutemetros opcionales que siguen) La opcioacuten maacutes sencilla es la interrogacioacuten () cuyo resultado es una lista resumida de las opciones disponibles

Ensamblar A [direccioacuten] Comparar C direccioacuten de intervalo Volcar D [intervalo] Escribir E direccioacuten [lista de valores] Llenar F lista de intervalos Ir G [=direccioacuten] [direcciones] Hex H valor1 valor2 Entrada I puerto Cargar L [direccioacuten] [unidad] [primer_sector] [nuacutemero] Mover M direccioacuten de intervalo Nombre N [nombre_ruta] [lista_argumentos] Salida O byte de puerto Proceder P [=direccioacuten] [nuacutemero] Salir Q Registro R [registro] Buscar S lista de intervalos Seguimiento T [=direccioacuten] [valor] Desensamblar U [intervalo] Escribir W [direccioacuten] [unidad] [primer_sector] [nuacutemero] Asignar memoria expandida XA [paacuteginas] Desasignar memoria expandida XD [identificador] Asignar paacuteginas de memoria expandida XM [Lpaacutegina] [Ppaacutegina] [identificador] Mostrar estado de la memoria expandida XS

En particular obseacutervese 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 EJEMPLOCOM entonces carga a EJEMPLOCOM en memoria a partir de la direccioacuten 0100h

Comandos del DEBUG D DUMP D ltdireccioacuten1gt ltdireccioacuten2gt Muestra el contenido de una zona de memoria en hexadecimal y en ASCII Sin paraacutemetros muestra los primeros 128 bytes a partir de la posicioacuten a la que se llegoacute en el uacuteltimo d Si se le da un rango mostraraacute ese rango Ambas direcciones son opcionales La 1ra es la direccioacuten de inicio de despliegue la 2da es la direccioacuten de fin Ejemplo

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

E EDIT E ltdireccioacutengtltlistagt Permite editar byte por byte una zona de memoria Muestra -en hexadecimal- el byte de esa posicioacuten 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 siacute se ha hecho Para terminar la edicioacuten se pulsa INTRO Los cambios pueden ser especificados en la liacutenea de comandos en cualquier combinacioacuten de nuacutemeros hexadecimales o caracteres ASCII los caracteres ASCII deben estar entre comillas simples o dobles Por ejemplo E 100 Benjamin Iglesiasrsquo Establece el patroacuten 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 ltlistagt se entra en un modo especial en el que DEBUG despliega los valores de ltdireccioacutengt 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 ltregistrogt Sin paraacutemetros muestra el contenido de los registros de la CPU asiacute como la proacutexima instruccioacuten a ejecutarR [REGISTRO] muestra el contenido del registro especificado y cambia

el prompt de - a invitando a que se cambie su valor Pulsando Enter sin maacutes lo deja como estaba Ejemplo R ltregistrogt Donde ltregistrogt 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 sinoacutenimos A ASSEMBLE A ltdireccioacutengt Sin paraacutemetros ensambla las instrucciones que se introduzcan guardaacutendolas en la direccioacuten siguiente a la que se llegoacute en el uacuteltimo a Cuando se utiliza este comando se le puede dar como paraacutemetro la direccioacuten donde se desea que se inicie el ensamblado si se omite el paraacutemetro el ensamblado se iniciaraacute en la localizacioacuten especificada por CSIP usualmente 0100H que es la localizacioacuten donde deben iniciar los programas con extensioacuten COM y seraacute la localizacioacuten que utilizaremos debido a que DEBUG solo puede crear este tipo especiacutefico de programas La sintaxis es A ltdireccioacutengt Praacutecticamente cualquier mnemoteacutecnico es soportado por DEBUG incluyendo los especificadores de override de segmento (CS DS ES SS) Una excepcioacuten 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 instruccioacuten MOV que como veremos maacutes adelante sirve para copiar datos de la memoria a los registros y viceversa ademaacutes de copiar datos entre registros que es justo lo que vamos a usar en el ejemplo -a 20480106 mov axbx 20480108 mov bxcx 2048010A ltRETgt -u 106 108 20480106 89D8 MOV AXBX 20480108 89CB MOV BXCX Como veremos maacutes adelante la instruccioacuten U sirve para hacer volcados de memoria pero no viendo el contenido de la misma sino interpretaacutendola como instrucciones en lenguaje ensamblador Ejemplo 2 -r cs CS 2048 2050 -a 200 20500200 mov axbx 20500202 ltRETgt -u 200 200 20500200 89D8 MOV AXBX

F FILL F ltbloquegt ltvalor de rellenogt Este comando llena un bloque de memoria con un valor especiacutefico o una serie de valores La sintaxis es F ltbloquegt ltvalor de rellenogt ltbloquegt es la direccioacuten de inicio y final o si se preceden con L la direccioacuten de inicio y la longitud del bloque ltvalor de rellenogt es(son) el(los) valor(es) con los que debe de llenarse el bloque Si ltvalor de rellenogt 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 liacuteneas llena (con 0rsquos) el bloque DS00FF F DS0000 DS00FF 0 DS0000 LFF 0 Ejemplo -f 100 105 66 -d 100 105 20480100 66 66 66 66 66 66 ffffff Q QUIT Q Salir de DEBUG y volver al DOS P PROCEED P lt=direccioacutengtltnuacutemerogt Similar al comando T pero al encontrarse un CALL o INT lo ejecuta de golpe sin entrar en su interior (ojo iexclesto uacuteltimo falla al tracear sobre memoria ROM) Trace puede ser incoacutemodo si no se quiere depurar el coacutedigo de las rutinas de interrupcioacuten o si ya se sabe el coacutedigo que hay en las subrutinas y tan soacutelo interesa seguir avanzando sin entrar en ellas En estos casos se usa p por lo que si ejecutamos una interrupcioacuten de MS-DOS no sabriacuteamos 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 20480107 3D5000 CMP AX0050 -a 100 20480100 mov ax0200 20480103 mov dl61 20480105 int 21 20480107 -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 20480103 B261 MOV DL61 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 20480105 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 20480107 3D5000 CMP AX0050 T TRACE T lt=direccioacutengt ltvalorgt Ejecuta una instruccioacuten del programa (a partir de CSIP) mostrando a continuacioacuten el estado de los registros y la siguiente instruccioacuten Ejecutar T10 equivaldriacutea a ejecutar 16 veces el comando T Si la instruccioacuten es CALL o INT se ejecutaraacute como tal introducieacutendose 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 20480100 3D0000 CMP AX0000 -r bx BX 0000 2 -a 100 20480100 mov axbx 20480102 -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 20480102 00AC01D8 ADD [SI+D801]CH DSD801=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 20480100 3D0000 CMP AX0000 -a 100 20480100 mov axbx 20480102 mov cxbx 20480104 -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 20480102 89D9 MOV CXBX 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 20480104 01D8 ADD AXBX

N NAME N ltnombre_archivogt Se asigna un nombre al programa que estaacute siendo creado o modificado Se puede indicar la trayectoria de directorios L LOAD L ltbuffergt ltnumdiscogt ltsectorinigt ltnumsectorgt ltbuffergt es la direccioacuten en donde se carga la informacioacuten ltnumdiscogt es el nuacutemero (opcional) del disco de donde se leeraacute la informacioacuten (0=A 1=B 2=C etc) ltsectorinigt es el sector de disco absoluto (en hexadecimal) a leer ltnumsectorgt es la cantidad de sectores a leer No se pueden leer maacutes de 80H (128) sectores Si no se suministra la combinacioacuten ltnumdiscogt ltsectorinigt ltnumsectorgt DEBUG presume que se desea leer un archivo En este caso ltbuffergt es opcional Debe usarse el comando N (ver maacutes adelante) para especificar el archivo a leer Eacuteste se carga en CS0100 Ejemplo Se va a leer el sector 0 del disco A y se vuelca a partir de la direccioacuten DS100 como se puede observar el disco contiene mucha informacioacuten ( ESTO NO QUIERE DECIR QUE TENGA QUE SALIR LO MISMO EN SU VOLCADO )

l 100 0 0 1 -d 100 300

W WRITE W ltdireccioacutengt Graba el contenido de una zona de memoria a disco Si no se indica la direccioacuten se graba desde CS100h hasta CS100h+nuacutemero_bytes el nuacutemero de bytes se indica en BXCX (no es una direccioacuten segmentada sino un valor de 32 bits) Si se trata de un EXE no se permitiraacute grabarlo (para modificarlos hay que renombrarles para cambiarles la extensioacuten aunque de esta manera no seraacuten montados al cargarlos) La sintaxis es W ltbuffergt ltnumdiscogt ltsectorinigt ltnumsectorgt ltbuffergt es la direccioacuten de donde se carga la informacioacuten ltnumdiscogt es el nuacutemero (opcional) del disco en donde se escribiraacute la informacioacuten (0=A 1=B 2=C etc) ltsectorinigt es el sector de disco absoluto (en hexadecimal) en donde empieza la escritura ltnumsectorgt es la cantidad de sectores a leer No se pueden escribir maacutes de 80H (128) sectores Si no se suministra la combinacioacuten ltnumdiscogt ltsectorinigt ltnumsectorgt DEBUG presume que el inicio de archivo es CS100 En este caso ltbuffergt es opcional Debe usarse el comando N (ver arriba) para especificar el archivo a escribir Antes de escribir BXCX debe ajustarse al nuacutemero de bytes que desean grabarse W no puede escribir a archivos con la extensioacuten EXE o HEX [5] Ejemplo

N ltnomarchivogt BXCX lt--- 2000 W

S SEARCH S ltrangogt ltlistagt Busca una cadena de bytes por la memoria Para buscar la cadena PEPE terminada por cero en un aacuterea de 512 bytes desde DS100 se hariacutea S 100 L 200 PEPE0 (por defecto se busca en DS) No se encontrariacutea sin embargo pepe (en minuacutesculas) C COMPARE C ltrangogt ltdireccioacutengt Compara dos zonas de memoria mostrando las diferencias Por ejemplo para comparar 5 bytes de DS100 y DS200 se hace C 100 L 5 200 M MOVE M ltrangogt ltdireccioacutengt Maacutes que mover copia una zona de memoria en otra de manera inteligente (controlando los posibles solapamientos de los bloques) I INPUT I ltpuertogt Visualiza la lectura del puerto de ES indicado

O OUTPUT O ltpuertogt ltvalorgt Enviacutea un valor a un puerto de ES H HEX H ltvalor1gt ltvalor2gt Muestra la suma y resta de valor1 y valor2 ambos operandos de un maacuteximo de 16 bits (si hay desbordamiento se trunca el resultado que tampoco excede los 16 bits) Resultado ltresultado_1gt Es la suma ( ltvalor1gt + ltvalor2gt) ltresultado_2gt es la resta (ltvalor1gt - ltvalor2gt ) Ejemplo -h 0003 0002 0005 0001 -h 0000 0001 0001 FFFF como se observa el resultado de la segunda operacioacuten es FFFF que es el equivalente en complemento a 2 de -1 G GO G =ltiniciogt ltquiebre1gt ltquiebre2gt ltquiebre10gt Este comando ejecuta el coacutedigo en memoria Si se estaacute depurando un programa permite ejecutar el coacutedigo cargado en memoria Tambieacuten permite establecer puntos de quiebre (breakpoints) que son direcciones en las que se detiene la ejecucioacuten del programa La sintaxis es G =ltiniciogt ltquiebre1gt ltquiebre2gt ltquiebre10gt ltiniciogt es la direccioacuten de inicio de ejecucioacuten ltquiebre1gt hasta ltquiebre10gt son direcciones opcionales de paro del programa Si no se especifica ltiniciogt Go inicia con la direccioacuten contenida en CSIP Para lograr los quiebres DEBUG reemplaza el coacutedigo en las direcciones de quiebre por el valor hexadecimal CC que es el coacutedigo de interrupcioacuten Si DEBUG llega a CC todos los puntos de quiebre son restituidos los registros se despliegan (como con el comando R [veacutease adelante]) y se para la ejecucioacuten U UNASSEMBLE U ltrangogt Este comando desensambla el contenido de la memoria a partir de la posicioacuten actual Registros y Banderas del DEBUG La mayoriacutea de los comandos de DEBUG ejecutan una accioacuten y vuelven al indicador del shell pero si es un comando largo como puede ser mostrar un trozo grande de coacutedigo puede detenerse pulsando CTRL-Pausa o interrumpirse con CTRL-C para volver al shell Por ejemplo al teclear lo siguiente

- r [Enter]

-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 17A70100 E8CD0F CALL 10D0 - Se desplegaran todos los contenidos de los registros internos del microprocesador una forma alternativa de mostrarlos es usar el comando r utilizando como paraacutemetro el nombre del registro cuyo valor se quiera visualizar Por ejemplo

- r bx Esta instruccioacuten desplegaraacute uacutenicamente el contenido del registro BX y cambia el indicador del DEBUG de - a Estando asiacute el prompt es posible cambiar el valor del registro que se visualizoacute tecleando el nuevo valor y a continuacioacuten [Enter] o se puede dejar el valor anterior presionando [Enter] sin teclear ninguacuten valor Es posible cambiar el valor del registro de banderas asiacute como utilizarlo como estructura de control en nuestros programas como se veraacute maacutes adelante Cada bit del registro tiene un nombre y significado especial la lista dada a continuacioacuten describe el valor de cada bit tanto apagado como prendido y su relacioacuten con las operaciones del microprocesador

Overflow (O) NV = no hay desbordamiento OV = si lo hay Direction (D) UP = hacia adelante DN = hacia atraacutes Interrupts (I) DI = desactivadas EI = activadas Sign (S) PL = positivo NG = negativo Zero (Z) NZ = no es cero ZR = s lo es Auxiliary Carry (A) NA = no hay acarreo auxiliar

AC = hay acarreo auxiliar Parity (P) PO = paridad non PE = paridad par Carry (C) NC = no hay acarreo CY = Si lo hay

La estructura del ensamblador En el lenguaje ensamblador las liacuteneas de coacutedigo constan de dos partes la primera es el nombre de la instruccioacuten que se va a ejecutar y la segunda son los paraacutemetros del comando u operandos Por ejemplo

add ahbh Aquiacute add es el comando a ejecutar (en este caso una adicioacuten) y tanto ah como bh son los paraacutemetros El nombre de las instrucciones en este lenguaje estaacute formado por dos tres o cuatro letras a estas instrucciones tambieacuten se les llama nombres mnemoacutenicos o coacutedigos de operacioacuten ya que representan alguna funcioacuten que habraacute de realizar el microprocesador Existen algunos comandos que no requieren paraacutemetros para su operacioacuten asiacute como otros que requieren solo un paraacutemetro Algunas veces se utilizaraacuten las instrucciones como sigue

add al[170] Los corchetes en el segundo paraacutemetro nos indican que vamos a trabajar con el contenido de la posicioacuten de memoria nuacutemero 170 y no con el valor 170 a esto se le conoce como direccionamiento directo Primer programa en ensamblador con el DEBUG Vamos a crear un programa que sirva para ilustrar lo que hemos estado viendo lo que haremos seraacute una suma de dos valores que introduciremos directamente en el programa El primer paso es iniciar el DEBUG este paso consiste uacutenicamente en teclear DEBUG [Enter] en el prompt del sistema operativo Para ensamblar un programa en el DEBUG se utiliza el comando a (assemble) cuando se utiliza este comando se le puede dar como paraacutemetro la direccioacuten donde se desea que se inicie el ensamblado Si se omite el paraacutemetro el ensamblado se iniciaraacute en la localidad especificada por CSIP usualmente 0100H que es la localidad donde deben iniciar los programas con extensioacuten COM y seraacute la localidad que utilizaremos debido a que DEBUG solo puede crear este tipo especiacutefico de programas

Aunque en este momento no es necesario darle un paraacutemetro al comando a es recomendable hacerlo para evitar problemas una vez que se haga uso de los registros CSIP por lo tanto tecleamos

- a 100 [Enter] Al hacer esto apareceraacute en la pantalla algo como 0C1B0100 y el cursor se posiciona a la derecha de estos nuacutemeros noacutetese que los primeros cuatro diacutegitos (en sistema hexadecimal) pueden ser diferentes pero los uacuteltimos cuatro deben ser 0100 ya que es la direccioacuten que indicamos como inicio Ahora podemos introducir las instrucciones

0C1B0100 mov ax0002 coloca el valor 0002 en el registro ax 0C1B0103 mov bx0004 coloca el valor 0004 en el registro bx 0C1B0106 add axbx le adiciona al contenido de ax el contenido de bx 0C1B0108 int 20 provoca la terminacioacuten del programa 0C1B010A

No es necesario escribir los comentarios que van despueacutes del Una vez escrito el uacuteltimo comando int 20 se le da [Enter] sin escribir nada maacutes para volver al prompt del DEBUG La uacuteltima liacutenea escrita no es propiamente una instruccioacuten de ensamblador es una llamada a una interrupcioacuten del sistema operativo estas interrupciones seraacuten tratadas maacutes a fondo en un capiacutetulo posterior por el momento solo es necesario saber que nos ahorran un gran nuacutemero de liacuteneas y son muy uacutetiles para accesar a funciones del sistema operativo Para ejecutar el programa que escribimos se utiliza el comando g al utilizarlo veremos que aparece un mensaje que dice Program terminated normally Naturalmente con un mensaje como eacuteste no podemos estar seguros que el programa haya hecho la suma pero existe una forma sencilla de verificarlo utilizando el comando r del DEBUG podemos ver los contenidos de todos los registros del microprocesador simplemente teclee

- r [Enter] Apareceraacute en pantalla cada registro con su respectivo valor actual -R AX=0006 BX=0004 CX=0000 DX=0000 SP=FFFE BP=0000 SI=0000 DI=0000 DS=0C1B ES=0C1B SS=0C1B CS=0C1B IP=010A NV UP EI PL NZ NA PO NC 17A70100 E8CD0F CALL 10D0 - Existe la posibilidad de que los registros contengan valores diferentes pero AX y BX deben ser los mismos ya que son los que acabamos de modificar Otra forma de ver los valores mientras se ejecuta el programa es utilizando como paraacutemetro para g la direccioacuten donde queremos que termine la ejecucioacuten y muestre los valores de los registros en este caso seraacute g108 esta instruccioacuten ejecuta el programa se detiene en la direccioacuten 108 y muestra los contenidos de los registros Tambieacuten se puede llevar un seguimiento de lo que pasa en los registros utilizando el comando t (trace) la funcioacuten de este comando es ejecutar liacutenea por liacutenea lo que se ensambloacute mostrando cada vez los contenidos de los registros Para salir del DEBUG se utiliza el comando q (quit)

Guardar y cargar los programas No seriacutea praacutectico tener que escribir todo un programa cada vez que se necesite para evitar eso es posible guardar un programa en el disco con la enorme ventaja de que ya ensamblado no seraacute necesario correr de nuevo DEBUG para ejecutarlo ya que cuando el DEBUG guardo nuestro programa en el disco eacuteste se guardo en binario (archivo con la extensioacuten com) Los pasos a seguir para guardar un programa ya almacenado en la memoria son

Obtener la longitud del programa restando la direccioacuten final de la direccioacuten inicial naturalmente en sistema hexadecimal

Darle un nombre al programa y una extensioacuten

Poner la longitud del programa en el registro CX

Ordenar a DEBUG que escriba el programa en el disco Utilizando como ejemplo el programa del ejemplo anterior tendremos una idea maacutes clara de coacutemo llevar estos pasos Al terminar de ensamblar el programa se veriacutea asiacute

0C1B0100 mov ax0002 0C1B0103 mov bx0004 0C1B0106 add axbx 0C1B0108 int 20 0C1B010A

Para almacenarlo en el disco hacemos lo siguiente - h 10a 100 020a 000a - n pruebacom - r cx CX 0000 000a -w Writing 000A bytes

Para obtener la longitud de un programa se utiliza el comando h el cual nos muestra la suma y resta de dos nuacutemeros en hexadecimal Para obtener la longitud del programa le proporcionamos como paraacutemetros el valor de la direccioacuten final de nuestro programa (10A) y el valor de la direccioacuten inicial (0100) El primer resultado que nos muestra el comando es la suma de los paraacutemetros y el segundo es la resta El comando n nos permite poner un nombre al programa El comando r cx nos permite cambiar el contenido del registro CX al valor que obtuvimos del tamantildeo del archivo con h en este caso 000a ya que nos interesa el resultado de la resta de la direccioacuten inicial a la direccioacuten final

Por uacuteltimo el comando w escribe nuestro programa en el disco indicaacutendonos cuantos bytes escribioacute

NOTA Si se trabaja en una ventana de DOS de Windows Vista o 7 es probable que al momento de guardar su programa el DEBUG escriba mas coacutedigo que el sentildealado por el registro CX por consiguiente seraacute necesario limpiar el registro BX esto es ponerlo a ceros y despueacutes utilizar el comando w Por ejemplo _r bx BX 000E 0000 w

Para cargar un archivo ya guardado son necesarios dos pasos

Proporcionar el nombre del archivo que se cargaraacute a memoria

Cargarlo utilizando el comando l (load) Para obtener el resultado correcto de los siguientes pasos es necesario que previamente se haya creado el programa anterior Dentro del DEBUG escribimos lo siguiente

- n pruebacom - l - u 100 109 0C3D0100 B80200 MOV AX0002 0C3D0103 BB0400 MOV BX0004 0C3D0106 01D8 ADD AXBX 0C3D0108 CD20 INT 20

El uacuteltimo comando u se utiliza para verificar que el programa se cargoacute en memoria lo que hace es desensamblar el coacutedigo y mostrarlo ya desensamblado Los paraacutemetros le indican a DEBUG desde donde y hasta donde desensamblar DEBUG siempre carga los programas en memoria en la direccioacuten 100H a menos que se le indique alguna otra Un programa que realiza un conteo en pantalla Con el DEBUG es posible escribir un programa que realice un conteo en pantalla por razones de comprensioacuten nuestro programa solo realizara un conteo de 9 a 0 (conteo descendente) 0B3B0100 B90A00 MOV CX000A CX=10 en decimal 0B3B0103 88CA MOV DLCL 0B3B0105 80C22F ADD DL2F sumamos 02Fh a DL 0B3B0108 B402 MOV AH02 funcioacuten 02 de INT 21 para imprimir un caracter 0B3B010A CD21 INT 21

0B3B010C E2F5 LOOP 0103 CX=0 Si no salta a 0103 0B3B010E CD20 INT 20 termina el programa En la liacutenea 0103 se puede observar que el valor del registro CX en su parte baja (en CL) se almacena en el registro DL Si se omitiera la liacutenea 0105 entonces cuando se ejecutara la liacutenea 010A solo se imprimiriacutea en pantalla el coacutedigo ASCII del valor que contenga DL (el coacutedigo ASCII de 0Ah que es 10 en decimal es un caraacutecter especial no imprimible) Para conseguir el ldquoefectordquo de que el programa realiza el conteo en decimal se hace un corrimiento de 02F (47 en decimal) Por ejemplo cuando se ejecuta la liacutenea 0105 DL tendriacutea el valor de 39h=57d (02Fh+0Ah=39h=57d) y el coacutedigo ASCII de 57d es el caraacutecter ldquo9rdquo El sentencia LOOP decrementa CX en 1 si CX es diferente a 0 salta a la liacutenea 0103 El proceso se repite y el programa imprime en pantalla 9876543210 Seriacutea interesante que el programa anterior fuera modificado para que la numeracioacuten se imprimiera de la siguiente manera 9 8 7 6 5 4 3 2 1 0

NOTA Como se dijo anteriormente cuando el DEBUG almacena un programa en el disco este archivo se graba en binario esto es en ejecutable Por lo tanto no es necesario cargar el DEBUG para volver a ejecutar nuestro programa sino que se hace de manera directa desde DOS El problema surge cuando al ejecutar nuestro programa el resultado no se puede observar porque el DOS borra la pantalla despueacutes de terminar de ejecutar el programa Para evitar el borrado automaacutetico seraacute necesario agregarle a nuestro programa antes de la INT 20h una instruccioacuten para la lectura de un caraacutecter desde el teclado Para tal efecto utilizaremos la funcioacuten 08 de la INT 21h (un buen truco para que el programa haga una pausa) asiacute el programa esperara hasta que el usuario presiona una tecla permitiendo observar el resultado Ejemplo mov ah08 Int 21 Int 20

Condiciones ciclos y bifurcaciones Estas estructuras o formas de control le dan a la maacutequina un cierto grado de decisioacuten basado en la informacioacuten que recibe La forma maacutes sencilla de comprender este tema es por medio de ejemplos Vamos a crear tres programas que hagan lo mismo desplegar un nuacutemero determinado de veces una cadena de caracteres en la pantalla

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV CX000F veces que se desplegara la cadena 0C1B0128 MOV DX0102 copia cadena al registro DX 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F LOOP 012D si CXgt0 salta a 012D 0C1B0131 INT 20 termina el programa

Por medio del comando e es posible introducir una cadena de caracteres en una determinada localidad de memoria dada como paraacutemetro la cadena se introduce entre comillas le sigue un espacio luego el valor hexadecimal del retorno de carro un espacio el valor de liacutenea nueva y por uacuteltimo el siacutembolo $ que el ensamblador interpreta como final de la cadena La interrupcioacuten 21 utiliza el valor almacenado en el registro AH para ejecutar una determinada funcioacuten en este caso mostrar la cadena en pantalla la cadena que muestra es la que estaacute almacenada en el registro DX La instruccioacuten LOOP decrementa automaacuteticamente el registro CX en uno y si no ha llegado el valor de este registro a cero salta a la posicioacuten de memoria indicada como paraacutemetro lo cual crea un ciclo que se repite el nuacutemero de veces especificado por el valor de CX La interrupcioacuten 20 termina la ejecucioacuten del programa Otra forma de realizar la misma funcioacuten pero sin utilizar el comando LOOP es la siguiente

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV BX000F veces que se desplegara la cadena 0C1B0128 MOV DX0102 copia cadena al registro DX 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F DEC BX decrementa en 1 a BX 0C1B0130 JNZ 012D si BX es diferente a 0 salta a 012D 0C1B0132 INT 20 termina el programa

En este caso se utiliza el registro BX como contador para el programa y por medio de la instruccioacuten DEC se disminuye su valor en 1 La instruccioacuten JNZ verifica si el valor de BX es diferente a 0 esto con base en la bandera NZ en caso afirmativo salta hacia la direccioacuten 012D En caso contrario continuacutea la ejecucioacuten normal del programa y por lo tanto se termina Una uacuteltima variante del programa es utilizando de nuevo a CX como contador pero en lugar de utilizar LOOP utilizaremos decrementos a CX y comparacioacuten de CX a 0

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV DX0102 copia cadena al registro DX 0C1B0128 MOV CX000F veces que se desplegara la cadena 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F DEC CX decrementa en 1 a CX 0C1B0130 JCXZ 0134 si CX es igual a 0 salta a 0134 0C1B0132 JMP 012D salta a la direccioacuten 012D 0C1B0134 INT 20 termina el programa

En este ejemplo se usoacute la instruccioacuten JCXZ para controlar la condicioacuten de salto el significado de tal funcioacuten es salta si CX=0 El tipo de control a utilizar dependeraacute de las necesidades de programacioacuten en determinado momento

Manipulacioacuten de Posiciones de Memoria Con el DEBUG es posible almacenar y recuperar datos numeacutericos en memoria por medio de un programa a traveacutes de los registros del microprocesador Por ejemplo el siguiente programa almacena previamente dos valores numeacutericos en la posicioacuten 0300h y 0400h respectivamente despueacutes el programa los recupera realiza la operacioacuten de suma con esos valores y el resultado lo almacena en la posicioacuten 0500h -a 100 0B1C0100 mov ax0002 ax=2 0B1C0103 mov [0300]ax almacenamos 2 en la direccioacuten 0300h 0B1C0106 mov ax0004 ax=4 0B1C0109 mov [0400]ax almacenamos 4 en la direccioacuten 0400h 0B1C010C mov ax[0300] recuperamos el dato1 en AX 0B1C010F mov bx[0400] recuperamos el dato2 en BX 0B1C0113 add axbx hacemos la operacioacuten de suma en AX 0B1C0115 mov [0500]ax almacenamos el 6 en la direccioacuten 0500h 0B1C0118 int 21 0B1C011A - Un nuacutemero entre corchetes [numero_hex] indica una posicioacuten de memoria y su manejo se hace a traveacutes de registros ya que no es posible almacenar valores numeacutericos de manera directa Ejecutamos el programa -g 118 AX=0006 BX=0004 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=0B1C ES=0B1C SS=0B1C CS=0B1C IP=0118 NV UP EI PL NZ NA PE NC 0B1C0118 CD21 INT 21 - Para ver si el resultado se almaceno en la direccioacuten correcta hacemos

Como se puede observar en la direccioacuten 0B1C0500 se encuentra el 06 y en 0B1C0501 se encuentra el 00 que es el resultado de la operacioacuten 2+4 Perohellip Porque aparece el 06 y despueacutes el 00 pareceriacutea que el resultado fue de 0600 pero no es asiacute lo que sucedes que los datos se almacenan en memoria de la siguiente manera

Como se hizo la operacioacuten AX=AX+BX entonces el resultado es de 16 bits (dos bytes) AX=6 entonces AX=0000 0000 0000 0110 (16 bits) por lo tanto los 8 bits de menor peso de AX son 0000 0110 y deben almacenarse en la direccioacuten 0500 y en la direccioacuten 0501 se almacena 0000 0000

0 0 0 0 0 1 1 0 0500

0 0 0 0 0 0 0 0 0501

x x x x x x x x 0502

x x x x x x x x 0503

x x x x x x x x 0504

x x x x x x x x 0505

Interrupciones Definicioacuten de interrupcioacuten

Una interrupcioacuten es una instruccioacuten que detiene la ejecucioacuten de un programa para permitir el uso del microprocesador en un proceso prioritario Una vez concluido este uacuteltimo proceso se devuelve el control a la aplicacioacuten anterior

Por ejemplo cuando estamos trabajando con un procesador de palabras y en ese momento llega un aviso de uno de los puertos de comunicaciones se detiene temporalmente la aplicacioacuten que estaacutebamos utilizando para permitir el uso del microprocesador al manejo de la informacioacuten que estaacute llegando en ese momento Una vez terminada la transferencia de informacioacuten se reanudan las funciones normales del procesador de palabras Las interrupciones ocurren muy seguido sencillamente la interrupcioacuten que actualiza la hora del diacutea ocurre aproximadamente 18 veces por segundo Para lograr administrar todas estas interrupciones la computadora cuenta con un espacio de memoria llamado memoria baja donde se almacenan las direcciones de cierta localidad de memoria donde se encuentran un juego de instrucciones que el microprocesador ejecutaraacute para despueacutes regresar a la aplicacioacuten que estaba en proceso En los programas anteriores hicimos uso de la interrupcioacuten nuacutemero 20H para terminar la ejecucioacuten de nuestros programas y en otros ejemplos utilizamos otra interrupcioacuten para mostrar informacioacuten en pantalla (INT 21h) Utilizando DEBUG tecleamos

- a100 2C1B0100 JMP 011D 2C1B0102 [ENTER] - E 102 Hola como estas 0D 0A $ - A011D 2C1B011D MOV DX0102 2C1B0120 MOV AH09 2C1B0122 INT 21 2C1B0123 INT 20

Orden

creciente

de la

memoria

En este programa la interrupcioacuten 21h manda al monitor la cadena localizada en la direccioacuten a la que apunta el registro DX El valor que se le da a AH determina cual de las opciones de la interrupcioacuten 21h seraacute utilizada ya que esta interrupcioacuten cuenta con varias opciones El manejo directo de interrupciones es una de las partes maacutes fuertes del lenguaje ensamblador ya que con ellas es posible controlar eficientemente todos los dispositivos internos y externos de una computadora gracias al completo control que se tiene sobre operaciones de entrada y salida Maacutes del DEBUG Una caracteriacutestica poco conocida es que DEBUG puede aceptar entradas desde un archivo Script que puede ser un simple archivo de texto ASCII en el que cada comando esteacute separado del anterior por un INTRO Despueacutes del uacuteltimo que debe ser una Q para salir de DEBUG es conveniente dejar una liacutenea en blanco pulsando INTRO dos veces Las liacuteneas pueden contener comentarios Cualquier cosa a partir del caracter punto y coma () hasta el final de la liacutenea seraacute ignorado esto es un comentario D aquiacute se mostraraacute algo Suponiendo que tengamos un archivo Script de nombre Ordenestxt puede ser utilizado como entrada para DEBUG mediante un comando de redireccioacuten en la siguiente forma DEBUG lt ordenestxt Tambieacuten puede conseguirse que el programa redireccione la salida hacia un archivo que puede ser inspeccionado maacutes 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 podriacutea obtenerse un archivo Resulttxt con el siguiente comando DEBUG lt ordenestxt gt Resulttxt Errores Cuando DEBUG no sabe interpretar un comando muestra un mensaje de error y un indicador ^ debajo del sitio del comando donde estaacute el error Entradas y Salidas DEBUG asume que los datos numeacutericos proporcionados son hexadecimales y cuando se trate de direcciones de memoria deben introducirse en forma segmentada A su vez los resultados son mostrados tambieacuten 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

Cada fila muestra 16 posiciones de memoria a partir de la posicioacuten sentildealada por las columnas de la izquierda que las muestran como segmentodesplazamiento El bloque central muestra el contenido hexadecimal de cada byte mientras que el bloque derecho contiene la representacioacuten ASCII Por ejemplo la 3ra fila muestra el contenido de las posiciones 0B770120 a 0B77012F (ambas inclusive) Sus tres uacuteltimos bytes contienen respectivamente los caracteres r 9 y 2 que corresponden a las cantidades 72h 39h y 32h del bloque central Que como sabemos equivalen a los decimales 114 57 y 50 que son precisamente los valores ASCII de los caracteres ldquorrdquo ldquo9rdquo y ldquo2rdquo anteriormente mencionados

Nota Por razoacuten de que eacuteste tipo de salida pueda ser listado a impresora el bloque derecho no contiene en realidad la representacioacuten ASCII de todos los caracteres (algunos ni siquiera tienen una representacioacuten imprimible) En realidad solo se muestran los caracteres imprimibles del primer bloque (US-ASCII) El resto estaacute 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 caraacutecter imprimible Esto no significa que dichas posiciones representen efectivamente tales valores para la aplicacioacuten que las utiliza Por ejemplo puede que en realidad las dos posiciones de memoria mencionadas (dos octetos o bytes) en vez de los caracteres ldquo5rdquo y ldquoardquo representen una palabra de 16 bits en formato Little Endian que a su vez representan una cantidad entera (un nuacutemero) Comandos Aunque su descripcioacuten completa llenariacutea todo un capiacutetulo a continuacioacuten comentamos algunas de las opciones maacutes interesantes relativas a inspeccioacuten del coacutedigo y de contenidos de memoria La opcioacuten D (Dump) permite obtener un volcado del contenido de la memoria (de DEBUG) La sintaxis acepta dos formas D [direccioacuten-inicial] [L posiciones-desde-direccioacuten-inicial ] D [direccioacuten-inicial][direccioacuten-final] Naturalmente para que exista algo en el buacutefer de memoria (al principio quizaacutes solo contiene basura) es preciso indicarle que lea algo Este algo puede ser un rango de direcciones de memoria RAM una direccioacuten absoluta de disco (sector) un archivo o el contenido de los registros del procesador Para empezar puede indicaacutersele que cargue un archivo xxxxyz que tenemos en el directorio actual o en el PATH cuyo contenido queremos ver Cgt DEBUG xxxxyz -D aquiacute se obtendriacutea una salida anaacuteloga a la comentada

Hemos visto un ejemplo al tratar de los servicios de interrupciones del PC aquiacute mostraremos otro Sabemos que el punto de inicio de la BIOS es la direccioacuten F000FFF0 y que desde eacutesta posicioacuten hasta el final de la memoria DOS hay 16 bytes Puede obtenerse un volcado de estas posiciones con el siguiente comando -D F000FFF0 La salida en un equipo puede ser F000FFF0 CD 19 E0 00 F0 30 36 2F-33 30 2F 39 37 00 FC 38 0630978 En este caso el comando solo muestra una liacutenea porque ha alcanzado el final de la memoria Puede verse que la fecha de la BIOS del sistema ocupa las uacuteltimas posiciones Si se ordena el volcado de una direccioacuten suficientemente alejada del final de la memoria sin indicar ninguacuten nuacutemero de posiciones por defecto se toma el valor 128 (8 filas de 16 posiciones) Si desea una cantidad distinta hay que antildeadir una L (Long) y el nuacutemero de posiciones hasta un maacuteximo de 64 KB (FFFF) Todos los nuacutemeros deben ser expresados en hexadecimal Por consiguiente los dos comandos que siguen son equivalentes (recuerde que 80 es el equivalente hexadecimal de 128) D FE000000 D FE000000 L 80 He aquiacute el resultado

Sabemos que esta zona corresponde al aacuterea de la BIOS del Sistema Otra opcioacuten muy interesante nos permite buscar determinados contenidos a traveacutes de la memoria utilizando el prefijo S (Search) Existen dos sintaxis alternativas S direccioacuten-de-inicio L longitud-a-explorar contenido-a-buscar S direccioacuten-de-inicio direccioacuten-final L contenido-a-buscar El contenido debe ser proporcionado en hexadecimal (tal como apareceriacutea en la columna central del ejemplo anterior) o entre comillas si es un texto ASCII Por ejemplo en un equipo IBM deseo ver algunas caracteriacutesticas de la BIOS Seacute que estos datos se alojan a partir de la posicioacuten F0000000 hasta el final de la memoria Es decir una longitud de 64 Kbytes (FFFF) a partir de la posicioacuten de inicio y que seguramente los datos buscados estaraacuten cerca de la identificacioacuten de la propia BIOS (la cadena IBM) Por lo que se utiliza la siguiente sintaxis [3] -s f0000000 L ffff IBM

y se obtiene la siguiente salida F000E00E F000E111 con las direcciones donde se ha encontrado la ocurrencia buscada A continuacioacuten puedo explorar las proximidades de cada posicioacuten Por ejemplo para la primera -D f000e000

Si lo que se busca estaacute en un archivo primero hay que cargarlo Lo que se puede hacer de dos formas en la propia invocacioacuten de DEBUG o mediante los comandos N y L Por ejemplo si queremos inspeccionar el contenido del archivo morecom podemos utilizar dos formas CWINDOWSgtDEBUG cwindowscommandmorecom CWINDOWSgtDEBUG - N cwindowscommandmorecom - L La sintaxis para el prefijo N es N [path-name]nombre-de-archivo En ambos casos el contenido del archivo seraacute cargado en memoria y podraacute ser utilizado Atencioacuten despueacutes de la orden L (Load) DEBUG le avisaraacute si no encuentra el archivo pero seguiraacute su funcionamiento En tal caso simplemente piensa que N sentildeala el nombre de un nuevo archivo que crearaacute con el contenido de la memoria -de DEBUG- cuando posteriormente seleccione la opcioacuten escribir W (Write)[4]

Nota Como ya habraacute deducido DEBUG permite leer un archivo realizar modificaciones en eacutel (con la opcioacuten E) y escribir el archivo modificado bajo otro nombre con NW

A continuacioacuten podemos comprobar el tamantildeo del archivo cargado Para ello usamos la opcioacuten 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 17A70100 E8CD0F CALL 10D0 -

Aquiacute nos interesa especialmente el contenido del registro CX cuyo valor 2917h (1519d) en este caso sentildeala el tamantildeo del archivo en bytes Tambieacuten podiacuteamos haber utilizado directamente el comando R CX que nos proporciona el valor de dicho registro -R CX CX 2917 -

Nota A continuacioacuten del valor correspondiente DEBUG muestra dos puntos () sentildealando que puede cambiar el valor del registro introduciendo un nuevo nuacutemero Pulse INTRO para dejar las cosas como estaacuten y volver al prompt (-) de DEBUG

Al llegar a este punto es importante sentildealar que a excepcioacuten de los archivos exe DEBUG carga los archivos a partir de la direccioacuten 100h (256d) de su memoria De forma que el primer octeto del archivo se carga en la direccioacuten 100 el segundo en 101 etc En nuestro caso el archivo se extenderaacute desde la posicioacuten 100h hasta 2A17h (100h + 2917h) A continuacioacuten para buscar la cadena Microsoft en el archivo utilizamos cualquiera de los siguientes comandos - S 100 L 2917 Microsoft - S 100 2a17 Microsoft El primer comando sentildeala el punto de inicio y el tamantildeo de la zona a buscar el segundo utiliza los puntos inicial y final de la exploracioacuten Con ambos se obtiene la misma respuesta 17A71083 17A710B2

Truco Debido a la forma especial en que se cargan los ejecutables exe si quiere inspeccionar la forma nativa de uno de estos archivos (como es su imagen en el disco) debe hacer una copia del archivo renombrarlo con cualquier otra terminacioacuten (o sin ella) y cargar esta copia En caso contrario DEBUG se prepararaacute para funcionar como un verdadero depurador de tiempo de ejecucioacuten (run-time) para lo que cargaraacute el archivo y lo acomodaraacute en memoria de forma que pueda ejecutarse [5]

Como ejercicio compruebe las distintas longitudes y aspecto (especialmente al principio) de un mismo archivo exe cargaacutendolo con DEBUG de las dos formas (busque en su sistema un exe lo maacutes pequentildeo posible) Ademaacutes de la capacidad de leer archivos antes mencionada quizaacutes una de las opciones maacutes interesantes (y peligrosas) de DEBUG es la posibilidad de leerescribir el contenido de disco a bajo nivel mediante los prefijos L (Load) y W (Write) Se utiliza la siguiente sintaxis L [Direccioacuten] [Unidad] [Primer_sector] [Nuacutemero] W [Direccioacuten] [Unidad] [Primer_sector] [Nuacutemero] El significado de los paraacutemetros es como sigue

Direccioacuten Posicioacuten de la memoria de DEBUG a partir de la cual se instalaraacuten los datos leiacutedos del disco o se tomaraacuten para el proceso de escritura (aquiacute se utiliza generalmente el valor 100h)

Unidad Valor numeacuterico que indica la loacutegica a utilizar 0 = A 1 = B 2 = C 3 = D etc [6]

Primer sector A partir del que se realizaraacute la lectura o se comenzaraacute a escribir

Nuacutemero Nuacutemero de sectores que se desea cargarescribir Como DEBUG no puede leerescribir maacutes de 64 Kbytes (2

16 = 65536) y los sectores de disco son de 512 bytes

el maacuteximo nuacutemero de sectores es 128 (80h) Asiacute pues el valor maacuteximo aquiacute es 80 Ejemplo Para obtener el contenido del sector de arranque (Master boot sector MBR) de un disquete en A utilizaremos el comando CWINDOWSgtDEBUG - L 100 0 0 1 - D 100 L 200 Como el resultado no cabe en una pantalla ingeniaremos un procedimiento para conservarlo en un archivo (maacutes adelante nos serviraacute para otro propoacutesito) Para ello creamos un archivo scripttxt con el siguiente contenido (dos INTRO despueacutes de la Q) L 100 0 0 1 D 100 L 200 Q A continuacioacuten invocamos DEBUG con el comando CWINDOWSgtDEBUG lt Dbuzonscripttxt gt Dbuzonresultadtxt Despueacutes de un breve parpadeo del disco y del disquete vuelve el prompt del DOS La operacioacuten ha concluido y en el directorio correspondiente de la unidad D tenemos el archivo resultadtxt con el volcado del sector de arranque del disquete ademaacutes de los ecos de los comandos introducidos (los hemos mantenido para orientacioacuten del lector) Otra forma de poder visualizar el contenido del Sector de Arranque del disco es utilizando el DEBUG Por ejemplo dentro del DEBUG tecleamos lo siguiente -L 100 0 0 1

-D 100 L 200

177C0100 EB 3E 90 2B 79 73 57 29-49 48 43 00 02 01 01 00 gt+ysW)IHC

177C0110 02 E0 00 40 0B F0 09 00-12 00 02 00 00 00 00 00

177C0120 00 00 00 00 00 00 29 5D-3B DD 10 4E 4F 20 4E 41 )]NO NA

177C0130 4D 45 20 20 20 20 46 41-54 31 32 20 20 20 F1 7D ME FAT12

177C0140 FA 33 C9 8E D1 BC FC 7B-16 07 BD 78 00 C5 76 00 3xv

177C0150 1E 56 16 55 BF 22 05 89-7E 00 89 4E 02 B1 0B FC VU~N

177C0160 F3 A4 06 1F BD 00 7C C6-45 FE 0F 8B 46 18 88 45 |EFE

177C0170 F9 FB 38 66 24 7C 04 CD-13 72 3C 8A 46 10 98 F7 8f$|rltF

177C0180 66 16 03 46 1C 13 56 1E-03 46 0E 13 D1 50 52 89 fFVFPR

177C0190 46 FC 89 56 FE B8 20 00-8B 76 11 F7 E6 8B 5E 0B FV v^

177C01A0 03 C3 48 F7 F3 01 46 FC-11 4E FE 5A 58 BB 00 07 HFNZX

177C01B0 8B FB B1 01 E8 94 00 72-47 38 2D 74 19 B1 0B 56 rG8-tV

177C01C0 8B 76 3E F3 A6 5E 74 4A-4E 74 0B 03 F9 83 C7 15 vgt^tJNt

177C01D0 3B FB 72 E5 EB D7 2B C9-B8 D8 7D 87 46 3E 3C D8 r+Fgtlt

177C01E0 75 99 BE 80 7D AC 98 03-F0 AC 84 C0 74 17 3C FF utlt

177C01F0 74 09 B4 0E BB 07 00 CD-10 EB EE BE 83 7D EB E5 t

177C0200 BE 81 7D EB E0 33 C0 CD-16 5E 1F 8F 04 8F 44 02 3^D

177C0210 CD 19 BE 82 7D 8B 7D 0F-83 FF 02 72 C8 8B C7 48 rH

177C0220 48 8A 4E 0D F7 E1 03 46-FC 13 56 FE BB 00 07 53 HNFVS

177C0230 B1 04 E8 16 00 5B 72 C8-81 3F 4D 5A 75 A7 81 BF [rMZu

177C0240 00 02 42 4A 75 9F EA 00-02 70 00 50 52 51 91 92 BJupPRQ

177C0250 33 D2 F7 76 18 91 F7 76-18 42 87 CA F7 76 1A 8A 3vvBv

177C0260 F2 8A 56 24 8A E8 D0 CC-D0 CC 0A CC B8 01 02 CD V$

177C0270 13 59 5A 58 72 09 40 75-01 42 03 5E 0B E2 CC C3 YZXruB^

177C0280 03 18 01 27 0D 0A 44 69-73 63 6F 20 69 6E 63 6F Disco inco

177C0290 72 72 65 63 74 6F 20 20-20 FF 0D 0A 45 72 72 6F rrecto Erro

177C02A0 72 20 45 2F 53 20 20 20-20 20 FF 0D 0A 43 61 6D r ES Cam

177C02B0 62 69 65 20 65 6C 20 64-69 73 63 6F 20 79 20 70 bie el disco y p

177C02C0 72 65 73 69 6F 6E 65 20-75 6E 61 20 74 65 63 6C resione una tecl

177C02D0 61 20 20 20 20 0D 0A 00-49 4F 20 20 20 20 20 20 a IO

177C02E0 53 59 53 4D 53 44 4F 53-20 20 20 53 59 53 80 01 SYSMSDOS SYS

177C02F0 00 57 49 4E 42 4F 4F 54-20 53 59 53 00 00 55 AA WINBOOT SYSU

-

-Q

FIN [1] En las primeras versiones de MS-DOS era un modesto programita DEBUGCOM de apenas 16 KB La versioacuten que acompantildea a Windows98 es ya un ejecutable en formato EXE de 21 KB [2] En realidad DEBUG es una utilidad de enorme potencia que requeririacutea todo un libro para ella sola Puede encontrarse una amplia descripcioacuten de esta herramienta en el libro de Paul Somerson PC Magazine DOS Powers Tools [3] Desgraciadamente no hay una convencioacuten estaacutendar sobre la colocacioacuten de los datos en la BIOS de forma que cada fabricante sigue sus propias reglas y es imposible por tanto utilizarla para cualquier tipo de identificacioacuten del sistema [4] En palabras del mencionado Paul Somerson Desgraciadamente debido a que DEBUG es un programa tan increiacuteblemente potente tambieacuten es increiacuteblemente peligroso Hay un dicho que afirma que El software no puede destruir el hardware Desgraciadamente esto no es cierto Ademaacutes de enviar mecanismos sensibles de la unidad de disco a tierra de nadie es posible hacer saltar monitores o transformadores Repito si sigue al pie de la letra las instrucciones y hace caso a todos los avisos todo iraacute bien [5] Recuerde que la imagen de un ejecutable exe cargado en memoria es distinta de su imagen en disco Solo en los ejecutables com la imagen en disco es una imagen exacta de su disposicioacuten en memoria [6] Es evidente que un pequentildeo error de nuacutemero en este paraacutemetro puede acarrear consecuencias nefastas Por ejemplo si cree que estaacute jugando con el disquete e inadvertidamente se dirige al disco duro (relea la nota [4])

Page 3: El Comando DEBUG

El registro AX

Todos los registros ocupan dos bytes de longitud (16 bits) Los registros de propoacutesito 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 ldquoLOWrdquo o ldquoBajardquo del registro AX mientras que AH es la parte ldquoHIGHrdquo o parte ldquoAltardquo 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 especiacuteficos

AX Acumulador BX Registro base CX Registro contador DX Registro de datos DS Registro del segmento de datos ES Registro del segmento extra SS Registro del segmento de pila CS Registro del segmento de coacutedigo BP Registro de apuntadores base SI Registro iacutendice fuente DI Registro iacutendice destino SP Registro del apuntador de la pila IP Registro de apuntador de siguiente instruccioacuten F Registro de banderas

Registro AX Este registro es el acumulador principal implicado en gran parte de las operaciones de aritmeacuteticas y de ES Registro BX Recibe el nombre de registro base ya que es el uacutenico registro de propoacutesito general que se usa como un iacutendice en el direccionamiento indexado Se suele utilizar para caacutelculos aritmeacuteticos Registro CX Es conocido como registro contador ya que puede contener un valor para controlar el nuacutemero de veces que se repite una cierta operacioacuten Registro DX Se conoce como registro de datos Algunas operaciones de ES requieren su uso y las operaciones de multiplicacioacuten y divisioacuten con cifras grandes suponen que el DX y el AX trabajando juntos Registro CS Registro Segmento de Coacutedigo Establece el aacuterea de memoria doacutende estaacute el programa durante su ejecucioacuten 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 colocacioacuten 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 estaacute siendo procesada en la pila Registro BP Facilita la referencia a los paraacutemetros de las rutinas los cuales son datos y direcciones transmitidos viacutea la pila Registro SI Registro iacutendice fuente requerido en algunas operaciones con cadenas de caracteres Este registro estaacute asociado con el registro DS Registro DI Registro iacutendice destino requerido tambieacuten en determinadas operaciones con cadenas de caracteres Estaacute 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 direccioacuten de la siguiente instruccioacuten que se ejecutaraacute Estaacute asociado con el registro CS en el sentido de que IP indica el desplazamiento de la siguiente instruccioacuten a ejecutar dentro del segmento de coacutedigo determinado por CS Registro de banderas FLAGS o registro de estado (FL) Es un registro de 16 bits pero soacutelo se utilizan nueve de ellos Sirven para indicar el estado actual de la maacutequina y el resultado del procesamiento La mayor parte de las instrucciones de

comparacioacuten y aritmeacuteticas modifican este registro Algunas instrucciones pueden realizar pruebas sobre este registro para determinar la accioacuten siguiente

OF (O) Bit de Overflow o desbordamiento Indica desbordamiento de un bit de orden alto (maacutes a la izquierda) despueacutes de una operacioacuten aritmeacutetica DF (D) Bit de Direccioacuten Designa la direccioacuten creciente (0) o decreciente (1) en operaciones con cadenas de caracteres IF (I) Bit de Interrupcioacuten Indica que una interrupcioacuten externa como la entrada desde el teclado sea procesada o ignorada TF (T) Bit de Trap o Desviacuteo Procesa o ignora la interrupcioacuten interna de trace (procesamiento paso a paso) SF (S) Bit de Signo Indica el valor del bit maacutes significativo del registro despueacutes de una operacioacuten aritmeacutetica o de desplazamiento ZF (Z) Bit Cero Se pone a 1 si una operacioacuten produce 0 como resultado AF (A) Bit de Carry Auxiliar Se pone a 1 si una operacioacuten aritmeacutetica produce un acarreo del bit 3 al 4 Se usa para aritmeacutetica especializada (ajuste BCD) PF (P) Bit de Paridad Se activa si el resultado de una operacioacuten tiene paridad par CF (C) Bit de Acarreo Contiene el acarreo de una operacioacuten aritmeacutetica 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 Cgt DEBUG [Enter] Una vez que el programa estaacute en ejecucioacuten el indicador (prompt) es un guioacuten - indicando que el Shell espera recibir oacuterdenes Para salir basta pulsar una Q Como muchos programas de su geacutenero sus comandos empiezan por una letra o combinacioacuten de ellas (pueden usarse indistintamente mayuacutesculas o minuacutesculas) y ciertos paraacutemetros opcionales (no es imprescindible separar la letra de opcioacuten de los paraacutemetros opcionales que siguen) La opcioacuten maacutes sencilla es la interrogacioacuten () cuyo resultado es una lista resumida de las opciones disponibles

Ensamblar A [direccioacuten] Comparar C direccioacuten de intervalo Volcar D [intervalo] Escribir E direccioacuten [lista de valores] Llenar F lista de intervalos Ir G [=direccioacuten] [direcciones] Hex H valor1 valor2 Entrada I puerto Cargar L [direccioacuten] [unidad] [primer_sector] [nuacutemero] Mover M direccioacuten de intervalo Nombre N [nombre_ruta] [lista_argumentos] Salida O byte de puerto Proceder P [=direccioacuten] [nuacutemero] Salir Q Registro R [registro] Buscar S lista de intervalos Seguimiento T [=direccioacuten] [valor] Desensamblar U [intervalo] Escribir W [direccioacuten] [unidad] [primer_sector] [nuacutemero] Asignar memoria expandida XA [paacuteginas] Desasignar memoria expandida XD [identificador] Asignar paacuteginas de memoria expandida XM [Lpaacutegina] [Ppaacutegina] [identificador] Mostrar estado de la memoria expandida XS

En particular obseacutervese 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 EJEMPLOCOM entonces carga a EJEMPLOCOM en memoria a partir de la direccioacuten 0100h

Comandos del DEBUG D DUMP D ltdireccioacuten1gt ltdireccioacuten2gt Muestra el contenido de una zona de memoria en hexadecimal y en ASCII Sin paraacutemetros muestra los primeros 128 bytes a partir de la posicioacuten a la que se llegoacute en el uacuteltimo d Si se le da un rango mostraraacute ese rango Ambas direcciones son opcionales La 1ra es la direccioacuten de inicio de despliegue la 2da es la direccioacuten de fin Ejemplo

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

E EDIT E ltdireccioacutengtltlistagt Permite editar byte por byte una zona de memoria Muestra -en hexadecimal- el byte de esa posicioacuten 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 siacute se ha hecho Para terminar la edicioacuten se pulsa INTRO Los cambios pueden ser especificados en la liacutenea de comandos en cualquier combinacioacuten de nuacutemeros hexadecimales o caracteres ASCII los caracteres ASCII deben estar entre comillas simples o dobles Por ejemplo E 100 Benjamin Iglesiasrsquo Establece el patroacuten 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 ltlistagt se entra en un modo especial en el que DEBUG despliega los valores de ltdireccioacutengt 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 ltregistrogt Sin paraacutemetros muestra el contenido de los registros de la CPU asiacute como la proacutexima instruccioacuten a ejecutarR [REGISTRO] muestra el contenido del registro especificado y cambia

el prompt de - a invitando a que se cambie su valor Pulsando Enter sin maacutes lo deja como estaba Ejemplo R ltregistrogt Donde ltregistrogt 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 sinoacutenimos A ASSEMBLE A ltdireccioacutengt Sin paraacutemetros ensambla las instrucciones que se introduzcan guardaacutendolas en la direccioacuten siguiente a la que se llegoacute en el uacuteltimo a Cuando se utiliza este comando se le puede dar como paraacutemetro la direccioacuten donde se desea que se inicie el ensamblado si se omite el paraacutemetro el ensamblado se iniciaraacute en la localizacioacuten especificada por CSIP usualmente 0100H que es la localizacioacuten donde deben iniciar los programas con extensioacuten COM y seraacute la localizacioacuten que utilizaremos debido a que DEBUG solo puede crear este tipo especiacutefico de programas La sintaxis es A ltdireccioacutengt Praacutecticamente cualquier mnemoteacutecnico es soportado por DEBUG incluyendo los especificadores de override de segmento (CS DS ES SS) Una excepcioacuten 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 instruccioacuten MOV que como veremos maacutes adelante sirve para copiar datos de la memoria a los registros y viceversa ademaacutes de copiar datos entre registros que es justo lo que vamos a usar en el ejemplo -a 20480106 mov axbx 20480108 mov bxcx 2048010A ltRETgt -u 106 108 20480106 89D8 MOV AXBX 20480108 89CB MOV BXCX Como veremos maacutes adelante la instruccioacuten U sirve para hacer volcados de memoria pero no viendo el contenido de la misma sino interpretaacutendola como instrucciones en lenguaje ensamblador Ejemplo 2 -r cs CS 2048 2050 -a 200 20500200 mov axbx 20500202 ltRETgt -u 200 200 20500200 89D8 MOV AXBX

F FILL F ltbloquegt ltvalor de rellenogt Este comando llena un bloque de memoria con un valor especiacutefico o una serie de valores La sintaxis es F ltbloquegt ltvalor de rellenogt ltbloquegt es la direccioacuten de inicio y final o si se preceden con L la direccioacuten de inicio y la longitud del bloque ltvalor de rellenogt es(son) el(los) valor(es) con los que debe de llenarse el bloque Si ltvalor de rellenogt 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 liacuteneas llena (con 0rsquos) el bloque DS00FF F DS0000 DS00FF 0 DS0000 LFF 0 Ejemplo -f 100 105 66 -d 100 105 20480100 66 66 66 66 66 66 ffffff Q QUIT Q Salir de DEBUG y volver al DOS P PROCEED P lt=direccioacutengtltnuacutemerogt Similar al comando T pero al encontrarse un CALL o INT lo ejecuta de golpe sin entrar en su interior (ojo iexclesto uacuteltimo falla al tracear sobre memoria ROM) Trace puede ser incoacutemodo si no se quiere depurar el coacutedigo de las rutinas de interrupcioacuten o si ya se sabe el coacutedigo que hay en las subrutinas y tan soacutelo interesa seguir avanzando sin entrar en ellas En estos casos se usa p por lo que si ejecutamos una interrupcioacuten de MS-DOS no sabriacuteamos 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 20480107 3D5000 CMP AX0050 -a 100 20480100 mov ax0200 20480103 mov dl61 20480105 int 21 20480107 -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 20480103 B261 MOV DL61 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 20480105 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 20480107 3D5000 CMP AX0050 T TRACE T lt=direccioacutengt ltvalorgt Ejecuta una instruccioacuten del programa (a partir de CSIP) mostrando a continuacioacuten el estado de los registros y la siguiente instruccioacuten Ejecutar T10 equivaldriacutea a ejecutar 16 veces el comando T Si la instruccioacuten es CALL o INT se ejecutaraacute como tal introducieacutendose 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 20480100 3D0000 CMP AX0000 -r bx BX 0000 2 -a 100 20480100 mov axbx 20480102 -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 20480102 00AC01D8 ADD [SI+D801]CH DSD801=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 20480100 3D0000 CMP AX0000 -a 100 20480100 mov axbx 20480102 mov cxbx 20480104 -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 20480102 89D9 MOV CXBX 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 20480104 01D8 ADD AXBX

N NAME N ltnombre_archivogt Se asigna un nombre al programa que estaacute siendo creado o modificado Se puede indicar la trayectoria de directorios L LOAD L ltbuffergt ltnumdiscogt ltsectorinigt ltnumsectorgt ltbuffergt es la direccioacuten en donde se carga la informacioacuten ltnumdiscogt es el nuacutemero (opcional) del disco de donde se leeraacute la informacioacuten (0=A 1=B 2=C etc) ltsectorinigt es el sector de disco absoluto (en hexadecimal) a leer ltnumsectorgt es la cantidad de sectores a leer No se pueden leer maacutes de 80H (128) sectores Si no se suministra la combinacioacuten ltnumdiscogt ltsectorinigt ltnumsectorgt DEBUG presume que se desea leer un archivo En este caso ltbuffergt es opcional Debe usarse el comando N (ver maacutes adelante) para especificar el archivo a leer Eacuteste se carga en CS0100 Ejemplo Se va a leer el sector 0 del disco A y se vuelca a partir de la direccioacuten DS100 como se puede observar el disco contiene mucha informacioacuten ( ESTO NO QUIERE DECIR QUE TENGA QUE SALIR LO MISMO EN SU VOLCADO )

l 100 0 0 1 -d 100 300

W WRITE W ltdireccioacutengt Graba el contenido de una zona de memoria a disco Si no se indica la direccioacuten se graba desde CS100h hasta CS100h+nuacutemero_bytes el nuacutemero de bytes se indica en BXCX (no es una direccioacuten segmentada sino un valor de 32 bits) Si se trata de un EXE no se permitiraacute grabarlo (para modificarlos hay que renombrarles para cambiarles la extensioacuten aunque de esta manera no seraacuten montados al cargarlos) La sintaxis es W ltbuffergt ltnumdiscogt ltsectorinigt ltnumsectorgt ltbuffergt es la direccioacuten de donde se carga la informacioacuten ltnumdiscogt es el nuacutemero (opcional) del disco en donde se escribiraacute la informacioacuten (0=A 1=B 2=C etc) ltsectorinigt es el sector de disco absoluto (en hexadecimal) en donde empieza la escritura ltnumsectorgt es la cantidad de sectores a leer No se pueden escribir maacutes de 80H (128) sectores Si no se suministra la combinacioacuten ltnumdiscogt ltsectorinigt ltnumsectorgt DEBUG presume que el inicio de archivo es CS100 En este caso ltbuffergt es opcional Debe usarse el comando N (ver arriba) para especificar el archivo a escribir Antes de escribir BXCX debe ajustarse al nuacutemero de bytes que desean grabarse W no puede escribir a archivos con la extensioacuten EXE o HEX [5] Ejemplo

N ltnomarchivogt BXCX lt--- 2000 W

S SEARCH S ltrangogt ltlistagt Busca una cadena de bytes por la memoria Para buscar la cadena PEPE terminada por cero en un aacuterea de 512 bytes desde DS100 se hariacutea S 100 L 200 PEPE0 (por defecto se busca en DS) No se encontrariacutea sin embargo pepe (en minuacutesculas) C COMPARE C ltrangogt ltdireccioacutengt Compara dos zonas de memoria mostrando las diferencias Por ejemplo para comparar 5 bytes de DS100 y DS200 se hace C 100 L 5 200 M MOVE M ltrangogt ltdireccioacutengt Maacutes que mover copia una zona de memoria en otra de manera inteligente (controlando los posibles solapamientos de los bloques) I INPUT I ltpuertogt Visualiza la lectura del puerto de ES indicado

O OUTPUT O ltpuertogt ltvalorgt Enviacutea un valor a un puerto de ES H HEX H ltvalor1gt ltvalor2gt Muestra la suma y resta de valor1 y valor2 ambos operandos de un maacuteximo de 16 bits (si hay desbordamiento se trunca el resultado que tampoco excede los 16 bits) Resultado ltresultado_1gt Es la suma ( ltvalor1gt + ltvalor2gt) ltresultado_2gt es la resta (ltvalor1gt - ltvalor2gt ) Ejemplo -h 0003 0002 0005 0001 -h 0000 0001 0001 FFFF como se observa el resultado de la segunda operacioacuten es FFFF que es el equivalente en complemento a 2 de -1 G GO G =ltiniciogt ltquiebre1gt ltquiebre2gt ltquiebre10gt Este comando ejecuta el coacutedigo en memoria Si se estaacute depurando un programa permite ejecutar el coacutedigo cargado en memoria Tambieacuten permite establecer puntos de quiebre (breakpoints) que son direcciones en las que se detiene la ejecucioacuten del programa La sintaxis es G =ltiniciogt ltquiebre1gt ltquiebre2gt ltquiebre10gt ltiniciogt es la direccioacuten de inicio de ejecucioacuten ltquiebre1gt hasta ltquiebre10gt son direcciones opcionales de paro del programa Si no se especifica ltiniciogt Go inicia con la direccioacuten contenida en CSIP Para lograr los quiebres DEBUG reemplaza el coacutedigo en las direcciones de quiebre por el valor hexadecimal CC que es el coacutedigo de interrupcioacuten Si DEBUG llega a CC todos los puntos de quiebre son restituidos los registros se despliegan (como con el comando R [veacutease adelante]) y se para la ejecucioacuten U UNASSEMBLE U ltrangogt Este comando desensambla el contenido de la memoria a partir de la posicioacuten actual Registros y Banderas del DEBUG La mayoriacutea de los comandos de DEBUG ejecutan una accioacuten y vuelven al indicador del shell pero si es un comando largo como puede ser mostrar un trozo grande de coacutedigo puede detenerse pulsando CTRL-Pausa o interrumpirse con CTRL-C para volver al shell Por ejemplo al teclear lo siguiente

- r [Enter]

-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 17A70100 E8CD0F CALL 10D0 - Se desplegaran todos los contenidos de los registros internos del microprocesador una forma alternativa de mostrarlos es usar el comando r utilizando como paraacutemetro el nombre del registro cuyo valor se quiera visualizar Por ejemplo

- r bx Esta instruccioacuten desplegaraacute uacutenicamente el contenido del registro BX y cambia el indicador del DEBUG de - a Estando asiacute el prompt es posible cambiar el valor del registro que se visualizoacute tecleando el nuevo valor y a continuacioacuten [Enter] o se puede dejar el valor anterior presionando [Enter] sin teclear ninguacuten valor Es posible cambiar el valor del registro de banderas asiacute como utilizarlo como estructura de control en nuestros programas como se veraacute maacutes adelante Cada bit del registro tiene un nombre y significado especial la lista dada a continuacioacuten describe el valor de cada bit tanto apagado como prendido y su relacioacuten con las operaciones del microprocesador

Overflow (O) NV = no hay desbordamiento OV = si lo hay Direction (D) UP = hacia adelante DN = hacia atraacutes Interrupts (I) DI = desactivadas EI = activadas Sign (S) PL = positivo NG = negativo Zero (Z) NZ = no es cero ZR = s lo es Auxiliary Carry (A) NA = no hay acarreo auxiliar

AC = hay acarreo auxiliar Parity (P) PO = paridad non PE = paridad par Carry (C) NC = no hay acarreo CY = Si lo hay

La estructura del ensamblador En el lenguaje ensamblador las liacuteneas de coacutedigo constan de dos partes la primera es el nombre de la instruccioacuten que se va a ejecutar y la segunda son los paraacutemetros del comando u operandos Por ejemplo

add ahbh Aquiacute add es el comando a ejecutar (en este caso una adicioacuten) y tanto ah como bh son los paraacutemetros El nombre de las instrucciones en este lenguaje estaacute formado por dos tres o cuatro letras a estas instrucciones tambieacuten se les llama nombres mnemoacutenicos o coacutedigos de operacioacuten ya que representan alguna funcioacuten que habraacute de realizar el microprocesador Existen algunos comandos que no requieren paraacutemetros para su operacioacuten asiacute como otros que requieren solo un paraacutemetro Algunas veces se utilizaraacuten las instrucciones como sigue

add al[170] Los corchetes en el segundo paraacutemetro nos indican que vamos a trabajar con el contenido de la posicioacuten de memoria nuacutemero 170 y no con el valor 170 a esto se le conoce como direccionamiento directo Primer programa en ensamblador con el DEBUG Vamos a crear un programa que sirva para ilustrar lo que hemos estado viendo lo que haremos seraacute una suma de dos valores que introduciremos directamente en el programa El primer paso es iniciar el DEBUG este paso consiste uacutenicamente en teclear DEBUG [Enter] en el prompt del sistema operativo Para ensamblar un programa en el DEBUG se utiliza el comando a (assemble) cuando se utiliza este comando se le puede dar como paraacutemetro la direccioacuten donde se desea que se inicie el ensamblado Si se omite el paraacutemetro el ensamblado se iniciaraacute en la localidad especificada por CSIP usualmente 0100H que es la localidad donde deben iniciar los programas con extensioacuten COM y seraacute la localidad que utilizaremos debido a que DEBUG solo puede crear este tipo especiacutefico de programas

Aunque en este momento no es necesario darle un paraacutemetro al comando a es recomendable hacerlo para evitar problemas una vez que se haga uso de los registros CSIP por lo tanto tecleamos

- a 100 [Enter] Al hacer esto apareceraacute en la pantalla algo como 0C1B0100 y el cursor se posiciona a la derecha de estos nuacutemeros noacutetese que los primeros cuatro diacutegitos (en sistema hexadecimal) pueden ser diferentes pero los uacuteltimos cuatro deben ser 0100 ya que es la direccioacuten que indicamos como inicio Ahora podemos introducir las instrucciones

0C1B0100 mov ax0002 coloca el valor 0002 en el registro ax 0C1B0103 mov bx0004 coloca el valor 0004 en el registro bx 0C1B0106 add axbx le adiciona al contenido de ax el contenido de bx 0C1B0108 int 20 provoca la terminacioacuten del programa 0C1B010A

No es necesario escribir los comentarios que van despueacutes del Una vez escrito el uacuteltimo comando int 20 se le da [Enter] sin escribir nada maacutes para volver al prompt del DEBUG La uacuteltima liacutenea escrita no es propiamente una instruccioacuten de ensamblador es una llamada a una interrupcioacuten del sistema operativo estas interrupciones seraacuten tratadas maacutes a fondo en un capiacutetulo posterior por el momento solo es necesario saber que nos ahorran un gran nuacutemero de liacuteneas y son muy uacutetiles para accesar a funciones del sistema operativo Para ejecutar el programa que escribimos se utiliza el comando g al utilizarlo veremos que aparece un mensaje que dice Program terminated normally Naturalmente con un mensaje como eacuteste no podemos estar seguros que el programa haya hecho la suma pero existe una forma sencilla de verificarlo utilizando el comando r del DEBUG podemos ver los contenidos de todos los registros del microprocesador simplemente teclee

- r [Enter] Apareceraacute en pantalla cada registro con su respectivo valor actual -R AX=0006 BX=0004 CX=0000 DX=0000 SP=FFFE BP=0000 SI=0000 DI=0000 DS=0C1B ES=0C1B SS=0C1B CS=0C1B IP=010A NV UP EI PL NZ NA PO NC 17A70100 E8CD0F CALL 10D0 - Existe la posibilidad de que los registros contengan valores diferentes pero AX y BX deben ser los mismos ya que son los que acabamos de modificar Otra forma de ver los valores mientras se ejecuta el programa es utilizando como paraacutemetro para g la direccioacuten donde queremos que termine la ejecucioacuten y muestre los valores de los registros en este caso seraacute g108 esta instruccioacuten ejecuta el programa se detiene en la direccioacuten 108 y muestra los contenidos de los registros Tambieacuten se puede llevar un seguimiento de lo que pasa en los registros utilizando el comando t (trace) la funcioacuten de este comando es ejecutar liacutenea por liacutenea lo que se ensambloacute mostrando cada vez los contenidos de los registros Para salir del DEBUG se utiliza el comando q (quit)

Guardar y cargar los programas No seriacutea praacutectico tener que escribir todo un programa cada vez que se necesite para evitar eso es posible guardar un programa en el disco con la enorme ventaja de que ya ensamblado no seraacute necesario correr de nuevo DEBUG para ejecutarlo ya que cuando el DEBUG guardo nuestro programa en el disco eacuteste se guardo en binario (archivo con la extensioacuten com) Los pasos a seguir para guardar un programa ya almacenado en la memoria son

Obtener la longitud del programa restando la direccioacuten final de la direccioacuten inicial naturalmente en sistema hexadecimal

Darle un nombre al programa y una extensioacuten

Poner la longitud del programa en el registro CX

Ordenar a DEBUG que escriba el programa en el disco Utilizando como ejemplo el programa del ejemplo anterior tendremos una idea maacutes clara de coacutemo llevar estos pasos Al terminar de ensamblar el programa se veriacutea asiacute

0C1B0100 mov ax0002 0C1B0103 mov bx0004 0C1B0106 add axbx 0C1B0108 int 20 0C1B010A

Para almacenarlo en el disco hacemos lo siguiente - h 10a 100 020a 000a - n pruebacom - r cx CX 0000 000a -w Writing 000A bytes

Para obtener la longitud de un programa se utiliza el comando h el cual nos muestra la suma y resta de dos nuacutemeros en hexadecimal Para obtener la longitud del programa le proporcionamos como paraacutemetros el valor de la direccioacuten final de nuestro programa (10A) y el valor de la direccioacuten inicial (0100) El primer resultado que nos muestra el comando es la suma de los paraacutemetros y el segundo es la resta El comando n nos permite poner un nombre al programa El comando r cx nos permite cambiar el contenido del registro CX al valor que obtuvimos del tamantildeo del archivo con h en este caso 000a ya que nos interesa el resultado de la resta de la direccioacuten inicial a la direccioacuten final

Por uacuteltimo el comando w escribe nuestro programa en el disco indicaacutendonos cuantos bytes escribioacute

NOTA Si se trabaja en una ventana de DOS de Windows Vista o 7 es probable que al momento de guardar su programa el DEBUG escriba mas coacutedigo que el sentildealado por el registro CX por consiguiente seraacute necesario limpiar el registro BX esto es ponerlo a ceros y despueacutes utilizar el comando w Por ejemplo _r bx BX 000E 0000 w

Para cargar un archivo ya guardado son necesarios dos pasos

Proporcionar el nombre del archivo que se cargaraacute a memoria

Cargarlo utilizando el comando l (load) Para obtener el resultado correcto de los siguientes pasos es necesario que previamente se haya creado el programa anterior Dentro del DEBUG escribimos lo siguiente

- n pruebacom - l - u 100 109 0C3D0100 B80200 MOV AX0002 0C3D0103 BB0400 MOV BX0004 0C3D0106 01D8 ADD AXBX 0C3D0108 CD20 INT 20

El uacuteltimo comando u se utiliza para verificar que el programa se cargoacute en memoria lo que hace es desensamblar el coacutedigo y mostrarlo ya desensamblado Los paraacutemetros le indican a DEBUG desde donde y hasta donde desensamblar DEBUG siempre carga los programas en memoria en la direccioacuten 100H a menos que se le indique alguna otra Un programa que realiza un conteo en pantalla Con el DEBUG es posible escribir un programa que realice un conteo en pantalla por razones de comprensioacuten nuestro programa solo realizara un conteo de 9 a 0 (conteo descendente) 0B3B0100 B90A00 MOV CX000A CX=10 en decimal 0B3B0103 88CA MOV DLCL 0B3B0105 80C22F ADD DL2F sumamos 02Fh a DL 0B3B0108 B402 MOV AH02 funcioacuten 02 de INT 21 para imprimir un caracter 0B3B010A CD21 INT 21

0B3B010C E2F5 LOOP 0103 CX=0 Si no salta a 0103 0B3B010E CD20 INT 20 termina el programa En la liacutenea 0103 se puede observar que el valor del registro CX en su parte baja (en CL) se almacena en el registro DL Si se omitiera la liacutenea 0105 entonces cuando se ejecutara la liacutenea 010A solo se imprimiriacutea en pantalla el coacutedigo ASCII del valor que contenga DL (el coacutedigo ASCII de 0Ah que es 10 en decimal es un caraacutecter especial no imprimible) Para conseguir el ldquoefectordquo de que el programa realiza el conteo en decimal se hace un corrimiento de 02F (47 en decimal) Por ejemplo cuando se ejecuta la liacutenea 0105 DL tendriacutea el valor de 39h=57d (02Fh+0Ah=39h=57d) y el coacutedigo ASCII de 57d es el caraacutecter ldquo9rdquo El sentencia LOOP decrementa CX en 1 si CX es diferente a 0 salta a la liacutenea 0103 El proceso se repite y el programa imprime en pantalla 9876543210 Seriacutea interesante que el programa anterior fuera modificado para que la numeracioacuten se imprimiera de la siguiente manera 9 8 7 6 5 4 3 2 1 0

NOTA Como se dijo anteriormente cuando el DEBUG almacena un programa en el disco este archivo se graba en binario esto es en ejecutable Por lo tanto no es necesario cargar el DEBUG para volver a ejecutar nuestro programa sino que se hace de manera directa desde DOS El problema surge cuando al ejecutar nuestro programa el resultado no se puede observar porque el DOS borra la pantalla despueacutes de terminar de ejecutar el programa Para evitar el borrado automaacutetico seraacute necesario agregarle a nuestro programa antes de la INT 20h una instruccioacuten para la lectura de un caraacutecter desde el teclado Para tal efecto utilizaremos la funcioacuten 08 de la INT 21h (un buen truco para que el programa haga una pausa) asiacute el programa esperara hasta que el usuario presiona una tecla permitiendo observar el resultado Ejemplo mov ah08 Int 21 Int 20

Condiciones ciclos y bifurcaciones Estas estructuras o formas de control le dan a la maacutequina un cierto grado de decisioacuten basado en la informacioacuten que recibe La forma maacutes sencilla de comprender este tema es por medio de ejemplos Vamos a crear tres programas que hagan lo mismo desplegar un nuacutemero determinado de veces una cadena de caracteres en la pantalla

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV CX000F veces que se desplegara la cadena 0C1B0128 MOV DX0102 copia cadena al registro DX 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F LOOP 012D si CXgt0 salta a 012D 0C1B0131 INT 20 termina el programa

Por medio del comando e es posible introducir una cadena de caracteres en una determinada localidad de memoria dada como paraacutemetro la cadena se introduce entre comillas le sigue un espacio luego el valor hexadecimal del retorno de carro un espacio el valor de liacutenea nueva y por uacuteltimo el siacutembolo $ que el ensamblador interpreta como final de la cadena La interrupcioacuten 21 utiliza el valor almacenado en el registro AH para ejecutar una determinada funcioacuten en este caso mostrar la cadena en pantalla la cadena que muestra es la que estaacute almacenada en el registro DX La instruccioacuten LOOP decrementa automaacuteticamente el registro CX en uno y si no ha llegado el valor de este registro a cero salta a la posicioacuten de memoria indicada como paraacutemetro lo cual crea un ciclo que se repite el nuacutemero de veces especificado por el valor de CX La interrupcioacuten 20 termina la ejecucioacuten del programa Otra forma de realizar la misma funcioacuten pero sin utilizar el comando LOOP es la siguiente

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV BX000F veces que se desplegara la cadena 0C1B0128 MOV DX0102 copia cadena al registro DX 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F DEC BX decrementa en 1 a BX 0C1B0130 JNZ 012D si BX es diferente a 0 salta a 012D 0C1B0132 INT 20 termina el programa

En este caso se utiliza el registro BX como contador para el programa y por medio de la instruccioacuten DEC se disminuye su valor en 1 La instruccioacuten JNZ verifica si el valor de BX es diferente a 0 esto con base en la bandera NZ en caso afirmativo salta hacia la direccioacuten 012D En caso contrario continuacutea la ejecucioacuten normal del programa y por lo tanto se termina Una uacuteltima variante del programa es utilizando de nuevo a CX como contador pero en lugar de utilizar LOOP utilizaremos decrementos a CX y comparacioacuten de CX a 0

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV DX0102 copia cadena al registro DX 0C1B0128 MOV CX000F veces que se desplegara la cadena 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F DEC CX decrementa en 1 a CX 0C1B0130 JCXZ 0134 si CX es igual a 0 salta a 0134 0C1B0132 JMP 012D salta a la direccioacuten 012D 0C1B0134 INT 20 termina el programa

En este ejemplo se usoacute la instruccioacuten JCXZ para controlar la condicioacuten de salto el significado de tal funcioacuten es salta si CX=0 El tipo de control a utilizar dependeraacute de las necesidades de programacioacuten en determinado momento

Manipulacioacuten de Posiciones de Memoria Con el DEBUG es posible almacenar y recuperar datos numeacutericos en memoria por medio de un programa a traveacutes de los registros del microprocesador Por ejemplo el siguiente programa almacena previamente dos valores numeacutericos en la posicioacuten 0300h y 0400h respectivamente despueacutes el programa los recupera realiza la operacioacuten de suma con esos valores y el resultado lo almacena en la posicioacuten 0500h -a 100 0B1C0100 mov ax0002 ax=2 0B1C0103 mov [0300]ax almacenamos 2 en la direccioacuten 0300h 0B1C0106 mov ax0004 ax=4 0B1C0109 mov [0400]ax almacenamos 4 en la direccioacuten 0400h 0B1C010C mov ax[0300] recuperamos el dato1 en AX 0B1C010F mov bx[0400] recuperamos el dato2 en BX 0B1C0113 add axbx hacemos la operacioacuten de suma en AX 0B1C0115 mov [0500]ax almacenamos el 6 en la direccioacuten 0500h 0B1C0118 int 21 0B1C011A - Un nuacutemero entre corchetes [numero_hex] indica una posicioacuten de memoria y su manejo se hace a traveacutes de registros ya que no es posible almacenar valores numeacutericos de manera directa Ejecutamos el programa -g 118 AX=0006 BX=0004 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=0B1C ES=0B1C SS=0B1C CS=0B1C IP=0118 NV UP EI PL NZ NA PE NC 0B1C0118 CD21 INT 21 - Para ver si el resultado se almaceno en la direccioacuten correcta hacemos

Como se puede observar en la direccioacuten 0B1C0500 se encuentra el 06 y en 0B1C0501 se encuentra el 00 que es el resultado de la operacioacuten 2+4 Perohellip Porque aparece el 06 y despueacutes el 00 pareceriacutea que el resultado fue de 0600 pero no es asiacute lo que sucedes que los datos se almacenan en memoria de la siguiente manera

Como se hizo la operacioacuten AX=AX+BX entonces el resultado es de 16 bits (dos bytes) AX=6 entonces AX=0000 0000 0000 0110 (16 bits) por lo tanto los 8 bits de menor peso de AX son 0000 0110 y deben almacenarse en la direccioacuten 0500 y en la direccioacuten 0501 se almacena 0000 0000

0 0 0 0 0 1 1 0 0500

0 0 0 0 0 0 0 0 0501

x x x x x x x x 0502

x x x x x x x x 0503

x x x x x x x x 0504

x x x x x x x x 0505

Interrupciones Definicioacuten de interrupcioacuten

Una interrupcioacuten es una instruccioacuten que detiene la ejecucioacuten de un programa para permitir el uso del microprocesador en un proceso prioritario Una vez concluido este uacuteltimo proceso se devuelve el control a la aplicacioacuten anterior

Por ejemplo cuando estamos trabajando con un procesador de palabras y en ese momento llega un aviso de uno de los puertos de comunicaciones se detiene temporalmente la aplicacioacuten que estaacutebamos utilizando para permitir el uso del microprocesador al manejo de la informacioacuten que estaacute llegando en ese momento Una vez terminada la transferencia de informacioacuten se reanudan las funciones normales del procesador de palabras Las interrupciones ocurren muy seguido sencillamente la interrupcioacuten que actualiza la hora del diacutea ocurre aproximadamente 18 veces por segundo Para lograr administrar todas estas interrupciones la computadora cuenta con un espacio de memoria llamado memoria baja donde se almacenan las direcciones de cierta localidad de memoria donde se encuentran un juego de instrucciones que el microprocesador ejecutaraacute para despueacutes regresar a la aplicacioacuten que estaba en proceso En los programas anteriores hicimos uso de la interrupcioacuten nuacutemero 20H para terminar la ejecucioacuten de nuestros programas y en otros ejemplos utilizamos otra interrupcioacuten para mostrar informacioacuten en pantalla (INT 21h) Utilizando DEBUG tecleamos

- a100 2C1B0100 JMP 011D 2C1B0102 [ENTER] - E 102 Hola como estas 0D 0A $ - A011D 2C1B011D MOV DX0102 2C1B0120 MOV AH09 2C1B0122 INT 21 2C1B0123 INT 20

Orden

creciente

de la

memoria

En este programa la interrupcioacuten 21h manda al monitor la cadena localizada en la direccioacuten a la que apunta el registro DX El valor que se le da a AH determina cual de las opciones de la interrupcioacuten 21h seraacute utilizada ya que esta interrupcioacuten cuenta con varias opciones El manejo directo de interrupciones es una de las partes maacutes fuertes del lenguaje ensamblador ya que con ellas es posible controlar eficientemente todos los dispositivos internos y externos de una computadora gracias al completo control que se tiene sobre operaciones de entrada y salida Maacutes del DEBUG Una caracteriacutestica poco conocida es que DEBUG puede aceptar entradas desde un archivo Script que puede ser un simple archivo de texto ASCII en el que cada comando esteacute separado del anterior por un INTRO Despueacutes del uacuteltimo que debe ser una Q para salir de DEBUG es conveniente dejar una liacutenea en blanco pulsando INTRO dos veces Las liacuteneas pueden contener comentarios Cualquier cosa a partir del caracter punto y coma () hasta el final de la liacutenea seraacute ignorado esto es un comentario D aquiacute se mostraraacute algo Suponiendo que tengamos un archivo Script de nombre Ordenestxt puede ser utilizado como entrada para DEBUG mediante un comando de redireccioacuten en la siguiente forma DEBUG lt ordenestxt Tambieacuten puede conseguirse que el programa redireccione la salida hacia un archivo que puede ser inspeccionado maacutes 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 podriacutea obtenerse un archivo Resulttxt con el siguiente comando DEBUG lt ordenestxt gt Resulttxt Errores Cuando DEBUG no sabe interpretar un comando muestra un mensaje de error y un indicador ^ debajo del sitio del comando donde estaacute el error Entradas y Salidas DEBUG asume que los datos numeacutericos proporcionados son hexadecimales y cuando se trate de direcciones de memoria deben introducirse en forma segmentada A su vez los resultados son mostrados tambieacuten 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

Cada fila muestra 16 posiciones de memoria a partir de la posicioacuten sentildealada por las columnas de la izquierda que las muestran como segmentodesplazamiento El bloque central muestra el contenido hexadecimal de cada byte mientras que el bloque derecho contiene la representacioacuten ASCII Por ejemplo la 3ra fila muestra el contenido de las posiciones 0B770120 a 0B77012F (ambas inclusive) Sus tres uacuteltimos bytes contienen respectivamente los caracteres r 9 y 2 que corresponden a las cantidades 72h 39h y 32h del bloque central Que como sabemos equivalen a los decimales 114 57 y 50 que son precisamente los valores ASCII de los caracteres ldquorrdquo ldquo9rdquo y ldquo2rdquo anteriormente mencionados

Nota Por razoacuten de que eacuteste tipo de salida pueda ser listado a impresora el bloque derecho no contiene en realidad la representacioacuten ASCII de todos los caracteres (algunos ni siquiera tienen una representacioacuten imprimible) En realidad solo se muestran los caracteres imprimibles del primer bloque (US-ASCII) El resto estaacute 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 caraacutecter imprimible Esto no significa que dichas posiciones representen efectivamente tales valores para la aplicacioacuten que las utiliza Por ejemplo puede que en realidad las dos posiciones de memoria mencionadas (dos octetos o bytes) en vez de los caracteres ldquo5rdquo y ldquoardquo representen una palabra de 16 bits en formato Little Endian que a su vez representan una cantidad entera (un nuacutemero) Comandos Aunque su descripcioacuten completa llenariacutea todo un capiacutetulo a continuacioacuten comentamos algunas de las opciones maacutes interesantes relativas a inspeccioacuten del coacutedigo y de contenidos de memoria La opcioacuten D (Dump) permite obtener un volcado del contenido de la memoria (de DEBUG) La sintaxis acepta dos formas D [direccioacuten-inicial] [L posiciones-desde-direccioacuten-inicial ] D [direccioacuten-inicial][direccioacuten-final] Naturalmente para que exista algo en el buacutefer de memoria (al principio quizaacutes solo contiene basura) es preciso indicarle que lea algo Este algo puede ser un rango de direcciones de memoria RAM una direccioacuten absoluta de disco (sector) un archivo o el contenido de los registros del procesador Para empezar puede indicaacutersele que cargue un archivo xxxxyz que tenemos en el directorio actual o en el PATH cuyo contenido queremos ver Cgt DEBUG xxxxyz -D aquiacute se obtendriacutea una salida anaacuteloga a la comentada

Hemos visto un ejemplo al tratar de los servicios de interrupciones del PC aquiacute mostraremos otro Sabemos que el punto de inicio de la BIOS es la direccioacuten F000FFF0 y que desde eacutesta posicioacuten hasta el final de la memoria DOS hay 16 bytes Puede obtenerse un volcado de estas posiciones con el siguiente comando -D F000FFF0 La salida en un equipo puede ser F000FFF0 CD 19 E0 00 F0 30 36 2F-33 30 2F 39 37 00 FC 38 0630978 En este caso el comando solo muestra una liacutenea porque ha alcanzado el final de la memoria Puede verse que la fecha de la BIOS del sistema ocupa las uacuteltimas posiciones Si se ordena el volcado de una direccioacuten suficientemente alejada del final de la memoria sin indicar ninguacuten nuacutemero de posiciones por defecto se toma el valor 128 (8 filas de 16 posiciones) Si desea una cantidad distinta hay que antildeadir una L (Long) y el nuacutemero de posiciones hasta un maacuteximo de 64 KB (FFFF) Todos los nuacutemeros deben ser expresados en hexadecimal Por consiguiente los dos comandos que siguen son equivalentes (recuerde que 80 es el equivalente hexadecimal de 128) D FE000000 D FE000000 L 80 He aquiacute el resultado

Sabemos que esta zona corresponde al aacuterea de la BIOS del Sistema Otra opcioacuten muy interesante nos permite buscar determinados contenidos a traveacutes de la memoria utilizando el prefijo S (Search) Existen dos sintaxis alternativas S direccioacuten-de-inicio L longitud-a-explorar contenido-a-buscar S direccioacuten-de-inicio direccioacuten-final L contenido-a-buscar El contenido debe ser proporcionado en hexadecimal (tal como apareceriacutea en la columna central del ejemplo anterior) o entre comillas si es un texto ASCII Por ejemplo en un equipo IBM deseo ver algunas caracteriacutesticas de la BIOS Seacute que estos datos se alojan a partir de la posicioacuten F0000000 hasta el final de la memoria Es decir una longitud de 64 Kbytes (FFFF) a partir de la posicioacuten de inicio y que seguramente los datos buscados estaraacuten cerca de la identificacioacuten de la propia BIOS (la cadena IBM) Por lo que se utiliza la siguiente sintaxis [3] -s f0000000 L ffff IBM

y se obtiene la siguiente salida F000E00E F000E111 con las direcciones donde se ha encontrado la ocurrencia buscada A continuacioacuten puedo explorar las proximidades de cada posicioacuten Por ejemplo para la primera -D f000e000

Si lo que se busca estaacute en un archivo primero hay que cargarlo Lo que se puede hacer de dos formas en la propia invocacioacuten de DEBUG o mediante los comandos N y L Por ejemplo si queremos inspeccionar el contenido del archivo morecom podemos utilizar dos formas CWINDOWSgtDEBUG cwindowscommandmorecom CWINDOWSgtDEBUG - N cwindowscommandmorecom - L La sintaxis para el prefijo N es N [path-name]nombre-de-archivo En ambos casos el contenido del archivo seraacute cargado en memoria y podraacute ser utilizado Atencioacuten despueacutes de la orden L (Load) DEBUG le avisaraacute si no encuentra el archivo pero seguiraacute su funcionamiento En tal caso simplemente piensa que N sentildeala el nombre de un nuevo archivo que crearaacute con el contenido de la memoria -de DEBUG- cuando posteriormente seleccione la opcioacuten escribir W (Write)[4]

Nota Como ya habraacute deducido DEBUG permite leer un archivo realizar modificaciones en eacutel (con la opcioacuten E) y escribir el archivo modificado bajo otro nombre con NW

A continuacioacuten podemos comprobar el tamantildeo del archivo cargado Para ello usamos la opcioacuten 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 17A70100 E8CD0F CALL 10D0 -

Aquiacute nos interesa especialmente el contenido del registro CX cuyo valor 2917h (1519d) en este caso sentildeala el tamantildeo del archivo en bytes Tambieacuten podiacuteamos haber utilizado directamente el comando R CX que nos proporciona el valor de dicho registro -R CX CX 2917 -

Nota A continuacioacuten del valor correspondiente DEBUG muestra dos puntos () sentildealando que puede cambiar el valor del registro introduciendo un nuevo nuacutemero Pulse INTRO para dejar las cosas como estaacuten y volver al prompt (-) de DEBUG

Al llegar a este punto es importante sentildealar que a excepcioacuten de los archivos exe DEBUG carga los archivos a partir de la direccioacuten 100h (256d) de su memoria De forma que el primer octeto del archivo se carga en la direccioacuten 100 el segundo en 101 etc En nuestro caso el archivo se extenderaacute desde la posicioacuten 100h hasta 2A17h (100h + 2917h) A continuacioacuten para buscar la cadena Microsoft en el archivo utilizamos cualquiera de los siguientes comandos - S 100 L 2917 Microsoft - S 100 2a17 Microsoft El primer comando sentildeala el punto de inicio y el tamantildeo de la zona a buscar el segundo utiliza los puntos inicial y final de la exploracioacuten Con ambos se obtiene la misma respuesta 17A71083 17A710B2

Truco Debido a la forma especial en que se cargan los ejecutables exe si quiere inspeccionar la forma nativa de uno de estos archivos (como es su imagen en el disco) debe hacer una copia del archivo renombrarlo con cualquier otra terminacioacuten (o sin ella) y cargar esta copia En caso contrario DEBUG se prepararaacute para funcionar como un verdadero depurador de tiempo de ejecucioacuten (run-time) para lo que cargaraacute el archivo y lo acomodaraacute en memoria de forma que pueda ejecutarse [5]

Como ejercicio compruebe las distintas longitudes y aspecto (especialmente al principio) de un mismo archivo exe cargaacutendolo con DEBUG de las dos formas (busque en su sistema un exe lo maacutes pequentildeo posible) Ademaacutes de la capacidad de leer archivos antes mencionada quizaacutes una de las opciones maacutes interesantes (y peligrosas) de DEBUG es la posibilidad de leerescribir el contenido de disco a bajo nivel mediante los prefijos L (Load) y W (Write) Se utiliza la siguiente sintaxis L [Direccioacuten] [Unidad] [Primer_sector] [Nuacutemero] W [Direccioacuten] [Unidad] [Primer_sector] [Nuacutemero] El significado de los paraacutemetros es como sigue

Direccioacuten Posicioacuten de la memoria de DEBUG a partir de la cual se instalaraacuten los datos leiacutedos del disco o se tomaraacuten para el proceso de escritura (aquiacute se utiliza generalmente el valor 100h)

Unidad Valor numeacuterico que indica la loacutegica a utilizar 0 = A 1 = B 2 = C 3 = D etc [6]

Primer sector A partir del que se realizaraacute la lectura o se comenzaraacute a escribir

Nuacutemero Nuacutemero de sectores que se desea cargarescribir Como DEBUG no puede leerescribir maacutes de 64 Kbytes (2

16 = 65536) y los sectores de disco son de 512 bytes

el maacuteximo nuacutemero de sectores es 128 (80h) Asiacute pues el valor maacuteximo aquiacute es 80 Ejemplo Para obtener el contenido del sector de arranque (Master boot sector MBR) de un disquete en A utilizaremos el comando CWINDOWSgtDEBUG - L 100 0 0 1 - D 100 L 200 Como el resultado no cabe en una pantalla ingeniaremos un procedimiento para conservarlo en un archivo (maacutes adelante nos serviraacute para otro propoacutesito) Para ello creamos un archivo scripttxt con el siguiente contenido (dos INTRO despueacutes de la Q) L 100 0 0 1 D 100 L 200 Q A continuacioacuten invocamos DEBUG con el comando CWINDOWSgtDEBUG lt Dbuzonscripttxt gt Dbuzonresultadtxt Despueacutes de un breve parpadeo del disco y del disquete vuelve el prompt del DOS La operacioacuten ha concluido y en el directorio correspondiente de la unidad D tenemos el archivo resultadtxt con el volcado del sector de arranque del disquete ademaacutes de los ecos de los comandos introducidos (los hemos mantenido para orientacioacuten del lector) Otra forma de poder visualizar el contenido del Sector de Arranque del disco es utilizando el DEBUG Por ejemplo dentro del DEBUG tecleamos lo siguiente -L 100 0 0 1

-D 100 L 200

177C0100 EB 3E 90 2B 79 73 57 29-49 48 43 00 02 01 01 00 gt+ysW)IHC

177C0110 02 E0 00 40 0B F0 09 00-12 00 02 00 00 00 00 00

177C0120 00 00 00 00 00 00 29 5D-3B DD 10 4E 4F 20 4E 41 )]NO NA

177C0130 4D 45 20 20 20 20 46 41-54 31 32 20 20 20 F1 7D ME FAT12

177C0140 FA 33 C9 8E D1 BC FC 7B-16 07 BD 78 00 C5 76 00 3xv

177C0150 1E 56 16 55 BF 22 05 89-7E 00 89 4E 02 B1 0B FC VU~N

177C0160 F3 A4 06 1F BD 00 7C C6-45 FE 0F 8B 46 18 88 45 |EFE

177C0170 F9 FB 38 66 24 7C 04 CD-13 72 3C 8A 46 10 98 F7 8f$|rltF

177C0180 66 16 03 46 1C 13 56 1E-03 46 0E 13 D1 50 52 89 fFVFPR

177C0190 46 FC 89 56 FE B8 20 00-8B 76 11 F7 E6 8B 5E 0B FV v^

177C01A0 03 C3 48 F7 F3 01 46 FC-11 4E FE 5A 58 BB 00 07 HFNZX

177C01B0 8B FB B1 01 E8 94 00 72-47 38 2D 74 19 B1 0B 56 rG8-tV

177C01C0 8B 76 3E F3 A6 5E 74 4A-4E 74 0B 03 F9 83 C7 15 vgt^tJNt

177C01D0 3B FB 72 E5 EB D7 2B C9-B8 D8 7D 87 46 3E 3C D8 r+Fgtlt

177C01E0 75 99 BE 80 7D AC 98 03-F0 AC 84 C0 74 17 3C FF utlt

177C01F0 74 09 B4 0E BB 07 00 CD-10 EB EE BE 83 7D EB E5 t

177C0200 BE 81 7D EB E0 33 C0 CD-16 5E 1F 8F 04 8F 44 02 3^D

177C0210 CD 19 BE 82 7D 8B 7D 0F-83 FF 02 72 C8 8B C7 48 rH

177C0220 48 8A 4E 0D F7 E1 03 46-FC 13 56 FE BB 00 07 53 HNFVS

177C0230 B1 04 E8 16 00 5B 72 C8-81 3F 4D 5A 75 A7 81 BF [rMZu

177C0240 00 02 42 4A 75 9F EA 00-02 70 00 50 52 51 91 92 BJupPRQ

177C0250 33 D2 F7 76 18 91 F7 76-18 42 87 CA F7 76 1A 8A 3vvBv

177C0260 F2 8A 56 24 8A E8 D0 CC-D0 CC 0A CC B8 01 02 CD V$

177C0270 13 59 5A 58 72 09 40 75-01 42 03 5E 0B E2 CC C3 YZXruB^

177C0280 03 18 01 27 0D 0A 44 69-73 63 6F 20 69 6E 63 6F Disco inco

177C0290 72 72 65 63 74 6F 20 20-20 FF 0D 0A 45 72 72 6F rrecto Erro

177C02A0 72 20 45 2F 53 20 20 20-20 20 FF 0D 0A 43 61 6D r ES Cam

177C02B0 62 69 65 20 65 6C 20 64-69 73 63 6F 20 79 20 70 bie el disco y p

177C02C0 72 65 73 69 6F 6E 65 20-75 6E 61 20 74 65 63 6C resione una tecl

177C02D0 61 20 20 20 20 0D 0A 00-49 4F 20 20 20 20 20 20 a IO

177C02E0 53 59 53 4D 53 44 4F 53-20 20 20 53 59 53 80 01 SYSMSDOS SYS

177C02F0 00 57 49 4E 42 4F 4F 54-20 53 59 53 00 00 55 AA WINBOOT SYSU

-

-Q

FIN [1] En las primeras versiones de MS-DOS era un modesto programita DEBUGCOM de apenas 16 KB La versioacuten que acompantildea a Windows98 es ya un ejecutable en formato EXE de 21 KB [2] En realidad DEBUG es una utilidad de enorme potencia que requeririacutea todo un libro para ella sola Puede encontrarse una amplia descripcioacuten de esta herramienta en el libro de Paul Somerson PC Magazine DOS Powers Tools [3] Desgraciadamente no hay una convencioacuten estaacutendar sobre la colocacioacuten de los datos en la BIOS de forma que cada fabricante sigue sus propias reglas y es imposible por tanto utilizarla para cualquier tipo de identificacioacuten del sistema [4] En palabras del mencionado Paul Somerson Desgraciadamente debido a que DEBUG es un programa tan increiacuteblemente potente tambieacuten es increiacuteblemente peligroso Hay un dicho que afirma que El software no puede destruir el hardware Desgraciadamente esto no es cierto Ademaacutes de enviar mecanismos sensibles de la unidad de disco a tierra de nadie es posible hacer saltar monitores o transformadores Repito si sigue al pie de la letra las instrucciones y hace caso a todos los avisos todo iraacute bien [5] Recuerde que la imagen de un ejecutable exe cargado en memoria es distinta de su imagen en disco Solo en los ejecutables com la imagen en disco es una imagen exacta de su disposicioacuten en memoria [6] Es evidente que un pequentildeo error de nuacutemero en este paraacutemetro puede acarrear consecuencias nefastas Por ejemplo si cree que estaacute jugando con el disquete e inadvertidamente se dirige al disco duro (relea la nota [4])

Page 4: El Comando DEBUG

Registro AX Este registro es el acumulador principal implicado en gran parte de las operaciones de aritmeacuteticas y de ES Registro BX Recibe el nombre de registro base ya que es el uacutenico registro de propoacutesito general que se usa como un iacutendice en el direccionamiento indexado Se suele utilizar para caacutelculos aritmeacuteticos Registro CX Es conocido como registro contador ya que puede contener un valor para controlar el nuacutemero de veces que se repite una cierta operacioacuten Registro DX Se conoce como registro de datos Algunas operaciones de ES requieren su uso y las operaciones de multiplicacioacuten y divisioacuten con cifras grandes suponen que el DX y el AX trabajando juntos Registro CS Registro Segmento de Coacutedigo Establece el aacuterea de memoria doacutende estaacute el programa durante su ejecucioacuten 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 colocacioacuten 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 estaacute siendo procesada en la pila Registro BP Facilita la referencia a los paraacutemetros de las rutinas los cuales son datos y direcciones transmitidos viacutea la pila Registro SI Registro iacutendice fuente requerido en algunas operaciones con cadenas de caracteres Este registro estaacute asociado con el registro DS Registro DI Registro iacutendice destino requerido tambieacuten en determinadas operaciones con cadenas de caracteres Estaacute 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 direccioacuten de la siguiente instruccioacuten que se ejecutaraacute Estaacute asociado con el registro CS en el sentido de que IP indica el desplazamiento de la siguiente instruccioacuten a ejecutar dentro del segmento de coacutedigo determinado por CS Registro de banderas FLAGS o registro de estado (FL) Es un registro de 16 bits pero soacutelo se utilizan nueve de ellos Sirven para indicar el estado actual de la maacutequina y el resultado del procesamiento La mayor parte de las instrucciones de

comparacioacuten y aritmeacuteticas modifican este registro Algunas instrucciones pueden realizar pruebas sobre este registro para determinar la accioacuten siguiente

OF (O) Bit de Overflow o desbordamiento Indica desbordamiento de un bit de orden alto (maacutes a la izquierda) despueacutes de una operacioacuten aritmeacutetica DF (D) Bit de Direccioacuten Designa la direccioacuten creciente (0) o decreciente (1) en operaciones con cadenas de caracteres IF (I) Bit de Interrupcioacuten Indica que una interrupcioacuten externa como la entrada desde el teclado sea procesada o ignorada TF (T) Bit de Trap o Desviacuteo Procesa o ignora la interrupcioacuten interna de trace (procesamiento paso a paso) SF (S) Bit de Signo Indica el valor del bit maacutes significativo del registro despueacutes de una operacioacuten aritmeacutetica o de desplazamiento ZF (Z) Bit Cero Se pone a 1 si una operacioacuten produce 0 como resultado AF (A) Bit de Carry Auxiliar Se pone a 1 si una operacioacuten aritmeacutetica produce un acarreo del bit 3 al 4 Se usa para aritmeacutetica especializada (ajuste BCD) PF (P) Bit de Paridad Se activa si el resultado de una operacioacuten tiene paridad par CF (C) Bit de Acarreo Contiene el acarreo de una operacioacuten aritmeacutetica 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 Cgt DEBUG [Enter] Una vez que el programa estaacute en ejecucioacuten el indicador (prompt) es un guioacuten - indicando que el Shell espera recibir oacuterdenes Para salir basta pulsar una Q Como muchos programas de su geacutenero sus comandos empiezan por una letra o combinacioacuten de ellas (pueden usarse indistintamente mayuacutesculas o minuacutesculas) y ciertos paraacutemetros opcionales (no es imprescindible separar la letra de opcioacuten de los paraacutemetros opcionales que siguen) La opcioacuten maacutes sencilla es la interrogacioacuten () cuyo resultado es una lista resumida de las opciones disponibles

Ensamblar A [direccioacuten] Comparar C direccioacuten de intervalo Volcar D [intervalo] Escribir E direccioacuten [lista de valores] Llenar F lista de intervalos Ir G [=direccioacuten] [direcciones] Hex H valor1 valor2 Entrada I puerto Cargar L [direccioacuten] [unidad] [primer_sector] [nuacutemero] Mover M direccioacuten de intervalo Nombre N [nombre_ruta] [lista_argumentos] Salida O byte de puerto Proceder P [=direccioacuten] [nuacutemero] Salir Q Registro R [registro] Buscar S lista de intervalos Seguimiento T [=direccioacuten] [valor] Desensamblar U [intervalo] Escribir W [direccioacuten] [unidad] [primer_sector] [nuacutemero] Asignar memoria expandida XA [paacuteginas] Desasignar memoria expandida XD [identificador] Asignar paacuteginas de memoria expandida XM [Lpaacutegina] [Ppaacutegina] [identificador] Mostrar estado de la memoria expandida XS

En particular obseacutervese 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 EJEMPLOCOM entonces carga a EJEMPLOCOM en memoria a partir de la direccioacuten 0100h

Comandos del DEBUG D DUMP D ltdireccioacuten1gt ltdireccioacuten2gt Muestra el contenido de una zona de memoria en hexadecimal y en ASCII Sin paraacutemetros muestra los primeros 128 bytes a partir de la posicioacuten a la que se llegoacute en el uacuteltimo d Si se le da un rango mostraraacute ese rango Ambas direcciones son opcionales La 1ra es la direccioacuten de inicio de despliegue la 2da es la direccioacuten de fin Ejemplo

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

E EDIT E ltdireccioacutengtltlistagt Permite editar byte por byte una zona de memoria Muestra -en hexadecimal- el byte de esa posicioacuten 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 siacute se ha hecho Para terminar la edicioacuten se pulsa INTRO Los cambios pueden ser especificados en la liacutenea de comandos en cualquier combinacioacuten de nuacutemeros hexadecimales o caracteres ASCII los caracteres ASCII deben estar entre comillas simples o dobles Por ejemplo E 100 Benjamin Iglesiasrsquo Establece el patroacuten 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 ltlistagt se entra en un modo especial en el que DEBUG despliega los valores de ltdireccioacutengt 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 ltregistrogt Sin paraacutemetros muestra el contenido de los registros de la CPU asiacute como la proacutexima instruccioacuten a ejecutarR [REGISTRO] muestra el contenido del registro especificado y cambia

el prompt de - a invitando a que se cambie su valor Pulsando Enter sin maacutes lo deja como estaba Ejemplo R ltregistrogt Donde ltregistrogt 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 sinoacutenimos A ASSEMBLE A ltdireccioacutengt Sin paraacutemetros ensambla las instrucciones que se introduzcan guardaacutendolas en la direccioacuten siguiente a la que se llegoacute en el uacuteltimo a Cuando se utiliza este comando se le puede dar como paraacutemetro la direccioacuten donde se desea que se inicie el ensamblado si se omite el paraacutemetro el ensamblado se iniciaraacute en la localizacioacuten especificada por CSIP usualmente 0100H que es la localizacioacuten donde deben iniciar los programas con extensioacuten COM y seraacute la localizacioacuten que utilizaremos debido a que DEBUG solo puede crear este tipo especiacutefico de programas La sintaxis es A ltdireccioacutengt Praacutecticamente cualquier mnemoteacutecnico es soportado por DEBUG incluyendo los especificadores de override de segmento (CS DS ES SS) Una excepcioacuten 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 instruccioacuten MOV que como veremos maacutes adelante sirve para copiar datos de la memoria a los registros y viceversa ademaacutes de copiar datos entre registros que es justo lo que vamos a usar en el ejemplo -a 20480106 mov axbx 20480108 mov bxcx 2048010A ltRETgt -u 106 108 20480106 89D8 MOV AXBX 20480108 89CB MOV BXCX Como veremos maacutes adelante la instruccioacuten U sirve para hacer volcados de memoria pero no viendo el contenido de la misma sino interpretaacutendola como instrucciones en lenguaje ensamblador Ejemplo 2 -r cs CS 2048 2050 -a 200 20500200 mov axbx 20500202 ltRETgt -u 200 200 20500200 89D8 MOV AXBX

F FILL F ltbloquegt ltvalor de rellenogt Este comando llena un bloque de memoria con un valor especiacutefico o una serie de valores La sintaxis es F ltbloquegt ltvalor de rellenogt ltbloquegt es la direccioacuten de inicio y final o si se preceden con L la direccioacuten de inicio y la longitud del bloque ltvalor de rellenogt es(son) el(los) valor(es) con los que debe de llenarse el bloque Si ltvalor de rellenogt 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 liacuteneas llena (con 0rsquos) el bloque DS00FF F DS0000 DS00FF 0 DS0000 LFF 0 Ejemplo -f 100 105 66 -d 100 105 20480100 66 66 66 66 66 66 ffffff Q QUIT Q Salir de DEBUG y volver al DOS P PROCEED P lt=direccioacutengtltnuacutemerogt Similar al comando T pero al encontrarse un CALL o INT lo ejecuta de golpe sin entrar en su interior (ojo iexclesto uacuteltimo falla al tracear sobre memoria ROM) Trace puede ser incoacutemodo si no se quiere depurar el coacutedigo de las rutinas de interrupcioacuten o si ya se sabe el coacutedigo que hay en las subrutinas y tan soacutelo interesa seguir avanzando sin entrar en ellas En estos casos se usa p por lo que si ejecutamos una interrupcioacuten de MS-DOS no sabriacuteamos 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 20480107 3D5000 CMP AX0050 -a 100 20480100 mov ax0200 20480103 mov dl61 20480105 int 21 20480107 -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 20480103 B261 MOV DL61 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 20480105 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 20480107 3D5000 CMP AX0050 T TRACE T lt=direccioacutengt ltvalorgt Ejecuta una instruccioacuten del programa (a partir de CSIP) mostrando a continuacioacuten el estado de los registros y la siguiente instruccioacuten Ejecutar T10 equivaldriacutea a ejecutar 16 veces el comando T Si la instruccioacuten es CALL o INT se ejecutaraacute como tal introducieacutendose 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 20480100 3D0000 CMP AX0000 -r bx BX 0000 2 -a 100 20480100 mov axbx 20480102 -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 20480102 00AC01D8 ADD [SI+D801]CH DSD801=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 20480100 3D0000 CMP AX0000 -a 100 20480100 mov axbx 20480102 mov cxbx 20480104 -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 20480102 89D9 MOV CXBX 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 20480104 01D8 ADD AXBX

N NAME N ltnombre_archivogt Se asigna un nombre al programa que estaacute siendo creado o modificado Se puede indicar la trayectoria de directorios L LOAD L ltbuffergt ltnumdiscogt ltsectorinigt ltnumsectorgt ltbuffergt es la direccioacuten en donde se carga la informacioacuten ltnumdiscogt es el nuacutemero (opcional) del disco de donde se leeraacute la informacioacuten (0=A 1=B 2=C etc) ltsectorinigt es el sector de disco absoluto (en hexadecimal) a leer ltnumsectorgt es la cantidad de sectores a leer No se pueden leer maacutes de 80H (128) sectores Si no se suministra la combinacioacuten ltnumdiscogt ltsectorinigt ltnumsectorgt DEBUG presume que se desea leer un archivo En este caso ltbuffergt es opcional Debe usarse el comando N (ver maacutes adelante) para especificar el archivo a leer Eacuteste se carga en CS0100 Ejemplo Se va a leer el sector 0 del disco A y se vuelca a partir de la direccioacuten DS100 como se puede observar el disco contiene mucha informacioacuten ( ESTO NO QUIERE DECIR QUE TENGA QUE SALIR LO MISMO EN SU VOLCADO )

l 100 0 0 1 -d 100 300

W WRITE W ltdireccioacutengt Graba el contenido de una zona de memoria a disco Si no se indica la direccioacuten se graba desde CS100h hasta CS100h+nuacutemero_bytes el nuacutemero de bytes se indica en BXCX (no es una direccioacuten segmentada sino un valor de 32 bits) Si se trata de un EXE no se permitiraacute grabarlo (para modificarlos hay que renombrarles para cambiarles la extensioacuten aunque de esta manera no seraacuten montados al cargarlos) La sintaxis es W ltbuffergt ltnumdiscogt ltsectorinigt ltnumsectorgt ltbuffergt es la direccioacuten de donde se carga la informacioacuten ltnumdiscogt es el nuacutemero (opcional) del disco en donde se escribiraacute la informacioacuten (0=A 1=B 2=C etc) ltsectorinigt es el sector de disco absoluto (en hexadecimal) en donde empieza la escritura ltnumsectorgt es la cantidad de sectores a leer No se pueden escribir maacutes de 80H (128) sectores Si no se suministra la combinacioacuten ltnumdiscogt ltsectorinigt ltnumsectorgt DEBUG presume que el inicio de archivo es CS100 En este caso ltbuffergt es opcional Debe usarse el comando N (ver arriba) para especificar el archivo a escribir Antes de escribir BXCX debe ajustarse al nuacutemero de bytes que desean grabarse W no puede escribir a archivos con la extensioacuten EXE o HEX [5] Ejemplo

N ltnomarchivogt BXCX lt--- 2000 W

S SEARCH S ltrangogt ltlistagt Busca una cadena de bytes por la memoria Para buscar la cadena PEPE terminada por cero en un aacuterea de 512 bytes desde DS100 se hariacutea S 100 L 200 PEPE0 (por defecto se busca en DS) No se encontrariacutea sin embargo pepe (en minuacutesculas) C COMPARE C ltrangogt ltdireccioacutengt Compara dos zonas de memoria mostrando las diferencias Por ejemplo para comparar 5 bytes de DS100 y DS200 se hace C 100 L 5 200 M MOVE M ltrangogt ltdireccioacutengt Maacutes que mover copia una zona de memoria en otra de manera inteligente (controlando los posibles solapamientos de los bloques) I INPUT I ltpuertogt Visualiza la lectura del puerto de ES indicado

O OUTPUT O ltpuertogt ltvalorgt Enviacutea un valor a un puerto de ES H HEX H ltvalor1gt ltvalor2gt Muestra la suma y resta de valor1 y valor2 ambos operandos de un maacuteximo de 16 bits (si hay desbordamiento se trunca el resultado que tampoco excede los 16 bits) Resultado ltresultado_1gt Es la suma ( ltvalor1gt + ltvalor2gt) ltresultado_2gt es la resta (ltvalor1gt - ltvalor2gt ) Ejemplo -h 0003 0002 0005 0001 -h 0000 0001 0001 FFFF como se observa el resultado de la segunda operacioacuten es FFFF que es el equivalente en complemento a 2 de -1 G GO G =ltiniciogt ltquiebre1gt ltquiebre2gt ltquiebre10gt Este comando ejecuta el coacutedigo en memoria Si se estaacute depurando un programa permite ejecutar el coacutedigo cargado en memoria Tambieacuten permite establecer puntos de quiebre (breakpoints) que son direcciones en las que se detiene la ejecucioacuten del programa La sintaxis es G =ltiniciogt ltquiebre1gt ltquiebre2gt ltquiebre10gt ltiniciogt es la direccioacuten de inicio de ejecucioacuten ltquiebre1gt hasta ltquiebre10gt son direcciones opcionales de paro del programa Si no se especifica ltiniciogt Go inicia con la direccioacuten contenida en CSIP Para lograr los quiebres DEBUG reemplaza el coacutedigo en las direcciones de quiebre por el valor hexadecimal CC que es el coacutedigo de interrupcioacuten Si DEBUG llega a CC todos los puntos de quiebre son restituidos los registros se despliegan (como con el comando R [veacutease adelante]) y se para la ejecucioacuten U UNASSEMBLE U ltrangogt Este comando desensambla el contenido de la memoria a partir de la posicioacuten actual Registros y Banderas del DEBUG La mayoriacutea de los comandos de DEBUG ejecutan una accioacuten y vuelven al indicador del shell pero si es un comando largo como puede ser mostrar un trozo grande de coacutedigo puede detenerse pulsando CTRL-Pausa o interrumpirse con CTRL-C para volver al shell Por ejemplo al teclear lo siguiente

- r [Enter]

-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 17A70100 E8CD0F CALL 10D0 - Se desplegaran todos los contenidos de los registros internos del microprocesador una forma alternativa de mostrarlos es usar el comando r utilizando como paraacutemetro el nombre del registro cuyo valor se quiera visualizar Por ejemplo

- r bx Esta instruccioacuten desplegaraacute uacutenicamente el contenido del registro BX y cambia el indicador del DEBUG de - a Estando asiacute el prompt es posible cambiar el valor del registro que se visualizoacute tecleando el nuevo valor y a continuacioacuten [Enter] o se puede dejar el valor anterior presionando [Enter] sin teclear ninguacuten valor Es posible cambiar el valor del registro de banderas asiacute como utilizarlo como estructura de control en nuestros programas como se veraacute maacutes adelante Cada bit del registro tiene un nombre y significado especial la lista dada a continuacioacuten describe el valor de cada bit tanto apagado como prendido y su relacioacuten con las operaciones del microprocesador

Overflow (O) NV = no hay desbordamiento OV = si lo hay Direction (D) UP = hacia adelante DN = hacia atraacutes Interrupts (I) DI = desactivadas EI = activadas Sign (S) PL = positivo NG = negativo Zero (Z) NZ = no es cero ZR = s lo es Auxiliary Carry (A) NA = no hay acarreo auxiliar

AC = hay acarreo auxiliar Parity (P) PO = paridad non PE = paridad par Carry (C) NC = no hay acarreo CY = Si lo hay

La estructura del ensamblador En el lenguaje ensamblador las liacuteneas de coacutedigo constan de dos partes la primera es el nombre de la instruccioacuten que se va a ejecutar y la segunda son los paraacutemetros del comando u operandos Por ejemplo

add ahbh Aquiacute add es el comando a ejecutar (en este caso una adicioacuten) y tanto ah como bh son los paraacutemetros El nombre de las instrucciones en este lenguaje estaacute formado por dos tres o cuatro letras a estas instrucciones tambieacuten se les llama nombres mnemoacutenicos o coacutedigos de operacioacuten ya que representan alguna funcioacuten que habraacute de realizar el microprocesador Existen algunos comandos que no requieren paraacutemetros para su operacioacuten asiacute como otros que requieren solo un paraacutemetro Algunas veces se utilizaraacuten las instrucciones como sigue

add al[170] Los corchetes en el segundo paraacutemetro nos indican que vamos a trabajar con el contenido de la posicioacuten de memoria nuacutemero 170 y no con el valor 170 a esto se le conoce como direccionamiento directo Primer programa en ensamblador con el DEBUG Vamos a crear un programa que sirva para ilustrar lo que hemos estado viendo lo que haremos seraacute una suma de dos valores que introduciremos directamente en el programa El primer paso es iniciar el DEBUG este paso consiste uacutenicamente en teclear DEBUG [Enter] en el prompt del sistema operativo Para ensamblar un programa en el DEBUG se utiliza el comando a (assemble) cuando se utiliza este comando se le puede dar como paraacutemetro la direccioacuten donde se desea que se inicie el ensamblado Si se omite el paraacutemetro el ensamblado se iniciaraacute en la localidad especificada por CSIP usualmente 0100H que es la localidad donde deben iniciar los programas con extensioacuten COM y seraacute la localidad que utilizaremos debido a que DEBUG solo puede crear este tipo especiacutefico de programas

Aunque en este momento no es necesario darle un paraacutemetro al comando a es recomendable hacerlo para evitar problemas una vez que se haga uso de los registros CSIP por lo tanto tecleamos

- a 100 [Enter] Al hacer esto apareceraacute en la pantalla algo como 0C1B0100 y el cursor se posiciona a la derecha de estos nuacutemeros noacutetese que los primeros cuatro diacutegitos (en sistema hexadecimal) pueden ser diferentes pero los uacuteltimos cuatro deben ser 0100 ya que es la direccioacuten que indicamos como inicio Ahora podemos introducir las instrucciones

0C1B0100 mov ax0002 coloca el valor 0002 en el registro ax 0C1B0103 mov bx0004 coloca el valor 0004 en el registro bx 0C1B0106 add axbx le adiciona al contenido de ax el contenido de bx 0C1B0108 int 20 provoca la terminacioacuten del programa 0C1B010A

No es necesario escribir los comentarios que van despueacutes del Una vez escrito el uacuteltimo comando int 20 se le da [Enter] sin escribir nada maacutes para volver al prompt del DEBUG La uacuteltima liacutenea escrita no es propiamente una instruccioacuten de ensamblador es una llamada a una interrupcioacuten del sistema operativo estas interrupciones seraacuten tratadas maacutes a fondo en un capiacutetulo posterior por el momento solo es necesario saber que nos ahorran un gran nuacutemero de liacuteneas y son muy uacutetiles para accesar a funciones del sistema operativo Para ejecutar el programa que escribimos se utiliza el comando g al utilizarlo veremos que aparece un mensaje que dice Program terminated normally Naturalmente con un mensaje como eacuteste no podemos estar seguros que el programa haya hecho la suma pero existe una forma sencilla de verificarlo utilizando el comando r del DEBUG podemos ver los contenidos de todos los registros del microprocesador simplemente teclee

- r [Enter] Apareceraacute en pantalla cada registro con su respectivo valor actual -R AX=0006 BX=0004 CX=0000 DX=0000 SP=FFFE BP=0000 SI=0000 DI=0000 DS=0C1B ES=0C1B SS=0C1B CS=0C1B IP=010A NV UP EI PL NZ NA PO NC 17A70100 E8CD0F CALL 10D0 - Existe la posibilidad de que los registros contengan valores diferentes pero AX y BX deben ser los mismos ya que son los que acabamos de modificar Otra forma de ver los valores mientras se ejecuta el programa es utilizando como paraacutemetro para g la direccioacuten donde queremos que termine la ejecucioacuten y muestre los valores de los registros en este caso seraacute g108 esta instruccioacuten ejecuta el programa se detiene en la direccioacuten 108 y muestra los contenidos de los registros Tambieacuten se puede llevar un seguimiento de lo que pasa en los registros utilizando el comando t (trace) la funcioacuten de este comando es ejecutar liacutenea por liacutenea lo que se ensambloacute mostrando cada vez los contenidos de los registros Para salir del DEBUG se utiliza el comando q (quit)

Guardar y cargar los programas No seriacutea praacutectico tener que escribir todo un programa cada vez que se necesite para evitar eso es posible guardar un programa en el disco con la enorme ventaja de que ya ensamblado no seraacute necesario correr de nuevo DEBUG para ejecutarlo ya que cuando el DEBUG guardo nuestro programa en el disco eacuteste se guardo en binario (archivo con la extensioacuten com) Los pasos a seguir para guardar un programa ya almacenado en la memoria son

Obtener la longitud del programa restando la direccioacuten final de la direccioacuten inicial naturalmente en sistema hexadecimal

Darle un nombre al programa y una extensioacuten

Poner la longitud del programa en el registro CX

Ordenar a DEBUG que escriba el programa en el disco Utilizando como ejemplo el programa del ejemplo anterior tendremos una idea maacutes clara de coacutemo llevar estos pasos Al terminar de ensamblar el programa se veriacutea asiacute

0C1B0100 mov ax0002 0C1B0103 mov bx0004 0C1B0106 add axbx 0C1B0108 int 20 0C1B010A

Para almacenarlo en el disco hacemos lo siguiente - h 10a 100 020a 000a - n pruebacom - r cx CX 0000 000a -w Writing 000A bytes

Para obtener la longitud de un programa se utiliza el comando h el cual nos muestra la suma y resta de dos nuacutemeros en hexadecimal Para obtener la longitud del programa le proporcionamos como paraacutemetros el valor de la direccioacuten final de nuestro programa (10A) y el valor de la direccioacuten inicial (0100) El primer resultado que nos muestra el comando es la suma de los paraacutemetros y el segundo es la resta El comando n nos permite poner un nombre al programa El comando r cx nos permite cambiar el contenido del registro CX al valor que obtuvimos del tamantildeo del archivo con h en este caso 000a ya que nos interesa el resultado de la resta de la direccioacuten inicial a la direccioacuten final

Por uacuteltimo el comando w escribe nuestro programa en el disco indicaacutendonos cuantos bytes escribioacute

NOTA Si se trabaja en una ventana de DOS de Windows Vista o 7 es probable que al momento de guardar su programa el DEBUG escriba mas coacutedigo que el sentildealado por el registro CX por consiguiente seraacute necesario limpiar el registro BX esto es ponerlo a ceros y despueacutes utilizar el comando w Por ejemplo _r bx BX 000E 0000 w

Para cargar un archivo ya guardado son necesarios dos pasos

Proporcionar el nombre del archivo que se cargaraacute a memoria

Cargarlo utilizando el comando l (load) Para obtener el resultado correcto de los siguientes pasos es necesario que previamente se haya creado el programa anterior Dentro del DEBUG escribimos lo siguiente

- n pruebacom - l - u 100 109 0C3D0100 B80200 MOV AX0002 0C3D0103 BB0400 MOV BX0004 0C3D0106 01D8 ADD AXBX 0C3D0108 CD20 INT 20

El uacuteltimo comando u se utiliza para verificar que el programa se cargoacute en memoria lo que hace es desensamblar el coacutedigo y mostrarlo ya desensamblado Los paraacutemetros le indican a DEBUG desde donde y hasta donde desensamblar DEBUG siempre carga los programas en memoria en la direccioacuten 100H a menos que se le indique alguna otra Un programa que realiza un conteo en pantalla Con el DEBUG es posible escribir un programa que realice un conteo en pantalla por razones de comprensioacuten nuestro programa solo realizara un conteo de 9 a 0 (conteo descendente) 0B3B0100 B90A00 MOV CX000A CX=10 en decimal 0B3B0103 88CA MOV DLCL 0B3B0105 80C22F ADD DL2F sumamos 02Fh a DL 0B3B0108 B402 MOV AH02 funcioacuten 02 de INT 21 para imprimir un caracter 0B3B010A CD21 INT 21

0B3B010C E2F5 LOOP 0103 CX=0 Si no salta a 0103 0B3B010E CD20 INT 20 termina el programa En la liacutenea 0103 se puede observar que el valor del registro CX en su parte baja (en CL) se almacena en el registro DL Si se omitiera la liacutenea 0105 entonces cuando se ejecutara la liacutenea 010A solo se imprimiriacutea en pantalla el coacutedigo ASCII del valor que contenga DL (el coacutedigo ASCII de 0Ah que es 10 en decimal es un caraacutecter especial no imprimible) Para conseguir el ldquoefectordquo de que el programa realiza el conteo en decimal se hace un corrimiento de 02F (47 en decimal) Por ejemplo cuando se ejecuta la liacutenea 0105 DL tendriacutea el valor de 39h=57d (02Fh+0Ah=39h=57d) y el coacutedigo ASCII de 57d es el caraacutecter ldquo9rdquo El sentencia LOOP decrementa CX en 1 si CX es diferente a 0 salta a la liacutenea 0103 El proceso se repite y el programa imprime en pantalla 9876543210 Seriacutea interesante que el programa anterior fuera modificado para que la numeracioacuten se imprimiera de la siguiente manera 9 8 7 6 5 4 3 2 1 0

NOTA Como se dijo anteriormente cuando el DEBUG almacena un programa en el disco este archivo se graba en binario esto es en ejecutable Por lo tanto no es necesario cargar el DEBUG para volver a ejecutar nuestro programa sino que se hace de manera directa desde DOS El problema surge cuando al ejecutar nuestro programa el resultado no se puede observar porque el DOS borra la pantalla despueacutes de terminar de ejecutar el programa Para evitar el borrado automaacutetico seraacute necesario agregarle a nuestro programa antes de la INT 20h una instruccioacuten para la lectura de un caraacutecter desde el teclado Para tal efecto utilizaremos la funcioacuten 08 de la INT 21h (un buen truco para que el programa haga una pausa) asiacute el programa esperara hasta que el usuario presiona una tecla permitiendo observar el resultado Ejemplo mov ah08 Int 21 Int 20

Condiciones ciclos y bifurcaciones Estas estructuras o formas de control le dan a la maacutequina un cierto grado de decisioacuten basado en la informacioacuten que recibe La forma maacutes sencilla de comprender este tema es por medio de ejemplos Vamos a crear tres programas que hagan lo mismo desplegar un nuacutemero determinado de veces una cadena de caracteres en la pantalla

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV CX000F veces que se desplegara la cadena 0C1B0128 MOV DX0102 copia cadena al registro DX 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F LOOP 012D si CXgt0 salta a 012D 0C1B0131 INT 20 termina el programa

Por medio del comando e es posible introducir una cadena de caracteres en una determinada localidad de memoria dada como paraacutemetro la cadena se introduce entre comillas le sigue un espacio luego el valor hexadecimal del retorno de carro un espacio el valor de liacutenea nueva y por uacuteltimo el siacutembolo $ que el ensamblador interpreta como final de la cadena La interrupcioacuten 21 utiliza el valor almacenado en el registro AH para ejecutar una determinada funcioacuten en este caso mostrar la cadena en pantalla la cadena que muestra es la que estaacute almacenada en el registro DX La instruccioacuten LOOP decrementa automaacuteticamente el registro CX en uno y si no ha llegado el valor de este registro a cero salta a la posicioacuten de memoria indicada como paraacutemetro lo cual crea un ciclo que se repite el nuacutemero de veces especificado por el valor de CX La interrupcioacuten 20 termina la ejecucioacuten del programa Otra forma de realizar la misma funcioacuten pero sin utilizar el comando LOOP es la siguiente

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV BX000F veces que se desplegara la cadena 0C1B0128 MOV DX0102 copia cadena al registro DX 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F DEC BX decrementa en 1 a BX 0C1B0130 JNZ 012D si BX es diferente a 0 salta a 012D 0C1B0132 INT 20 termina el programa

En este caso se utiliza el registro BX como contador para el programa y por medio de la instruccioacuten DEC se disminuye su valor en 1 La instruccioacuten JNZ verifica si el valor de BX es diferente a 0 esto con base en la bandera NZ en caso afirmativo salta hacia la direccioacuten 012D En caso contrario continuacutea la ejecucioacuten normal del programa y por lo tanto se termina Una uacuteltima variante del programa es utilizando de nuevo a CX como contador pero en lugar de utilizar LOOP utilizaremos decrementos a CX y comparacioacuten de CX a 0

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV DX0102 copia cadena al registro DX 0C1B0128 MOV CX000F veces que se desplegara la cadena 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F DEC CX decrementa en 1 a CX 0C1B0130 JCXZ 0134 si CX es igual a 0 salta a 0134 0C1B0132 JMP 012D salta a la direccioacuten 012D 0C1B0134 INT 20 termina el programa

En este ejemplo se usoacute la instruccioacuten JCXZ para controlar la condicioacuten de salto el significado de tal funcioacuten es salta si CX=0 El tipo de control a utilizar dependeraacute de las necesidades de programacioacuten en determinado momento

Manipulacioacuten de Posiciones de Memoria Con el DEBUG es posible almacenar y recuperar datos numeacutericos en memoria por medio de un programa a traveacutes de los registros del microprocesador Por ejemplo el siguiente programa almacena previamente dos valores numeacutericos en la posicioacuten 0300h y 0400h respectivamente despueacutes el programa los recupera realiza la operacioacuten de suma con esos valores y el resultado lo almacena en la posicioacuten 0500h -a 100 0B1C0100 mov ax0002 ax=2 0B1C0103 mov [0300]ax almacenamos 2 en la direccioacuten 0300h 0B1C0106 mov ax0004 ax=4 0B1C0109 mov [0400]ax almacenamos 4 en la direccioacuten 0400h 0B1C010C mov ax[0300] recuperamos el dato1 en AX 0B1C010F mov bx[0400] recuperamos el dato2 en BX 0B1C0113 add axbx hacemos la operacioacuten de suma en AX 0B1C0115 mov [0500]ax almacenamos el 6 en la direccioacuten 0500h 0B1C0118 int 21 0B1C011A - Un nuacutemero entre corchetes [numero_hex] indica una posicioacuten de memoria y su manejo se hace a traveacutes de registros ya que no es posible almacenar valores numeacutericos de manera directa Ejecutamos el programa -g 118 AX=0006 BX=0004 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=0B1C ES=0B1C SS=0B1C CS=0B1C IP=0118 NV UP EI PL NZ NA PE NC 0B1C0118 CD21 INT 21 - Para ver si el resultado se almaceno en la direccioacuten correcta hacemos

Como se puede observar en la direccioacuten 0B1C0500 se encuentra el 06 y en 0B1C0501 se encuentra el 00 que es el resultado de la operacioacuten 2+4 Perohellip Porque aparece el 06 y despueacutes el 00 pareceriacutea que el resultado fue de 0600 pero no es asiacute lo que sucedes que los datos se almacenan en memoria de la siguiente manera

Como se hizo la operacioacuten AX=AX+BX entonces el resultado es de 16 bits (dos bytes) AX=6 entonces AX=0000 0000 0000 0110 (16 bits) por lo tanto los 8 bits de menor peso de AX son 0000 0110 y deben almacenarse en la direccioacuten 0500 y en la direccioacuten 0501 se almacena 0000 0000

0 0 0 0 0 1 1 0 0500

0 0 0 0 0 0 0 0 0501

x x x x x x x x 0502

x x x x x x x x 0503

x x x x x x x x 0504

x x x x x x x x 0505

Interrupciones Definicioacuten de interrupcioacuten

Una interrupcioacuten es una instruccioacuten que detiene la ejecucioacuten de un programa para permitir el uso del microprocesador en un proceso prioritario Una vez concluido este uacuteltimo proceso se devuelve el control a la aplicacioacuten anterior

Por ejemplo cuando estamos trabajando con un procesador de palabras y en ese momento llega un aviso de uno de los puertos de comunicaciones se detiene temporalmente la aplicacioacuten que estaacutebamos utilizando para permitir el uso del microprocesador al manejo de la informacioacuten que estaacute llegando en ese momento Una vez terminada la transferencia de informacioacuten se reanudan las funciones normales del procesador de palabras Las interrupciones ocurren muy seguido sencillamente la interrupcioacuten que actualiza la hora del diacutea ocurre aproximadamente 18 veces por segundo Para lograr administrar todas estas interrupciones la computadora cuenta con un espacio de memoria llamado memoria baja donde se almacenan las direcciones de cierta localidad de memoria donde se encuentran un juego de instrucciones que el microprocesador ejecutaraacute para despueacutes regresar a la aplicacioacuten que estaba en proceso En los programas anteriores hicimos uso de la interrupcioacuten nuacutemero 20H para terminar la ejecucioacuten de nuestros programas y en otros ejemplos utilizamos otra interrupcioacuten para mostrar informacioacuten en pantalla (INT 21h) Utilizando DEBUG tecleamos

- a100 2C1B0100 JMP 011D 2C1B0102 [ENTER] - E 102 Hola como estas 0D 0A $ - A011D 2C1B011D MOV DX0102 2C1B0120 MOV AH09 2C1B0122 INT 21 2C1B0123 INT 20

Orden

creciente

de la

memoria

En este programa la interrupcioacuten 21h manda al monitor la cadena localizada en la direccioacuten a la que apunta el registro DX El valor que se le da a AH determina cual de las opciones de la interrupcioacuten 21h seraacute utilizada ya que esta interrupcioacuten cuenta con varias opciones El manejo directo de interrupciones es una de las partes maacutes fuertes del lenguaje ensamblador ya que con ellas es posible controlar eficientemente todos los dispositivos internos y externos de una computadora gracias al completo control que se tiene sobre operaciones de entrada y salida Maacutes del DEBUG Una caracteriacutestica poco conocida es que DEBUG puede aceptar entradas desde un archivo Script que puede ser un simple archivo de texto ASCII en el que cada comando esteacute separado del anterior por un INTRO Despueacutes del uacuteltimo que debe ser una Q para salir de DEBUG es conveniente dejar una liacutenea en blanco pulsando INTRO dos veces Las liacuteneas pueden contener comentarios Cualquier cosa a partir del caracter punto y coma () hasta el final de la liacutenea seraacute ignorado esto es un comentario D aquiacute se mostraraacute algo Suponiendo que tengamos un archivo Script de nombre Ordenestxt puede ser utilizado como entrada para DEBUG mediante un comando de redireccioacuten en la siguiente forma DEBUG lt ordenestxt Tambieacuten puede conseguirse que el programa redireccione la salida hacia un archivo que puede ser inspeccionado maacutes 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 podriacutea obtenerse un archivo Resulttxt con el siguiente comando DEBUG lt ordenestxt gt Resulttxt Errores Cuando DEBUG no sabe interpretar un comando muestra un mensaje de error y un indicador ^ debajo del sitio del comando donde estaacute el error Entradas y Salidas DEBUG asume que los datos numeacutericos proporcionados son hexadecimales y cuando se trate de direcciones de memoria deben introducirse en forma segmentada A su vez los resultados son mostrados tambieacuten 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

Cada fila muestra 16 posiciones de memoria a partir de la posicioacuten sentildealada por las columnas de la izquierda que las muestran como segmentodesplazamiento El bloque central muestra el contenido hexadecimal de cada byte mientras que el bloque derecho contiene la representacioacuten ASCII Por ejemplo la 3ra fila muestra el contenido de las posiciones 0B770120 a 0B77012F (ambas inclusive) Sus tres uacuteltimos bytes contienen respectivamente los caracteres r 9 y 2 que corresponden a las cantidades 72h 39h y 32h del bloque central Que como sabemos equivalen a los decimales 114 57 y 50 que son precisamente los valores ASCII de los caracteres ldquorrdquo ldquo9rdquo y ldquo2rdquo anteriormente mencionados

Nota Por razoacuten de que eacuteste tipo de salida pueda ser listado a impresora el bloque derecho no contiene en realidad la representacioacuten ASCII de todos los caracteres (algunos ni siquiera tienen una representacioacuten imprimible) En realidad solo se muestran los caracteres imprimibles del primer bloque (US-ASCII) El resto estaacute 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 caraacutecter imprimible Esto no significa que dichas posiciones representen efectivamente tales valores para la aplicacioacuten que las utiliza Por ejemplo puede que en realidad las dos posiciones de memoria mencionadas (dos octetos o bytes) en vez de los caracteres ldquo5rdquo y ldquoardquo representen una palabra de 16 bits en formato Little Endian que a su vez representan una cantidad entera (un nuacutemero) Comandos Aunque su descripcioacuten completa llenariacutea todo un capiacutetulo a continuacioacuten comentamos algunas de las opciones maacutes interesantes relativas a inspeccioacuten del coacutedigo y de contenidos de memoria La opcioacuten D (Dump) permite obtener un volcado del contenido de la memoria (de DEBUG) La sintaxis acepta dos formas D [direccioacuten-inicial] [L posiciones-desde-direccioacuten-inicial ] D [direccioacuten-inicial][direccioacuten-final] Naturalmente para que exista algo en el buacutefer de memoria (al principio quizaacutes solo contiene basura) es preciso indicarle que lea algo Este algo puede ser un rango de direcciones de memoria RAM una direccioacuten absoluta de disco (sector) un archivo o el contenido de los registros del procesador Para empezar puede indicaacutersele que cargue un archivo xxxxyz que tenemos en el directorio actual o en el PATH cuyo contenido queremos ver Cgt DEBUG xxxxyz -D aquiacute se obtendriacutea una salida anaacuteloga a la comentada

Hemos visto un ejemplo al tratar de los servicios de interrupciones del PC aquiacute mostraremos otro Sabemos que el punto de inicio de la BIOS es la direccioacuten F000FFF0 y que desde eacutesta posicioacuten hasta el final de la memoria DOS hay 16 bytes Puede obtenerse un volcado de estas posiciones con el siguiente comando -D F000FFF0 La salida en un equipo puede ser F000FFF0 CD 19 E0 00 F0 30 36 2F-33 30 2F 39 37 00 FC 38 0630978 En este caso el comando solo muestra una liacutenea porque ha alcanzado el final de la memoria Puede verse que la fecha de la BIOS del sistema ocupa las uacuteltimas posiciones Si se ordena el volcado de una direccioacuten suficientemente alejada del final de la memoria sin indicar ninguacuten nuacutemero de posiciones por defecto se toma el valor 128 (8 filas de 16 posiciones) Si desea una cantidad distinta hay que antildeadir una L (Long) y el nuacutemero de posiciones hasta un maacuteximo de 64 KB (FFFF) Todos los nuacutemeros deben ser expresados en hexadecimal Por consiguiente los dos comandos que siguen son equivalentes (recuerde que 80 es el equivalente hexadecimal de 128) D FE000000 D FE000000 L 80 He aquiacute el resultado

Sabemos que esta zona corresponde al aacuterea de la BIOS del Sistema Otra opcioacuten muy interesante nos permite buscar determinados contenidos a traveacutes de la memoria utilizando el prefijo S (Search) Existen dos sintaxis alternativas S direccioacuten-de-inicio L longitud-a-explorar contenido-a-buscar S direccioacuten-de-inicio direccioacuten-final L contenido-a-buscar El contenido debe ser proporcionado en hexadecimal (tal como apareceriacutea en la columna central del ejemplo anterior) o entre comillas si es un texto ASCII Por ejemplo en un equipo IBM deseo ver algunas caracteriacutesticas de la BIOS Seacute que estos datos se alojan a partir de la posicioacuten F0000000 hasta el final de la memoria Es decir una longitud de 64 Kbytes (FFFF) a partir de la posicioacuten de inicio y que seguramente los datos buscados estaraacuten cerca de la identificacioacuten de la propia BIOS (la cadena IBM) Por lo que se utiliza la siguiente sintaxis [3] -s f0000000 L ffff IBM

y se obtiene la siguiente salida F000E00E F000E111 con las direcciones donde se ha encontrado la ocurrencia buscada A continuacioacuten puedo explorar las proximidades de cada posicioacuten Por ejemplo para la primera -D f000e000

Si lo que se busca estaacute en un archivo primero hay que cargarlo Lo que se puede hacer de dos formas en la propia invocacioacuten de DEBUG o mediante los comandos N y L Por ejemplo si queremos inspeccionar el contenido del archivo morecom podemos utilizar dos formas CWINDOWSgtDEBUG cwindowscommandmorecom CWINDOWSgtDEBUG - N cwindowscommandmorecom - L La sintaxis para el prefijo N es N [path-name]nombre-de-archivo En ambos casos el contenido del archivo seraacute cargado en memoria y podraacute ser utilizado Atencioacuten despueacutes de la orden L (Load) DEBUG le avisaraacute si no encuentra el archivo pero seguiraacute su funcionamiento En tal caso simplemente piensa que N sentildeala el nombre de un nuevo archivo que crearaacute con el contenido de la memoria -de DEBUG- cuando posteriormente seleccione la opcioacuten escribir W (Write)[4]

Nota Como ya habraacute deducido DEBUG permite leer un archivo realizar modificaciones en eacutel (con la opcioacuten E) y escribir el archivo modificado bajo otro nombre con NW

A continuacioacuten podemos comprobar el tamantildeo del archivo cargado Para ello usamos la opcioacuten 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 17A70100 E8CD0F CALL 10D0 -

Aquiacute nos interesa especialmente el contenido del registro CX cuyo valor 2917h (1519d) en este caso sentildeala el tamantildeo del archivo en bytes Tambieacuten podiacuteamos haber utilizado directamente el comando R CX que nos proporciona el valor de dicho registro -R CX CX 2917 -

Nota A continuacioacuten del valor correspondiente DEBUG muestra dos puntos () sentildealando que puede cambiar el valor del registro introduciendo un nuevo nuacutemero Pulse INTRO para dejar las cosas como estaacuten y volver al prompt (-) de DEBUG

Al llegar a este punto es importante sentildealar que a excepcioacuten de los archivos exe DEBUG carga los archivos a partir de la direccioacuten 100h (256d) de su memoria De forma que el primer octeto del archivo se carga en la direccioacuten 100 el segundo en 101 etc En nuestro caso el archivo se extenderaacute desde la posicioacuten 100h hasta 2A17h (100h + 2917h) A continuacioacuten para buscar la cadena Microsoft en el archivo utilizamos cualquiera de los siguientes comandos - S 100 L 2917 Microsoft - S 100 2a17 Microsoft El primer comando sentildeala el punto de inicio y el tamantildeo de la zona a buscar el segundo utiliza los puntos inicial y final de la exploracioacuten Con ambos se obtiene la misma respuesta 17A71083 17A710B2

Truco Debido a la forma especial en que se cargan los ejecutables exe si quiere inspeccionar la forma nativa de uno de estos archivos (como es su imagen en el disco) debe hacer una copia del archivo renombrarlo con cualquier otra terminacioacuten (o sin ella) y cargar esta copia En caso contrario DEBUG se prepararaacute para funcionar como un verdadero depurador de tiempo de ejecucioacuten (run-time) para lo que cargaraacute el archivo y lo acomodaraacute en memoria de forma que pueda ejecutarse [5]

Como ejercicio compruebe las distintas longitudes y aspecto (especialmente al principio) de un mismo archivo exe cargaacutendolo con DEBUG de las dos formas (busque en su sistema un exe lo maacutes pequentildeo posible) Ademaacutes de la capacidad de leer archivos antes mencionada quizaacutes una de las opciones maacutes interesantes (y peligrosas) de DEBUG es la posibilidad de leerescribir el contenido de disco a bajo nivel mediante los prefijos L (Load) y W (Write) Se utiliza la siguiente sintaxis L [Direccioacuten] [Unidad] [Primer_sector] [Nuacutemero] W [Direccioacuten] [Unidad] [Primer_sector] [Nuacutemero] El significado de los paraacutemetros es como sigue

Direccioacuten Posicioacuten de la memoria de DEBUG a partir de la cual se instalaraacuten los datos leiacutedos del disco o se tomaraacuten para el proceso de escritura (aquiacute se utiliza generalmente el valor 100h)

Unidad Valor numeacuterico que indica la loacutegica a utilizar 0 = A 1 = B 2 = C 3 = D etc [6]

Primer sector A partir del que se realizaraacute la lectura o se comenzaraacute a escribir

Nuacutemero Nuacutemero de sectores que se desea cargarescribir Como DEBUG no puede leerescribir maacutes de 64 Kbytes (2

16 = 65536) y los sectores de disco son de 512 bytes

el maacuteximo nuacutemero de sectores es 128 (80h) Asiacute pues el valor maacuteximo aquiacute es 80 Ejemplo Para obtener el contenido del sector de arranque (Master boot sector MBR) de un disquete en A utilizaremos el comando CWINDOWSgtDEBUG - L 100 0 0 1 - D 100 L 200 Como el resultado no cabe en una pantalla ingeniaremos un procedimiento para conservarlo en un archivo (maacutes adelante nos serviraacute para otro propoacutesito) Para ello creamos un archivo scripttxt con el siguiente contenido (dos INTRO despueacutes de la Q) L 100 0 0 1 D 100 L 200 Q A continuacioacuten invocamos DEBUG con el comando CWINDOWSgtDEBUG lt Dbuzonscripttxt gt Dbuzonresultadtxt Despueacutes de un breve parpadeo del disco y del disquete vuelve el prompt del DOS La operacioacuten ha concluido y en el directorio correspondiente de la unidad D tenemos el archivo resultadtxt con el volcado del sector de arranque del disquete ademaacutes de los ecos de los comandos introducidos (los hemos mantenido para orientacioacuten del lector) Otra forma de poder visualizar el contenido del Sector de Arranque del disco es utilizando el DEBUG Por ejemplo dentro del DEBUG tecleamos lo siguiente -L 100 0 0 1

-D 100 L 200

177C0100 EB 3E 90 2B 79 73 57 29-49 48 43 00 02 01 01 00 gt+ysW)IHC

177C0110 02 E0 00 40 0B F0 09 00-12 00 02 00 00 00 00 00

177C0120 00 00 00 00 00 00 29 5D-3B DD 10 4E 4F 20 4E 41 )]NO NA

177C0130 4D 45 20 20 20 20 46 41-54 31 32 20 20 20 F1 7D ME FAT12

177C0140 FA 33 C9 8E D1 BC FC 7B-16 07 BD 78 00 C5 76 00 3xv

177C0150 1E 56 16 55 BF 22 05 89-7E 00 89 4E 02 B1 0B FC VU~N

177C0160 F3 A4 06 1F BD 00 7C C6-45 FE 0F 8B 46 18 88 45 |EFE

177C0170 F9 FB 38 66 24 7C 04 CD-13 72 3C 8A 46 10 98 F7 8f$|rltF

177C0180 66 16 03 46 1C 13 56 1E-03 46 0E 13 D1 50 52 89 fFVFPR

177C0190 46 FC 89 56 FE B8 20 00-8B 76 11 F7 E6 8B 5E 0B FV v^

177C01A0 03 C3 48 F7 F3 01 46 FC-11 4E FE 5A 58 BB 00 07 HFNZX

177C01B0 8B FB B1 01 E8 94 00 72-47 38 2D 74 19 B1 0B 56 rG8-tV

177C01C0 8B 76 3E F3 A6 5E 74 4A-4E 74 0B 03 F9 83 C7 15 vgt^tJNt

177C01D0 3B FB 72 E5 EB D7 2B C9-B8 D8 7D 87 46 3E 3C D8 r+Fgtlt

177C01E0 75 99 BE 80 7D AC 98 03-F0 AC 84 C0 74 17 3C FF utlt

177C01F0 74 09 B4 0E BB 07 00 CD-10 EB EE BE 83 7D EB E5 t

177C0200 BE 81 7D EB E0 33 C0 CD-16 5E 1F 8F 04 8F 44 02 3^D

177C0210 CD 19 BE 82 7D 8B 7D 0F-83 FF 02 72 C8 8B C7 48 rH

177C0220 48 8A 4E 0D F7 E1 03 46-FC 13 56 FE BB 00 07 53 HNFVS

177C0230 B1 04 E8 16 00 5B 72 C8-81 3F 4D 5A 75 A7 81 BF [rMZu

177C0240 00 02 42 4A 75 9F EA 00-02 70 00 50 52 51 91 92 BJupPRQ

177C0250 33 D2 F7 76 18 91 F7 76-18 42 87 CA F7 76 1A 8A 3vvBv

177C0260 F2 8A 56 24 8A E8 D0 CC-D0 CC 0A CC B8 01 02 CD V$

177C0270 13 59 5A 58 72 09 40 75-01 42 03 5E 0B E2 CC C3 YZXruB^

177C0280 03 18 01 27 0D 0A 44 69-73 63 6F 20 69 6E 63 6F Disco inco

177C0290 72 72 65 63 74 6F 20 20-20 FF 0D 0A 45 72 72 6F rrecto Erro

177C02A0 72 20 45 2F 53 20 20 20-20 20 FF 0D 0A 43 61 6D r ES Cam

177C02B0 62 69 65 20 65 6C 20 64-69 73 63 6F 20 79 20 70 bie el disco y p

177C02C0 72 65 73 69 6F 6E 65 20-75 6E 61 20 74 65 63 6C resione una tecl

177C02D0 61 20 20 20 20 0D 0A 00-49 4F 20 20 20 20 20 20 a IO

177C02E0 53 59 53 4D 53 44 4F 53-20 20 20 53 59 53 80 01 SYSMSDOS SYS

177C02F0 00 57 49 4E 42 4F 4F 54-20 53 59 53 00 00 55 AA WINBOOT SYSU

-

-Q

FIN [1] En las primeras versiones de MS-DOS era un modesto programita DEBUGCOM de apenas 16 KB La versioacuten que acompantildea a Windows98 es ya un ejecutable en formato EXE de 21 KB [2] En realidad DEBUG es una utilidad de enorme potencia que requeririacutea todo un libro para ella sola Puede encontrarse una amplia descripcioacuten de esta herramienta en el libro de Paul Somerson PC Magazine DOS Powers Tools [3] Desgraciadamente no hay una convencioacuten estaacutendar sobre la colocacioacuten de los datos en la BIOS de forma que cada fabricante sigue sus propias reglas y es imposible por tanto utilizarla para cualquier tipo de identificacioacuten del sistema [4] En palabras del mencionado Paul Somerson Desgraciadamente debido a que DEBUG es un programa tan increiacuteblemente potente tambieacuten es increiacuteblemente peligroso Hay un dicho que afirma que El software no puede destruir el hardware Desgraciadamente esto no es cierto Ademaacutes de enviar mecanismos sensibles de la unidad de disco a tierra de nadie es posible hacer saltar monitores o transformadores Repito si sigue al pie de la letra las instrucciones y hace caso a todos los avisos todo iraacute bien [5] Recuerde que la imagen de un ejecutable exe cargado en memoria es distinta de su imagen en disco Solo en los ejecutables com la imagen en disco es una imagen exacta de su disposicioacuten en memoria [6] Es evidente que un pequentildeo error de nuacutemero en este paraacutemetro puede acarrear consecuencias nefastas Por ejemplo si cree que estaacute jugando con el disquete e inadvertidamente se dirige al disco duro (relea la nota [4])

Page 5: El Comando DEBUG

comparacioacuten y aritmeacuteticas modifican este registro Algunas instrucciones pueden realizar pruebas sobre este registro para determinar la accioacuten siguiente

OF (O) Bit de Overflow o desbordamiento Indica desbordamiento de un bit de orden alto (maacutes a la izquierda) despueacutes de una operacioacuten aritmeacutetica DF (D) Bit de Direccioacuten Designa la direccioacuten creciente (0) o decreciente (1) en operaciones con cadenas de caracteres IF (I) Bit de Interrupcioacuten Indica que una interrupcioacuten externa como la entrada desde el teclado sea procesada o ignorada TF (T) Bit de Trap o Desviacuteo Procesa o ignora la interrupcioacuten interna de trace (procesamiento paso a paso) SF (S) Bit de Signo Indica el valor del bit maacutes significativo del registro despueacutes de una operacioacuten aritmeacutetica o de desplazamiento ZF (Z) Bit Cero Se pone a 1 si una operacioacuten produce 0 como resultado AF (A) Bit de Carry Auxiliar Se pone a 1 si una operacioacuten aritmeacutetica produce un acarreo del bit 3 al 4 Se usa para aritmeacutetica especializada (ajuste BCD) PF (P) Bit de Paridad Se activa si el resultado de una operacioacuten tiene paridad par CF (C) Bit de Acarreo Contiene el acarreo de una operacioacuten aritmeacutetica 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 Cgt DEBUG [Enter] Una vez que el programa estaacute en ejecucioacuten el indicador (prompt) es un guioacuten - indicando que el Shell espera recibir oacuterdenes Para salir basta pulsar una Q Como muchos programas de su geacutenero sus comandos empiezan por una letra o combinacioacuten de ellas (pueden usarse indistintamente mayuacutesculas o minuacutesculas) y ciertos paraacutemetros opcionales (no es imprescindible separar la letra de opcioacuten de los paraacutemetros opcionales que siguen) La opcioacuten maacutes sencilla es la interrogacioacuten () cuyo resultado es una lista resumida de las opciones disponibles

Ensamblar A [direccioacuten] Comparar C direccioacuten de intervalo Volcar D [intervalo] Escribir E direccioacuten [lista de valores] Llenar F lista de intervalos Ir G [=direccioacuten] [direcciones] Hex H valor1 valor2 Entrada I puerto Cargar L [direccioacuten] [unidad] [primer_sector] [nuacutemero] Mover M direccioacuten de intervalo Nombre N [nombre_ruta] [lista_argumentos] Salida O byte de puerto Proceder P [=direccioacuten] [nuacutemero] Salir Q Registro R [registro] Buscar S lista de intervalos Seguimiento T [=direccioacuten] [valor] Desensamblar U [intervalo] Escribir W [direccioacuten] [unidad] [primer_sector] [nuacutemero] Asignar memoria expandida XA [paacuteginas] Desasignar memoria expandida XD [identificador] Asignar paacuteginas de memoria expandida XM [Lpaacutegina] [Ppaacutegina] [identificador] Mostrar estado de la memoria expandida XS

En particular obseacutervese 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 EJEMPLOCOM entonces carga a EJEMPLOCOM en memoria a partir de la direccioacuten 0100h

Comandos del DEBUG D DUMP D ltdireccioacuten1gt ltdireccioacuten2gt Muestra el contenido de una zona de memoria en hexadecimal y en ASCII Sin paraacutemetros muestra los primeros 128 bytes a partir de la posicioacuten a la que se llegoacute en el uacuteltimo d Si se le da un rango mostraraacute ese rango Ambas direcciones son opcionales La 1ra es la direccioacuten de inicio de despliegue la 2da es la direccioacuten de fin Ejemplo

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

E EDIT E ltdireccioacutengtltlistagt Permite editar byte por byte una zona de memoria Muestra -en hexadecimal- el byte de esa posicioacuten 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 siacute se ha hecho Para terminar la edicioacuten se pulsa INTRO Los cambios pueden ser especificados en la liacutenea de comandos en cualquier combinacioacuten de nuacutemeros hexadecimales o caracteres ASCII los caracteres ASCII deben estar entre comillas simples o dobles Por ejemplo E 100 Benjamin Iglesiasrsquo Establece el patroacuten 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 ltlistagt se entra en un modo especial en el que DEBUG despliega los valores de ltdireccioacutengt 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 ltregistrogt Sin paraacutemetros muestra el contenido de los registros de la CPU asiacute como la proacutexima instruccioacuten a ejecutarR [REGISTRO] muestra el contenido del registro especificado y cambia

el prompt de - a invitando a que se cambie su valor Pulsando Enter sin maacutes lo deja como estaba Ejemplo R ltregistrogt Donde ltregistrogt 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 sinoacutenimos A ASSEMBLE A ltdireccioacutengt Sin paraacutemetros ensambla las instrucciones que se introduzcan guardaacutendolas en la direccioacuten siguiente a la que se llegoacute en el uacuteltimo a Cuando se utiliza este comando se le puede dar como paraacutemetro la direccioacuten donde se desea que se inicie el ensamblado si se omite el paraacutemetro el ensamblado se iniciaraacute en la localizacioacuten especificada por CSIP usualmente 0100H que es la localizacioacuten donde deben iniciar los programas con extensioacuten COM y seraacute la localizacioacuten que utilizaremos debido a que DEBUG solo puede crear este tipo especiacutefico de programas La sintaxis es A ltdireccioacutengt Praacutecticamente cualquier mnemoteacutecnico es soportado por DEBUG incluyendo los especificadores de override de segmento (CS DS ES SS) Una excepcioacuten 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 instruccioacuten MOV que como veremos maacutes adelante sirve para copiar datos de la memoria a los registros y viceversa ademaacutes de copiar datos entre registros que es justo lo que vamos a usar en el ejemplo -a 20480106 mov axbx 20480108 mov bxcx 2048010A ltRETgt -u 106 108 20480106 89D8 MOV AXBX 20480108 89CB MOV BXCX Como veremos maacutes adelante la instruccioacuten U sirve para hacer volcados de memoria pero no viendo el contenido de la misma sino interpretaacutendola como instrucciones en lenguaje ensamblador Ejemplo 2 -r cs CS 2048 2050 -a 200 20500200 mov axbx 20500202 ltRETgt -u 200 200 20500200 89D8 MOV AXBX

F FILL F ltbloquegt ltvalor de rellenogt Este comando llena un bloque de memoria con un valor especiacutefico o una serie de valores La sintaxis es F ltbloquegt ltvalor de rellenogt ltbloquegt es la direccioacuten de inicio y final o si se preceden con L la direccioacuten de inicio y la longitud del bloque ltvalor de rellenogt es(son) el(los) valor(es) con los que debe de llenarse el bloque Si ltvalor de rellenogt 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 liacuteneas llena (con 0rsquos) el bloque DS00FF F DS0000 DS00FF 0 DS0000 LFF 0 Ejemplo -f 100 105 66 -d 100 105 20480100 66 66 66 66 66 66 ffffff Q QUIT Q Salir de DEBUG y volver al DOS P PROCEED P lt=direccioacutengtltnuacutemerogt Similar al comando T pero al encontrarse un CALL o INT lo ejecuta de golpe sin entrar en su interior (ojo iexclesto uacuteltimo falla al tracear sobre memoria ROM) Trace puede ser incoacutemodo si no se quiere depurar el coacutedigo de las rutinas de interrupcioacuten o si ya se sabe el coacutedigo que hay en las subrutinas y tan soacutelo interesa seguir avanzando sin entrar en ellas En estos casos se usa p por lo que si ejecutamos una interrupcioacuten de MS-DOS no sabriacuteamos 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 20480107 3D5000 CMP AX0050 -a 100 20480100 mov ax0200 20480103 mov dl61 20480105 int 21 20480107 -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 20480103 B261 MOV DL61 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 20480105 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 20480107 3D5000 CMP AX0050 T TRACE T lt=direccioacutengt ltvalorgt Ejecuta una instruccioacuten del programa (a partir de CSIP) mostrando a continuacioacuten el estado de los registros y la siguiente instruccioacuten Ejecutar T10 equivaldriacutea a ejecutar 16 veces el comando T Si la instruccioacuten es CALL o INT se ejecutaraacute como tal introducieacutendose 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 20480100 3D0000 CMP AX0000 -r bx BX 0000 2 -a 100 20480100 mov axbx 20480102 -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 20480102 00AC01D8 ADD [SI+D801]CH DSD801=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 20480100 3D0000 CMP AX0000 -a 100 20480100 mov axbx 20480102 mov cxbx 20480104 -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 20480102 89D9 MOV CXBX 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 20480104 01D8 ADD AXBX

N NAME N ltnombre_archivogt Se asigna un nombre al programa que estaacute siendo creado o modificado Se puede indicar la trayectoria de directorios L LOAD L ltbuffergt ltnumdiscogt ltsectorinigt ltnumsectorgt ltbuffergt es la direccioacuten en donde se carga la informacioacuten ltnumdiscogt es el nuacutemero (opcional) del disco de donde se leeraacute la informacioacuten (0=A 1=B 2=C etc) ltsectorinigt es el sector de disco absoluto (en hexadecimal) a leer ltnumsectorgt es la cantidad de sectores a leer No se pueden leer maacutes de 80H (128) sectores Si no se suministra la combinacioacuten ltnumdiscogt ltsectorinigt ltnumsectorgt DEBUG presume que se desea leer un archivo En este caso ltbuffergt es opcional Debe usarse el comando N (ver maacutes adelante) para especificar el archivo a leer Eacuteste se carga en CS0100 Ejemplo Se va a leer el sector 0 del disco A y se vuelca a partir de la direccioacuten DS100 como se puede observar el disco contiene mucha informacioacuten ( ESTO NO QUIERE DECIR QUE TENGA QUE SALIR LO MISMO EN SU VOLCADO )

l 100 0 0 1 -d 100 300

W WRITE W ltdireccioacutengt Graba el contenido de una zona de memoria a disco Si no se indica la direccioacuten se graba desde CS100h hasta CS100h+nuacutemero_bytes el nuacutemero de bytes se indica en BXCX (no es una direccioacuten segmentada sino un valor de 32 bits) Si se trata de un EXE no se permitiraacute grabarlo (para modificarlos hay que renombrarles para cambiarles la extensioacuten aunque de esta manera no seraacuten montados al cargarlos) La sintaxis es W ltbuffergt ltnumdiscogt ltsectorinigt ltnumsectorgt ltbuffergt es la direccioacuten de donde se carga la informacioacuten ltnumdiscogt es el nuacutemero (opcional) del disco en donde se escribiraacute la informacioacuten (0=A 1=B 2=C etc) ltsectorinigt es el sector de disco absoluto (en hexadecimal) en donde empieza la escritura ltnumsectorgt es la cantidad de sectores a leer No se pueden escribir maacutes de 80H (128) sectores Si no se suministra la combinacioacuten ltnumdiscogt ltsectorinigt ltnumsectorgt DEBUG presume que el inicio de archivo es CS100 En este caso ltbuffergt es opcional Debe usarse el comando N (ver arriba) para especificar el archivo a escribir Antes de escribir BXCX debe ajustarse al nuacutemero de bytes que desean grabarse W no puede escribir a archivos con la extensioacuten EXE o HEX [5] Ejemplo

N ltnomarchivogt BXCX lt--- 2000 W

S SEARCH S ltrangogt ltlistagt Busca una cadena de bytes por la memoria Para buscar la cadena PEPE terminada por cero en un aacuterea de 512 bytes desde DS100 se hariacutea S 100 L 200 PEPE0 (por defecto se busca en DS) No se encontrariacutea sin embargo pepe (en minuacutesculas) C COMPARE C ltrangogt ltdireccioacutengt Compara dos zonas de memoria mostrando las diferencias Por ejemplo para comparar 5 bytes de DS100 y DS200 se hace C 100 L 5 200 M MOVE M ltrangogt ltdireccioacutengt Maacutes que mover copia una zona de memoria en otra de manera inteligente (controlando los posibles solapamientos de los bloques) I INPUT I ltpuertogt Visualiza la lectura del puerto de ES indicado

O OUTPUT O ltpuertogt ltvalorgt Enviacutea un valor a un puerto de ES H HEX H ltvalor1gt ltvalor2gt Muestra la suma y resta de valor1 y valor2 ambos operandos de un maacuteximo de 16 bits (si hay desbordamiento se trunca el resultado que tampoco excede los 16 bits) Resultado ltresultado_1gt Es la suma ( ltvalor1gt + ltvalor2gt) ltresultado_2gt es la resta (ltvalor1gt - ltvalor2gt ) Ejemplo -h 0003 0002 0005 0001 -h 0000 0001 0001 FFFF como se observa el resultado de la segunda operacioacuten es FFFF que es el equivalente en complemento a 2 de -1 G GO G =ltiniciogt ltquiebre1gt ltquiebre2gt ltquiebre10gt Este comando ejecuta el coacutedigo en memoria Si se estaacute depurando un programa permite ejecutar el coacutedigo cargado en memoria Tambieacuten permite establecer puntos de quiebre (breakpoints) que son direcciones en las que se detiene la ejecucioacuten del programa La sintaxis es G =ltiniciogt ltquiebre1gt ltquiebre2gt ltquiebre10gt ltiniciogt es la direccioacuten de inicio de ejecucioacuten ltquiebre1gt hasta ltquiebre10gt son direcciones opcionales de paro del programa Si no se especifica ltiniciogt Go inicia con la direccioacuten contenida en CSIP Para lograr los quiebres DEBUG reemplaza el coacutedigo en las direcciones de quiebre por el valor hexadecimal CC que es el coacutedigo de interrupcioacuten Si DEBUG llega a CC todos los puntos de quiebre son restituidos los registros se despliegan (como con el comando R [veacutease adelante]) y se para la ejecucioacuten U UNASSEMBLE U ltrangogt Este comando desensambla el contenido de la memoria a partir de la posicioacuten actual Registros y Banderas del DEBUG La mayoriacutea de los comandos de DEBUG ejecutan una accioacuten y vuelven al indicador del shell pero si es un comando largo como puede ser mostrar un trozo grande de coacutedigo puede detenerse pulsando CTRL-Pausa o interrumpirse con CTRL-C para volver al shell Por ejemplo al teclear lo siguiente

- r [Enter]

-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 17A70100 E8CD0F CALL 10D0 - Se desplegaran todos los contenidos de los registros internos del microprocesador una forma alternativa de mostrarlos es usar el comando r utilizando como paraacutemetro el nombre del registro cuyo valor se quiera visualizar Por ejemplo

- r bx Esta instruccioacuten desplegaraacute uacutenicamente el contenido del registro BX y cambia el indicador del DEBUG de - a Estando asiacute el prompt es posible cambiar el valor del registro que se visualizoacute tecleando el nuevo valor y a continuacioacuten [Enter] o se puede dejar el valor anterior presionando [Enter] sin teclear ninguacuten valor Es posible cambiar el valor del registro de banderas asiacute como utilizarlo como estructura de control en nuestros programas como se veraacute maacutes adelante Cada bit del registro tiene un nombre y significado especial la lista dada a continuacioacuten describe el valor de cada bit tanto apagado como prendido y su relacioacuten con las operaciones del microprocesador

Overflow (O) NV = no hay desbordamiento OV = si lo hay Direction (D) UP = hacia adelante DN = hacia atraacutes Interrupts (I) DI = desactivadas EI = activadas Sign (S) PL = positivo NG = negativo Zero (Z) NZ = no es cero ZR = s lo es Auxiliary Carry (A) NA = no hay acarreo auxiliar

AC = hay acarreo auxiliar Parity (P) PO = paridad non PE = paridad par Carry (C) NC = no hay acarreo CY = Si lo hay

La estructura del ensamblador En el lenguaje ensamblador las liacuteneas de coacutedigo constan de dos partes la primera es el nombre de la instruccioacuten que se va a ejecutar y la segunda son los paraacutemetros del comando u operandos Por ejemplo

add ahbh Aquiacute add es el comando a ejecutar (en este caso una adicioacuten) y tanto ah como bh son los paraacutemetros El nombre de las instrucciones en este lenguaje estaacute formado por dos tres o cuatro letras a estas instrucciones tambieacuten se les llama nombres mnemoacutenicos o coacutedigos de operacioacuten ya que representan alguna funcioacuten que habraacute de realizar el microprocesador Existen algunos comandos que no requieren paraacutemetros para su operacioacuten asiacute como otros que requieren solo un paraacutemetro Algunas veces se utilizaraacuten las instrucciones como sigue

add al[170] Los corchetes en el segundo paraacutemetro nos indican que vamos a trabajar con el contenido de la posicioacuten de memoria nuacutemero 170 y no con el valor 170 a esto se le conoce como direccionamiento directo Primer programa en ensamblador con el DEBUG Vamos a crear un programa que sirva para ilustrar lo que hemos estado viendo lo que haremos seraacute una suma de dos valores que introduciremos directamente en el programa El primer paso es iniciar el DEBUG este paso consiste uacutenicamente en teclear DEBUG [Enter] en el prompt del sistema operativo Para ensamblar un programa en el DEBUG se utiliza el comando a (assemble) cuando se utiliza este comando se le puede dar como paraacutemetro la direccioacuten donde se desea que se inicie el ensamblado Si se omite el paraacutemetro el ensamblado se iniciaraacute en la localidad especificada por CSIP usualmente 0100H que es la localidad donde deben iniciar los programas con extensioacuten COM y seraacute la localidad que utilizaremos debido a que DEBUG solo puede crear este tipo especiacutefico de programas

Aunque en este momento no es necesario darle un paraacutemetro al comando a es recomendable hacerlo para evitar problemas una vez que se haga uso de los registros CSIP por lo tanto tecleamos

- a 100 [Enter] Al hacer esto apareceraacute en la pantalla algo como 0C1B0100 y el cursor se posiciona a la derecha de estos nuacutemeros noacutetese que los primeros cuatro diacutegitos (en sistema hexadecimal) pueden ser diferentes pero los uacuteltimos cuatro deben ser 0100 ya que es la direccioacuten que indicamos como inicio Ahora podemos introducir las instrucciones

0C1B0100 mov ax0002 coloca el valor 0002 en el registro ax 0C1B0103 mov bx0004 coloca el valor 0004 en el registro bx 0C1B0106 add axbx le adiciona al contenido de ax el contenido de bx 0C1B0108 int 20 provoca la terminacioacuten del programa 0C1B010A

No es necesario escribir los comentarios que van despueacutes del Una vez escrito el uacuteltimo comando int 20 se le da [Enter] sin escribir nada maacutes para volver al prompt del DEBUG La uacuteltima liacutenea escrita no es propiamente una instruccioacuten de ensamblador es una llamada a una interrupcioacuten del sistema operativo estas interrupciones seraacuten tratadas maacutes a fondo en un capiacutetulo posterior por el momento solo es necesario saber que nos ahorran un gran nuacutemero de liacuteneas y son muy uacutetiles para accesar a funciones del sistema operativo Para ejecutar el programa que escribimos se utiliza el comando g al utilizarlo veremos que aparece un mensaje que dice Program terminated normally Naturalmente con un mensaje como eacuteste no podemos estar seguros que el programa haya hecho la suma pero existe una forma sencilla de verificarlo utilizando el comando r del DEBUG podemos ver los contenidos de todos los registros del microprocesador simplemente teclee

- r [Enter] Apareceraacute en pantalla cada registro con su respectivo valor actual -R AX=0006 BX=0004 CX=0000 DX=0000 SP=FFFE BP=0000 SI=0000 DI=0000 DS=0C1B ES=0C1B SS=0C1B CS=0C1B IP=010A NV UP EI PL NZ NA PO NC 17A70100 E8CD0F CALL 10D0 - Existe la posibilidad de que los registros contengan valores diferentes pero AX y BX deben ser los mismos ya que son los que acabamos de modificar Otra forma de ver los valores mientras se ejecuta el programa es utilizando como paraacutemetro para g la direccioacuten donde queremos que termine la ejecucioacuten y muestre los valores de los registros en este caso seraacute g108 esta instruccioacuten ejecuta el programa se detiene en la direccioacuten 108 y muestra los contenidos de los registros Tambieacuten se puede llevar un seguimiento de lo que pasa en los registros utilizando el comando t (trace) la funcioacuten de este comando es ejecutar liacutenea por liacutenea lo que se ensambloacute mostrando cada vez los contenidos de los registros Para salir del DEBUG se utiliza el comando q (quit)

Guardar y cargar los programas No seriacutea praacutectico tener que escribir todo un programa cada vez que se necesite para evitar eso es posible guardar un programa en el disco con la enorme ventaja de que ya ensamblado no seraacute necesario correr de nuevo DEBUG para ejecutarlo ya que cuando el DEBUG guardo nuestro programa en el disco eacuteste se guardo en binario (archivo con la extensioacuten com) Los pasos a seguir para guardar un programa ya almacenado en la memoria son

Obtener la longitud del programa restando la direccioacuten final de la direccioacuten inicial naturalmente en sistema hexadecimal

Darle un nombre al programa y una extensioacuten

Poner la longitud del programa en el registro CX

Ordenar a DEBUG que escriba el programa en el disco Utilizando como ejemplo el programa del ejemplo anterior tendremos una idea maacutes clara de coacutemo llevar estos pasos Al terminar de ensamblar el programa se veriacutea asiacute

0C1B0100 mov ax0002 0C1B0103 mov bx0004 0C1B0106 add axbx 0C1B0108 int 20 0C1B010A

Para almacenarlo en el disco hacemos lo siguiente - h 10a 100 020a 000a - n pruebacom - r cx CX 0000 000a -w Writing 000A bytes

Para obtener la longitud de un programa se utiliza el comando h el cual nos muestra la suma y resta de dos nuacutemeros en hexadecimal Para obtener la longitud del programa le proporcionamos como paraacutemetros el valor de la direccioacuten final de nuestro programa (10A) y el valor de la direccioacuten inicial (0100) El primer resultado que nos muestra el comando es la suma de los paraacutemetros y el segundo es la resta El comando n nos permite poner un nombre al programa El comando r cx nos permite cambiar el contenido del registro CX al valor que obtuvimos del tamantildeo del archivo con h en este caso 000a ya que nos interesa el resultado de la resta de la direccioacuten inicial a la direccioacuten final

Por uacuteltimo el comando w escribe nuestro programa en el disco indicaacutendonos cuantos bytes escribioacute

NOTA Si se trabaja en una ventana de DOS de Windows Vista o 7 es probable que al momento de guardar su programa el DEBUG escriba mas coacutedigo que el sentildealado por el registro CX por consiguiente seraacute necesario limpiar el registro BX esto es ponerlo a ceros y despueacutes utilizar el comando w Por ejemplo _r bx BX 000E 0000 w

Para cargar un archivo ya guardado son necesarios dos pasos

Proporcionar el nombre del archivo que se cargaraacute a memoria

Cargarlo utilizando el comando l (load) Para obtener el resultado correcto de los siguientes pasos es necesario que previamente se haya creado el programa anterior Dentro del DEBUG escribimos lo siguiente

- n pruebacom - l - u 100 109 0C3D0100 B80200 MOV AX0002 0C3D0103 BB0400 MOV BX0004 0C3D0106 01D8 ADD AXBX 0C3D0108 CD20 INT 20

El uacuteltimo comando u se utiliza para verificar que el programa se cargoacute en memoria lo que hace es desensamblar el coacutedigo y mostrarlo ya desensamblado Los paraacutemetros le indican a DEBUG desde donde y hasta donde desensamblar DEBUG siempre carga los programas en memoria en la direccioacuten 100H a menos que se le indique alguna otra Un programa que realiza un conteo en pantalla Con el DEBUG es posible escribir un programa que realice un conteo en pantalla por razones de comprensioacuten nuestro programa solo realizara un conteo de 9 a 0 (conteo descendente) 0B3B0100 B90A00 MOV CX000A CX=10 en decimal 0B3B0103 88CA MOV DLCL 0B3B0105 80C22F ADD DL2F sumamos 02Fh a DL 0B3B0108 B402 MOV AH02 funcioacuten 02 de INT 21 para imprimir un caracter 0B3B010A CD21 INT 21

0B3B010C E2F5 LOOP 0103 CX=0 Si no salta a 0103 0B3B010E CD20 INT 20 termina el programa En la liacutenea 0103 se puede observar que el valor del registro CX en su parte baja (en CL) se almacena en el registro DL Si se omitiera la liacutenea 0105 entonces cuando se ejecutara la liacutenea 010A solo se imprimiriacutea en pantalla el coacutedigo ASCII del valor que contenga DL (el coacutedigo ASCII de 0Ah que es 10 en decimal es un caraacutecter especial no imprimible) Para conseguir el ldquoefectordquo de que el programa realiza el conteo en decimal se hace un corrimiento de 02F (47 en decimal) Por ejemplo cuando se ejecuta la liacutenea 0105 DL tendriacutea el valor de 39h=57d (02Fh+0Ah=39h=57d) y el coacutedigo ASCII de 57d es el caraacutecter ldquo9rdquo El sentencia LOOP decrementa CX en 1 si CX es diferente a 0 salta a la liacutenea 0103 El proceso se repite y el programa imprime en pantalla 9876543210 Seriacutea interesante que el programa anterior fuera modificado para que la numeracioacuten se imprimiera de la siguiente manera 9 8 7 6 5 4 3 2 1 0

NOTA Como se dijo anteriormente cuando el DEBUG almacena un programa en el disco este archivo se graba en binario esto es en ejecutable Por lo tanto no es necesario cargar el DEBUG para volver a ejecutar nuestro programa sino que se hace de manera directa desde DOS El problema surge cuando al ejecutar nuestro programa el resultado no se puede observar porque el DOS borra la pantalla despueacutes de terminar de ejecutar el programa Para evitar el borrado automaacutetico seraacute necesario agregarle a nuestro programa antes de la INT 20h una instruccioacuten para la lectura de un caraacutecter desde el teclado Para tal efecto utilizaremos la funcioacuten 08 de la INT 21h (un buen truco para que el programa haga una pausa) asiacute el programa esperara hasta que el usuario presiona una tecla permitiendo observar el resultado Ejemplo mov ah08 Int 21 Int 20

Condiciones ciclos y bifurcaciones Estas estructuras o formas de control le dan a la maacutequina un cierto grado de decisioacuten basado en la informacioacuten que recibe La forma maacutes sencilla de comprender este tema es por medio de ejemplos Vamos a crear tres programas que hagan lo mismo desplegar un nuacutemero determinado de veces una cadena de caracteres en la pantalla

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV CX000F veces que se desplegara la cadena 0C1B0128 MOV DX0102 copia cadena al registro DX 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F LOOP 012D si CXgt0 salta a 012D 0C1B0131 INT 20 termina el programa

Por medio del comando e es posible introducir una cadena de caracteres en una determinada localidad de memoria dada como paraacutemetro la cadena se introduce entre comillas le sigue un espacio luego el valor hexadecimal del retorno de carro un espacio el valor de liacutenea nueva y por uacuteltimo el siacutembolo $ que el ensamblador interpreta como final de la cadena La interrupcioacuten 21 utiliza el valor almacenado en el registro AH para ejecutar una determinada funcioacuten en este caso mostrar la cadena en pantalla la cadena que muestra es la que estaacute almacenada en el registro DX La instruccioacuten LOOP decrementa automaacuteticamente el registro CX en uno y si no ha llegado el valor de este registro a cero salta a la posicioacuten de memoria indicada como paraacutemetro lo cual crea un ciclo que se repite el nuacutemero de veces especificado por el valor de CX La interrupcioacuten 20 termina la ejecucioacuten del programa Otra forma de realizar la misma funcioacuten pero sin utilizar el comando LOOP es la siguiente

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV BX000F veces que se desplegara la cadena 0C1B0128 MOV DX0102 copia cadena al registro DX 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F DEC BX decrementa en 1 a BX 0C1B0130 JNZ 012D si BX es diferente a 0 salta a 012D 0C1B0132 INT 20 termina el programa

En este caso se utiliza el registro BX como contador para el programa y por medio de la instruccioacuten DEC se disminuye su valor en 1 La instruccioacuten JNZ verifica si el valor de BX es diferente a 0 esto con base en la bandera NZ en caso afirmativo salta hacia la direccioacuten 012D En caso contrario continuacutea la ejecucioacuten normal del programa y por lo tanto se termina Una uacuteltima variante del programa es utilizando de nuevo a CX como contador pero en lugar de utilizar LOOP utilizaremos decrementos a CX y comparacioacuten de CX a 0

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV DX0102 copia cadena al registro DX 0C1B0128 MOV CX000F veces que se desplegara la cadena 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F DEC CX decrementa en 1 a CX 0C1B0130 JCXZ 0134 si CX es igual a 0 salta a 0134 0C1B0132 JMP 012D salta a la direccioacuten 012D 0C1B0134 INT 20 termina el programa

En este ejemplo se usoacute la instruccioacuten JCXZ para controlar la condicioacuten de salto el significado de tal funcioacuten es salta si CX=0 El tipo de control a utilizar dependeraacute de las necesidades de programacioacuten en determinado momento

Manipulacioacuten de Posiciones de Memoria Con el DEBUG es posible almacenar y recuperar datos numeacutericos en memoria por medio de un programa a traveacutes de los registros del microprocesador Por ejemplo el siguiente programa almacena previamente dos valores numeacutericos en la posicioacuten 0300h y 0400h respectivamente despueacutes el programa los recupera realiza la operacioacuten de suma con esos valores y el resultado lo almacena en la posicioacuten 0500h -a 100 0B1C0100 mov ax0002 ax=2 0B1C0103 mov [0300]ax almacenamos 2 en la direccioacuten 0300h 0B1C0106 mov ax0004 ax=4 0B1C0109 mov [0400]ax almacenamos 4 en la direccioacuten 0400h 0B1C010C mov ax[0300] recuperamos el dato1 en AX 0B1C010F mov bx[0400] recuperamos el dato2 en BX 0B1C0113 add axbx hacemos la operacioacuten de suma en AX 0B1C0115 mov [0500]ax almacenamos el 6 en la direccioacuten 0500h 0B1C0118 int 21 0B1C011A - Un nuacutemero entre corchetes [numero_hex] indica una posicioacuten de memoria y su manejo se hace a traveacutes de registros ya que no es posible almacenar valores numeacutericos de manera directa Ejecutamos el programa -g 118 AX=0006 BX=0004 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=0B1C ES=0B1C SS=0B1C CS=0B1C IP=0118 NV UP EI PL NZ NA PE NC 0B1C0118 CD21 INT 21 - Para ver si el resultado se almaceno en la direccioacuten correcta hacemos

Como se puede observar en la direccioacuten 0B1C0500 se encuentra el 06 y en 0B1C0501 se encuentra el 00 que es el resultado de la operacioacuten 2+4 Perohellip Porque aparece el 06 y despueacutes el 00 pareceriacutea que el resultado fue de 0600 pero no es asiacute lo que sucedes que los datos se almacenan en memoria de la siguiente manera

Como se hizo la operacioacuten AX=AX+BX entonces el resultado es de 16 bits (dos bytes) AX=6 entonces AX=0000 0000 0000 0110 (16 bits) por lo tanto los 8 bits de menor peso de AX son 0000 0110 y deben almacenarse en la direccioacuten 0500 y en la direccioacuten 0501 se almacena 0000 0000

0 0 0 0 0 1 1 0 0500

0 0 0 0 0 0 0 0 0501

x x x x x x x x 0502

x x x x x x x x 0503

x x x x x x x x 0504

x x x x x x x x 0505

Interrupciones Definicioacuten de interrupcioacuten

Una interrupcioacuten es una instruccioacuten que detiene la ejecucioacuten de un programa para permitir el uso del microprocesador en un proceso prioritario Una vez concluido este uacuteltimo proceso se devuelve el control a la aplicacioacuten anterior

Por ejemplo cuando estamos trabajando con un procesador de palabras y en ese momento llega un aviso de uno de los puertos de comunicaciones se detiene temporalmente la aplicacioacuten que estaacutebamos utilizando para permitir el uso del microprocesador al manejo de la informacioacuten que estaacute llegando en ese momento Una vez terminada la transferencia de informacioacuten se reanudan las funciones normales del procesador de palabras Las interrupciones ocurren muy seguido sencillamente la interrupcioacuten que actualiza la hora del diacutea ocurre aproximadamente 18 veces por segundo Para lograr administrar todas estas interrupciones la computadora cuenta con un espacio de memoria llamado memoria baja donde se almacenan las direcciones de cierta localidad de memoria donde se encuentran un juego de instrucciones que el microprocesador ejecutaraacute para despueacutes regresar a la aplicacioacuten que estaba en proceso En los programas anteriores hicimos uso de la interrupcioacuten nuacutemero 20H para terminar la ejecucioacuten de nuestros programas y en otros ejemplos utilizamos otra interrupcioacuten para mostrar informacioacuten en pantalla (INT 21h) Utilizando DEBUG tecleamos

- a100 2C1B0100 JMP 011D 2C1B0102 [ENTER] - E 102 Hola como estas 0D 0A $ - A011D 2C1B011D MOV DX0102 2C1B0120 MOV AH09 2C1B0122 INT 21 2C1B0123 INT 20

Orden

creciente

de la

memoria

En este programa la interrupcioacuten 21h manda al monitor la cadena localizada en la direccioacuten a la que apunta el registro DX El valor que se le da a AH determina cual de las opciones de la interrupcioacuten 21h seraacute utilizada ya que esta interrupcioacuten cuenta con varias opciones El manejo directo de interrupciones es una de las partes maacutes fuertes del lenguaje ensamblador ya que con ellas es posible controlar eficientemente todos los dispositivos internos y externos de una computadora gracias al completo control que se tiene sobre operaciones de entrada y salida Maacutes del DEBUG Una caracteriacutestica poco conocida es que DEBUG puede aceptar entradas desde un archivo Script que puede ser un simple archivo de texto ASCII en el que cada comando esteacute separado del anterior por un INTRO Despueacutes del uacuteltimo que debe ser una Q para salir de DEBUG es conveniente dejar una liacutenea en blanco pulsando INTRO dos veces Las liacuteneas pueden contener comentarios Cualquier cosa a partir del caracter punto y coma () hasta el final de la liacutenea seraacute ignorado esto es un comentario D aquiacute se mostraraacute algo Suponiendo que tengamos un archivo Script de nombre Ordenestxt puede ser utilizado como entrada para DEBUG mediante un comando de redireccioacuten en la siguiente forma DEBUG lt ordenestxt Tambieacuten puede conseguirse que el programa redireccione la salida hacia un archivo que puede ser inspeccionado maacutes 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 podriacutea obtenerse un archivo Resulttxt con el siguiente comando DEBUG lt ordenestxt gt Resulttxt Errores Cuando DEBUG no sabe interpretar un comando muestra un mensaje de error y un indicador ^ debajo del sitio del comando donde estaacute el error Entradas y Salidas DEBUG asume que los datos numeacutericos proporcionados son hexadecimales y cuando se trate de direcciones de memoria deben introducirse en forma segmentada A su vez los resultados son mostrados tambieacuten 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

Cada fila muestra 16 posiciones de memoria a partir de la posicioacuten sentildealada por las columnas de la izquierda que las muestran como segmentodesplazamiento El bloque central muestra el contenido hexadecimal de cada byte mientras que el bloque derecho contiene la representacioacuten ASCII Por ejemplo la 3ra fila muestra el contenido de las posiciones 0B770120 a 0B77012F (ambas inclusive) Sus tres uacuteltimos bytes contienen respectivamente los caracteres r 9 y 2 que corresponden a las cantidades 72h 39h y 32h del bloque central Que como sabemos equivalen a los decimales 114 57 y 50 que son precisamente los valores ASCII de los caracteres ldquorrdquo ldquo9rdquo y ldquo2rdquo anteriormente mencionados

Nota Por razoacuten de que eacuteste tipo de salida pueda ser listado a impresora el bloque derecho no contiene en realidad la representacioacuten ASCII de todos los caracteres (algunos ni siquiera tienen una representacioacuten imprimible) En realidad solo se muestran los caracteres imprimibles del primer bloque (US-ASCII) El resto estaacute 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 caraacutecter imprimible Esto no significa que dichas posiciones representen efectivamente tales valores para la aplicacioacuten que las utiliza Por ejemplo puede que en realidad las dos posiciones de memoria mencionadas (dos octetos o bytes) en vez de los caracteres ldquo5rdquo y ldquoardquo representen una palabra de 16 bits en formato Little Endian que a su vez representan una cantidad entera (un nuacutemero) Comandos Aunque su descripcioacuten completa llenariacutea todo un capiacutetulo a continuacioacuten comentamos algunas de las opciones maacutes interesantes relativas a inspeccioacuten del coacutedigo y de contenidos de memoria La opcioacuten D (Dump) permite obtener un volcado del contenido de la memoria (de DEBUG) La sintaxis acepta dos formas D [direccioacuten-inicial] [L posiciones-desde-direccioacuten-inicial ] D [direccioacuten-inicial][direccioacuten-final] Naturalmente para que exista algo en el buacutefer de memoria (al principio quizaacutes solo contiene basura) es preciso indicarle que lea algo Este algo puede ser un rango de direcciones de memoria RAM una direccioacuten absoluta de disco (sector) un archivo o el contenido de los registros del procesador Para empezar puede indicaacutersele que cargue un archivo xxxxyz que tenemos en el directorio actual o en el PATH cuyo contenido queremos ver Cgt DEBUG xxxxyz -D aquiacute se obtendriacutea una salida anaacuteloga a la comentada

Hemos visto un ejemplo al tratar de los servicios de interrupciones del PC aquiacute mostraremos otro Sabemos que el punto de inicio de la BIOS es la direccioacuten F000FFF0 y que desde eacutesta posicioacuten hasta el final de la memoria DOS hay 16 bytes Puede obtenerse un volcado de estas posiciones con el siguiente comando -D F000FFF0 La salida en un equipo puede ser F000FFF0 CD 19 E0 00 F0 30 36 2F-33 30 2F 39 37 00 FC 38 0630978 En este caso el comando solo muestra una liacutenea porque ha alcanzado el final de la memoria Puede verse que la fecha de la BIOS del sistema ocupa las uacuteltimas posiciones Si se ordena el volcado de una direccioacuten suficientemente alejada del final de la memoria sin indicar ninguacuten nuacutemero de posiciones por defecto se toma el valor 128 (8 filas de 16 posiciones) Si desea una cantidad distinta hay que antildeadir una L (Long) y el nuacutemero de posiciones hasta un maacuteximo de 64 KB (FFFF) Todos los nuacutemeros deben ser expresados en hexadecimal Por consiguiente los dos comandos que siguen son equivalentes (recuerde que 80 es el equivalente hexadecimal de 128) D FE000000 D FE000000 L 80 He aquiacute el resultado

Sabemos que esta zona corresponde al aacuterea de la BIOS del Sistema Otra opcioacuten muy interesante nos permite buscar determinados contenidos a traveacutes de la memoria utilizando el prefijo S (Search) Existen dos sintaxis alternativas S direccioacuten-de-inicio L longitud-a-explorar contenido-a-buscar S direccioacuten-de-inicio direccioacuten-final L contenido-a-buscar El contenido debe ser proporcionado en hexadecimal (tal como apareceriacutea en la columna central del ejemplo anterior) o entre comillas si es un texto ASCII Por ejemplo en un equipo IBM deseo ver algunas caracteriacutesticas de la BIOS Seacute que estos datos se alojan a partir de la posicioacuten F0000000 hasta el final de la memoria Es decir una longitud de 64 Kbytes (FFFF) a partir de la posicioacuten de inicio y que seguramente los datos buscados estaraacuten cerca de la identificacioacuten de la propia BIOS (la cadena IBM) Por lo que se utiliza la siguiente sintaxis [3] -s f0000000 L ffff IBM

y se obtiene la siguiente salida F000E00E F000E111 con las direcciones donde se ha encontrado la ocurrencia buscada A continuacioacuten puedo explorar las proximidades de cada posicioacuten Por ejemplo para la primera -D f000e000

Si lo que se busca estaacute en un archivo primero hay que cargarlo Lo que se puede hacer de dos formas en la propia invocacioacuten de DEBUG o mediante los comandos N y L Por ejemplo si queremos inspeccionar el contenido del archivo morecom podemos utilizar dos formas CWINDOWSgtDEBUG cwindowscommandmorecom CWINDOWSgtDEBUG - N cwindowscommandmorecom - L La sintaxis para el prefijo N es N [path-name]nombre-de-archivo En ambos casos el contenido del archivo seraacute cargado en memoria y podraacute ser utilizado Atencioacuten despueacutes de la orden L (Load) DEBUG le avisaraacute si no encuentra el archivo pero seguiraacute su funcionamiento En tal caso simplemente piensa que N sentildeala el nombre de un nuevo archivo que crearaacute con el contenido de la memoria -de DEBUG- cuando posteriormente seleccione la opcioacuten escribir W (Write)[4]

Nota Como ya habraacute deducido DEBUG permite leer un archivo realizar modificaciones en eacutel (con la opcioacuten E) y escribir el archivo modificado bajo otro nombre con NW

A continuacioacuten podemos comprobar el tamantildeo del archivo cargado Para ello usamos la opcioacuten 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 17A70100 E8CD0F CALL 10D0 -

Aquiacute nos interesa especialmente el contenido del registro CX cuyo valor 2917h (1519d) en este caso sentildeala el tamantildeo del archivo en bytes Tambieacuten podiacuteamos haber utilizado directamente el comando R CX que nos proporciona el valor de dicho registro -R CX CX 2917 -

Nota A continuacioacuten del valor correspondiente DEBUG muestra dos puntos () sentildealando que puede cambiar el valor del registro introduciendo un nuevo nuacutemero Pulse INTRO para dejar las cosas como estaacuten y volver al prompt (-) de DEBUG

Al llegar a este punto es importante sentildealar que a excepcioacuten de los archivos exe DEBUG carga los archivos a partir de la direccioacuten 100h (256d) de su memoria De forma que el primer octeto del archivo se carga en la direccioacuten 100 el segundo en 101 etc En nuestro caso el archivo se extenderaacute desde la posicioacuten 100h hasta 2A17h (100h + 2917h) A continuacioacuten para buscar la cadena Microsoft en el archivo utilizamos cualquiera de los siguientes comandos - S 100 L 2917 Microsoft - S 100 2a17 Microsoft El primer comando sentildeala el punto de inicio y el tamantildeo de la zona a buscar el segundo utiliza los puntos inicial y final de la exploracioacuten Con ambos se obtiene la misma respuesta 17A71083 17A710B2

Truco Debido a la forma especial en que se cargan los ejecutables exe si quiere inspeccionar la forma nativa de uno de estos archivos (como es su imagen en el disco) debe hacer una copia del archivo renombrarlo con cualquier otra terminacioacuten (o sin ella) y cargar esta copia En caso contrario DEBUG se prepararaacute para funcionar como un verdadero depurador de tiempo de ejecucioacuten (run-time) para lo que cargaraacute el archivo y lo acomodaraacute en memoria de forma que pueda ejecutarse [5]

Como ejercicio compruebe las distintas longitudes y aspecto (especialmente al principio) de un mismo archivo exe cargaacutendolo con DEBUG de las dos formas (busque en su sistema un exe lo maacutes pequentildeo posible) Ademaacutes de la capacidad de leer archivos antes mencionada quizaacutes una de las opciones maacutes interesantes (y peligrosas) de DEBUG es la posibilidad de leerescribir el contenido de disco a bajo nivel mediante los prefijos L (Load) y W (Write) Se utiliza la siguiente sintaxis L [Direccioacuten] [Unidad] [Primer_sector] [Nuacutemero] W [Direccioacuten] [Unidad] [Primer_sector] [Nuacutemero] El significado de los paraacutemetros es como sigue

Direccioacuten Posicioacuten de la memoria de DEBUG a partir de la cual se instalaraacuten los datos leiacutedos del disco o se tomaraacuten para el proceso de escritura (aquiacute se utiliza generalmente el valor 100h)

Unidad Valor numeacuterico que indica la loacutegica a utilizar 0 = A 1 = B 2 = C 3 = D etc [6]

Primer sector A partir del que se realizaraacute la lectura o se comenzaraacute a escribir

Nuacutemero Nuacutemero de sectores que se desea cargarescribir Como DEBUG no puede leerescribir maacutes de 64 Kbytes (2

16 = 65536) y los sectores de disco son de 512 bytes

el maacuteximo nuacutemero de sectores es 128 (80h) Asiacute pues el valor maacuteximo aquiacute es 80 Ejemplo Para obtener el contenido del sector de arranque (Master boot sector MBR) de un disquete en A utilizaremos el comando CWINDOWSgtDEBUG - L 100 0 0 1 - D 100 L 200 Como el resultado no cabe en una pantalla ingeniaremos un procedimiento para conservarlo en un archivo (maacutes adelante nos serviraacute para otro propoacutesito) Para ello creamos un archivo scripttxt con el siguiente contenido (dos INTRO despueacutes de la Q) L 100 0 0 1 D 100 L 200 Q A continuacioacuten invocamos DEBUG con el comando CWINDOWSgtDEBUG lt Dbuzonscripttxt gt Dbuzonresultadtxt Despueacutes de un breve parpadeo del disco y del disquete vuelve el prompt del DOS La operacioacuten ha concluido y en el directorio correspondiente de la unidad D tenemos el archivo resultadtxt con el volcado del sector de arranque del disquete ademaacutes de los ecos de los comandos introducidos (los hemos mantenido para orientacioacuten del lector) Otra forma de poder visualizar el contenido del Sector de Arranque del disco es utilizando el DEBUG Por ejemplo dentro del DEBUG tecleamos lo siguiente -L 100 0 0 1

-D 100 L 200

177C0100 EB 3E 90 2B 79 73 57 29-49 48 43 00 02 01 01 00 gt+ysW)IHC

177C0110 02 E0 00 40 0B F0 09 00-12 00 02 00 00 00 00 00

177C0120 00 00 00 00 00 00 29 5D-3B DD 10 4E 4F 20 4E 41 )]NO NA

177C0130 4D 45 20 20 20 20 46 41-54 31 32 20 20 20 F1 7D ME FAT12

177C0140 FA 33 C9 8E D1 BC FC 7B-16 07 BD 78 00 C5 76 00 3xv

177C0150 1E 56 16 55 BF 22 05 89-7E 00 89 4E 02 B1 0B FC VU~N

177C0160 F3 A4 06 1F BD 00 7C C6-45 FE 0F 8B 46 18 88 45 |EFE

177C0170 F9 FB 38 66 24 7C 04 CD-13 72 3C 8A 46 10 98 F7 8f$|rltF

177C0180 66 16 03 46 1C 13 56 1E-03 46 0E 13 D1 50 52 89 fFVFPR

177C0190 46 FC 89 56 FE B8 20 00-8B 76 11 F7 E6 8B 5E 0B FV v^

177C01A0 03 C3 48 F7 F3 01 46 FC-11 4E FE 5A 58 BB 00 07 HFNZX

177C01B0 8B FB B1 01 E8 94 00 72-47 38 2D 74 19 B1 0B 56 rG8-tV

177C01C0 8B 76 3E F3 A6 5E 74 4A-4E 74 0B 03 F9 83 C7 15 vgt^tJNt

177C01D0 3B FB 72 E5 EB D7 2B C9-B8 D8 7D 87 46 3E 3C D8 r+Fgtlt

177C01E0 75 99 BE 80 7D AC 98 03-F0 AC 84 C0 74 17 3C FF utlt

177C01F0 74 09 B4 0E BB 07 00 CD-10 EB EE BE 83 7D EB E5 t

177C0200 BE 81 7D EB E0 33 C0 CD-16 5E 1F 8F 04 8F 44 02 3^D

177C0210 CD 19 BE 82 7D 8B 7D 0F-83 FF 02 72 C8 8B C7 48 rH

177C0220 48 8A 4E 0D F7 E1 03 46-FC 13 56 FE BB 00 07 53 HNFVS

177C0230 B1 04 E8 16 00 5B 72 C8-81 3F 4D 5A 75 A7 81 BF [rMZu

177C0240 00 02 42 4A 75 9F EA 00-02 70 00 50 52 51 91 92 BJupPRQ

177C0250 33 D2 F7 76 18 91 F7 76-18 42 87 CA F7 76 1A 8A 3vvBv

177C0260 F2 8A 56 24 8A E8 D0 CC-D0 CC 0A CC B8 01 02 CD V$

177C0270 13 59 5A 58 72 09 40 75-01 42 03 5E 0B E2 CC C3 YZXruB^

177C0280 03 18 01 27 0D 0A 44 69-73 63 6F 20 69 6E 63 6F Disco inco

177C0290 72 72 65 63 74 6F 20 20-20 FF 0D 0A 45 72 72 6F rrecto Erro

177C02A0 72 20 45 2F 53 20 20 20-20 20 FF 0D 0A 43 61 6D r ES Cam

177C02B0 62 69 65 20 65 6C 20 64-69 73 63 6F 20 79 20 70 bie el disco y p

177C02C0 72 65 73 69 6F 6E 65 20-75 6E 61 20 74 65 63 6C resione una tecl

177C02D0 61 20 20 20 20 0D 0A 00-49 4F 20 20 20 20 20 20 a IO

177C02E0 53 59 53 4D 53 44 4F 53-20 20 20 53 59 53 80 01 SYSMSDOS SYS

177C02F0 00 57 49 4E 42 4F 4F 54-20 53 59 53 00 00 55 AA WINBOOT SYSU

-

-Q

FIN [1] En las primeras versiones de MS-DOS era un modesto programita DEBUGCOM de apenas 16 KB La versioacuten que acompantildea a Windows98 es ya un ejecutable en formato EXE de 21 KB [2] En realidad DEBUG es una utilidad de enorme potencia que requeririacutea todo un libro para ella sola Puede encontrarse una amplia descripcioacuten de esta herramienta en el libro de Paul Somerson PC Magazine DOS Powers Tools [3] Desgraciadamente no hay una convencioacuten estaacutendar sobre la colocacioacuten de los datos en la BIOS de forma que cada fabricante sigue sus propias reglas y es imposible por tanto utilizarla para cualquier tipo de identificacioacuten del sistema [4] En palabras del mencionado Paul Somerson Desgraciadamente debido a que DEBUG es un programa tan increiacuteblemente potente tambieacuten es increiacuteblemente peligroso Hay un dicho que afirma que El software no puede destruir el hardware Desgraciadamente esto no es cierto Ademaacutes de enviar mecanismos sensibles de la unidad de disco a tierra de nadie es posible hacer saltar monitores o transformadores Repito si sigue al pie de la letra las instrucciones y hace caso a todos los avisos todo iraacute bien [5] Recuerde que la imagen de un ejecutable exe cargado en memoria es distinta de su imagen en disco Solo en los ejecutables com la imagen en disco es una imagen exacta de su disposicioacuten en memoria [6] Es evidente que un pequentildeo error de nuacutemero en este paraacutemetro puede acarrear consecuencias nefastas Por ejemplo si cree que estaacute jugando con el disquete e inadvertidamente se dirige al disco duro (relea la nota [4])

Page 6: El Comando DEBUG

Ensamblar A [direccioacuten] Comparar C direccioacuten de intervalo Volcar D [intervalo] Escribir E direccioacuten [lista de valores] Llenar F lista de intervalos Ir G [=direccioacuten] [direcciones] Hex H valor1 valor2 Entrada I puerto Cargar L [direccioacuten] [unidad] [primer_sector] [nuacutemero] Mover M direccioacuten de intervalo Nombre N [nombre_ruta] [lista_argumentos] Salida O byte de puerto Proceder P [=direccioacuten] [nuacutemero] Salir Q Registro R [registro] Buscar S lista de intervalos Seguimiento T [=direccioacuten] [valor] Desensamblar U [intervalo] Escribir W [direccioacuten] [unidad] [primer_sector] [nuacutemero] Asignar memoria expandida XA [paacuteginas] Desasignar memoria expandida XD [identificador] Asignar paacuteginas de memoria expandida XM [Lpaacutegina] [Ppaacutegina] [identificador] Mostrar estado de la memoria expandida XS

En particular obseacutervese 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 EJEMPLOCOM entonces carga a EJEMPLOCOM en memoria a partir de la direccioacuten 0100h

Comandos del DEBUG D DUMP D ltdireccioacuten1gt ltdireccioacuten2gt Muestra el contenido de una zona de memoria en hexadecimal y en ASCII Sin paraacutemetros muestra los primeros 128 bytes a partir de la posicioacuten a la que se llegoacute en el uacuteltimo d Si se le da un rango mostraraacute ese rango Ambas direcciones son opcionales La 1ra es la direccioacuten de inicio de despliegue la 2da es la direccioacuten de fin Ejemplo

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

E EDIT E ltdireccioacutengtltlistagt Permite editar byte por byte una zona de memoria Muestra -en hexadecimal- el byte de esa posicioacuten 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 siacute se ha hecho Para terminar la edicioacuten se pulsa INTRO Los cambios pueden ser especificados en la liacutenea de comandos en cualquier combinacioacuten de nuacutemeros hexadecimales o caracteres ASCII los caracteres ASCII deben estar entre comillas simples o dobles Por ejemplo E 100 Benjamin Iglesiasrsquo Establece el patroacuten 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 ltlistagt se entra en un modo especial en el que DEBUG despliega los valores de ltdireccioacutengt 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 ltregistrogt Sin paraacutemetros muestra el contenido de los registros de la CPU asiacute como la proacutexima instruccioacuten a ejecutarR [REGISTRO] muestra el contenido del registro especificado y cambia

el prompt de - a invitando a que se cambie su valor Pulsando Enter sin maacutes lo deja como estaba Ejemplo R ltregistrogt Donde ltregistrogt 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 sinoacutenimos A ASSEMBLE A ltdireccioacutengt Sin paraacutemetros ensambla las instrucciones que se introduzcan guardaacutendolas en la direccioacuten siguiente a la que se llegoacute en el uacuteltimo a Cuando se utiliza este comando se le puede dar como paraacutemetro la direccioacuten donde se desea que se inicie el ensamblado si se omite el paraacutemetro el ensamblado se iniciaraacute en la localizacioacuten especificada por CSIP usualmente 0100H que es la localizacioacuten donde deben iniciar los programas con extensioacuten COM y seraacute la localizacioacuten que utilizaremos debido a que DEBUG solo puede crear este tipo especiacutefico de programas La sintaxis es A ltdireccioacutengt Praacutecticamente cualquier mnemoteacutecnico es soportado por DEBUG incluyendo los especificadores de override de segmento (CS DS ES SS) Una excepcioacuten 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 instruccioacuten MOV que como veremos maacutes adelante sirve para copiar datos de la memoria a los registros y viceversa ademaacutes de copiar datos entre registros que es justo lo que vamos a usar en el ejemplo -a 20480106 mov axbx 20480108 mov bxcx 2048010A ltRETgt -u 106 108 20480106 89D8 MOV AXBX 20480108 89CB MOV BXCX Como veremos maacutes adelante la instruccioacuten U sirve para hacer volcados de memoria pero no viendo el contenido de la misma sino interpretaacutendola como instrucciones en lenguaje ensamblador Ejemplo 2 -r cs CS 2048 2050 -a 200 20500200 mov axbx 20500202 ltRETgt -u 200 200 20500200 89D8 MOV AXBX

F FILL F ltbloquegt ltvalor de rellenogt Este comando llena un bloque de memoria con un valor especiacutefico o una serie de valores La sintaxis es F ltbloquegt ltvalor de rellenogt ltbloquegt es la direccioacuten de inicio y final o si se preceden con L la direccioacuten de inicio y la longitud del bloque ltvalor de rellenogt es(son) el(los) valor(es) con los que debe de llenarse el bloque Si ltvalor de rellenogt 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 liacuteneas llena (con 0rsquos) el bloque DS00FF F DS0000 DS00FF 0 DS0000 LFF 0 Ejemplo -f 100 105 66 -d 100 105 20480100 66 66 66 66 66 66 ffffff Q QUIT Q Salir de DEBUG y volver al DOS P PROCEED P lt=direccioacutengtltnuacutemerogt Similar al comando T pero al encontrarse un CALL o INT lo ejecuta de golpe sin entrar en su interior (ojo iexclesto uacuteltimo falla al tracear sobre memoria ROM) Trace puede ser incoacutemodo si no se quiere depurar el coacutedigo de las rutinas de interrupcioacuten o si ya se sabe el coacutedigo que hay en las subrutinas y tan soacutelo interesa seguir avanzando sin entrar en ellas En estos casos se usa p por lo que si ejecutamos una interrupcioacuten de MS-DOS no sabriacuteamos 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 20480107 3D5000 CMP AX0050 -a 100 20480100 mov ax0200 20480103 mov dl61 20480105 int 21 20480107 -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 20480103 B261 MOV DL61 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 20480105 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 20480107 3D5000 CMP AX0050 T TRACE T lt=direccioacutengt ltvalorgt Ejecuta una instruccioacuten del programa (a partir de CSIP) mostrando a continuacioacuten el estado de los registros y la siguiente instruccioacuten Ejecutar T10 equivaldriacutea a ejecutar 16 veces el comando T Si la instruccioacuten es CALL o INT se ejecutaraacute como tal introducieacutendose 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 20480100 3D0000 CMP AX0000 -r bx BX 0000 2 -a 100 20480100 mov axbx 20480102 -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 20480102 00AC01D8 ADD [SI+D801]CH DSD801=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 20480100 3D0000 CMP AX0000 -a 100 20480100 mov axbx 20480102 mov cxbx 20480104 -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 20480102 89D9 MOV CXBX 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 20480104 01D8 ADD AXBX

N NAME N ltnombre_archivogt Se asigna un nombre al programa que estaacute siendo creado o modificado Se puede indicar la trayectoria de directorios L LOAD L ltbuffergt ltnumdiscogt ltsectorinigt ltnumsectorgt ltbuffergt es la direccioacuten en donde se carga la informacioacuten ltnumdiscogt es el nuacutemero (opcional) del disco de donde se leeraacute la informacioacuten (0=A 1=B 2=C etc) ltsectorinigt es el sector de disco absoluto (en hexadecimal) a leer ltnumsectorgt es la cantidad de sectores a leer No se pueden leer maacutes de 80H (128) sectores Si no se suministra la combinacioacuten ltnumdiscogt ltsectorinigt ltnumsectorgt DEBUG presume que se desea leer un archivo En este caso ltbuffergt es opcional Debe usarse el comando N (ver maacutes adelante) para especificar el archivo a leer Eacuteste se carga en CS0100 Ejemplo Se va a leer el sector 0 del disco A y se vuelca a partir de la direccioacuten DS100 como se puede observar el disco contiene mucha informacioacuten ( ESTO NO QUIERE DECIR QUE TENGA QUE SALIR LO MISMO EN SU VOLCADO )

l 100 0 0 1 -d 100 300

W WRITE W ltdireccioacutengt Graba el contenido de una zona de memoria a disco Si no se indica la direccioacuten se graba desde CS100h hasta CS100h+nuacutemero_bytes el nuacutemero de bytes se indica en BXCX (no es una direccioacuten segmentada sino un valor de 32 bits) Si se trata de un EXE no se permitiraacute grabarlo (para modificarlos hay que renombrarles para cambiarles la extensioacuten aunque de esta manera no seraacuten montados al cargarlos) La sintaxis es W ltbuffergt ltnumdiscogt ltsectorinigt ltnumsectorgt ltbuffergt es la direccioacuten de donde se carga la informacioacuten ltnumdiscogt es el nuacutemero (opcional) del disco en donde se escribiraacute la informacioacuten (0=A 1=B 2=C etc) ltsectorinigt es el sector de disco absoluto (en hexadecimal) en donde empieza la escritura ltnumsectorgt es la cantidad de sectores a leer No se pueden escribir maacutes de 80H (128) sectores Si no se suministra la combinacioacuten ltnumdiscogt ltsectorinigt ltnumsectorgt DEBUG presume que el inicio de archivo es CS100 En este caso ltbuffergt es opcional Debe usarse el comando N (ver arriba) para especificar el archivo a escribir Antes de escribir BXCX debe ajustarse al nuacutemero de bytes que desean grabarse W no puede escribir a archivos con la extensioacuten EXE o HEX [5] Ejemplo

N ltnomarchivogt BXCX lt--- 2000 W

S SEARCH S ltrangogt ltlistagt Busca una cadena de bytes por la memoria Para buscar la cadena PEPE terminada por cero en un aacuterea de 512 bytes desde DS100 se hariacutea S 100 L 200 PEPE0 (por defecto se busca en DS) No se encontrariacutea sin embargo pepe (en minuacutesculas) C COMPARE C ltrangogt ltdireccioacutengt Compara dos zonas de memoria mostrando las diferencias Por ejemplo para comparar 5 bytes de DS100 y DS200 se hace C 100 L 5 200 M MOVE M ltrangogt ltdireccioacutengt Maacutes que mover copia una zona de memoria en otra de manera inteligente (controlando los posibles solapamientos de los bloques) I INPUT I ltpuertogt Visualiza la lectura del puerto de ES indicado

O OUTPUT O ltpuertogt ltvalorgt Enviacutea un valor a un puerto de ES H HEX H ltvalor1gt ltvalor2gt Muestra la suma y resta de valor1 y valor2 ambos operandos de un maacuteximo de 16 bits (si hay desbordamiento se trunca el resultado que tampoco excede los 16 bits) Resultado ltresultado_1gt Es la suma ( ltvalor1gt + ltvalor2gt) ltresultado_2gt es la resta (ltvalor1gt - ltvalor2gt ) Ejemplo -h 0003 0002 0005 0001 -h 0000 0001 0001 FFFF como se observa el resultado de la segunda operacioacuten es FFFF que es el equivalente en complemento a 2 de -1 G GO G =ltiniciogt ltquiebre1gt ltquiebre2gt ltquiebre10gt Este comando ejecuta el coacutedigo en memoria Si se estaacute depurando un programa permite ejecutar el coacutedigo cargado en memoria Tambieacuten permite establecer puntos de quiebre (breakpoints) que son direcciones en las que se detiene la ejecucioacuten del programa La sintaxis es G =ltiniciogt ltquiebre1gt ltquiebre2gt ltquiebre10gt ltiniciogt es la direccioacuten de inicio de ejecucioacuten ltquiebre1gt hasta ltquiebre10gt son direcciones opcionales de paro del programa Si no se especifica ltiniciogt Go inicia con la direccioacuten contenida en CSIP Para lograr los quiebres DEBUG reemplaza el coacutedigo en las direcciones de quiebre por el valor hexadecimal CC que es el coacutedigo de interrupcioacuten Si DEBUG llega a CC todos los puntos de quiebre son restituidos los registros se despliegan (como con el comando R [veacutease adelante]) y se para la ejecucioacuten U UNASSEMBLE U ltrangogt Este comando desensambla el contenido de la memoria a partir de la posicioacuten actual Registros y Banderas del DEBUG La mayoriacutea de los comandos de DEBUG ejecutan una accioacuten y vuelven al indicador del shell pero si es un comando largo como puede ser mostrar un trozo grande de coacutedigo puede detenerse pulsando CTRL-Pausa o interrumpirse con CTRL-C para volver al shell Por ejemplo al teclear lo siguiente

- r [Enter]

-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 17A70100 E8CD0F CALL 10D0 - Se desplegaran todos los contenidos de los registros internos del microprocesador una forma alternativa de mostrarlos es usar el comando r utilizando como paraacutemetro el nombre del registro cuyo valor se quiera visualizar Por ejemplo

- r bx Esta instruccioacuten desplegaraacute uacutenicamente el contenido del registro BX y cambia el indicador del DEBUG de - a Estando asiacute el prompt es posible cambiar el valor del registro que se visualizoacute tecleando el nuevo valor y a continuacioacuten [Enter] o se puede dejar el valor anterior presionando [Enter] sin teclear ninguacuten valor Es posible cambiar el valor del registro de banderas asiacute como utilizarlo como estructura de control en nuestros programas como se veraacute maacutes adelante Cada bit del registro tiene un nombre y significado especial la lista dada a continuacioacuten describe el valor de cada bit tanto apagado como prendido y su relacioacuten con las operaciones del microprocesador

Overflow (O) NV = no hay desbordamiento OV = si lo hay Direction (D) UP = hacia adelante DN = hacia atraacutes Interrupts (I) DI = desactivadas EI = activadas Sign (S) PL = positivo NG = negativo Zero (Z) NZ = no es cero ZR = s lo es Auxiliary Carry (A) NA = no hay acarreo auxiliar

AC = hay acarreo auxiliar Parity (P) PO = paridad non PE = paridad par Carry (C) NC = no hay acarreo CY = Si lo hay

La estructura del ensamblador En el lenguaje ensamblador las liacuteneas de coacutedigo constan de dos partes la primera es el nombre de la instruccioacuten que se va a ejecutar y la segunda son los paraacutemetros del comando u operandos Por ejemplo

add ahbh Aquiacute add es el comando a ejecutar (en este caso una adicioacuten) y tanto ah como bh son los paraacutemetros El nombre de las instrucciones en este lenguaje estaacute formado por dos tres o cuatro letras a estas instrucciones tambieacuten se les llama nombres mnemoacutenicos o coacutedigos de operacioacuten ya que representan alguna funcioacuten que habraacute de realizar el microprocesador Existen algunos comandos que no requieren paraacutemetros para su operacioacuten asiacute como otros que requieren solo un paraacutemetro Algunas veces se utilizaraacuten las instrucciones como sigue

add al[170] Los corchetes en el segundo paraacutemetro nos indican que vamos a trabajar con el contenido de la posicioacuten de memoria nuacutemero 170 y no con el valor 170 a esto se le conoce como direccionamiento directo Primer programa en ensamblador con el DEBUG Vamos a crear un programa que sirva para ilustrar lo que hemos estado viendo lo que haremos seraacute una suma de dos valores que introduciremos directamente en el programa El primer paso es iniciar el DEBUG este paso consiste uacutenicamente en teclear DEBUG [Enter] en el prompt del sistema operativo Para ensamblar un programa en el DEBUG se utiliza el comando a (assemble) cuando se utiliza este comando se le puede dar como paraacutemetro la direccioacuten donde se desea que se inicie el ensamblado Si se omite el paraacutemetro el ensamblado se iniciaraacute en la localidad especificada por CSIP usualmente 0100H que es la localidad donde deben iniciar los programas con extensioacuten COM y seraacute la localidad que utilizaremos debido a que DEBUG solo puede crear este tipo especiacutefico de programas

Aunque en este momento no es necesario darle un paraacutemetro al comando a es recomendable hacerlo para evitar problemas una vez que se haga uso de los registros CSIP por lo tanto tecleamos

- a 100 [Enter] Al hacer esto apareceraacute en la pantalla algo como 0C1B0100 y el cursor se posiciona a la derecha de estos nuacutemeros noacutetese que los primeros cuatro diacutegitos (en sistema hexadecimal) pueden ser diferentes pero los uacuteltimos cuatro deben ser 0100 ya que es la direccioacuten que indicamos como inicio Ahora podemos introducir las instrucciones

0C1B0100 mov ax0002 coloca el valor 0002 en el registro ax 0C1B0103 mov bx0004 coloca el valor 0004 en el registro bx 0C1B0106 add axbx le adiciona al contenido de ax el contenido de bx 0C1B0108 int 20 provoca la terminacioacuten del programa 0C1B010A

No es necesario escribir los comentarios que van despueacutes del Una vez escrito el uacuteltimo comando int 20 se le da [Enter] sin escribir nada maacutes para volver al prompt del DEBUG La uacuteltima liacutenea escrita no es propiamente una instruccioacuten de ensamblador es una llamada a una interrupcioacuten del sistema operativo estas interrupciones seraacuten tratadas maacutes a fondo en un capiacutetulo posterior por el momento solo es necesario saber que nos ahorran un gran nuacutemero de liacuteneas y son muy uacutetiles para accesar a funciones del sistema operativo Para ejecutar el programa que escribimos se utiliza el comando g al utilizarlo veremos que aparece un mensaje que dice Program terminated normally Naturalmente con un mensaje como eacuteste no podemos estar seguros que el programa haya hecho la suma pero existe una forma sencilla de verificarlo utilizando el comando r del DEBUG podemos ver los contenidos de todos los registros del microprocesador simplemente teclee

- r [Enter] Apareceraacute en pantalla cada registro con su respectivo valor actual -R AX=0006 BX=0004 CX=0000 DX=0000 SP=FFFE BP=0000 SI=0000 DI=0000 DS=0C1B ES=0C1B SS=0C1B CS=0C1B IP=010A NV UP EI PL NZ NA PO NC 17A70100 E8CD0F CALL 10D0 - Existe la posibilidad de que los registros contengan valores diferentes pero AX y BX deben ser los mismos ya que son los que acabamos de modificar Otra forma de ver los valores mientras se ejecuta el programa es utilizando como paraacutemetro para g la direccioacuten donde queremos que termine la ejecucioacuten y muestre los valores de los registros en este caso seraacute g108 esta instruccioacuten ejecuta el programa se detiene en la direccioacuten 108 y muestra los contenidos de los registros Tambieacuten se puede llevar un seguimiento de lo que pasa en los registros utilizando el comando t (trace) la funcioacuten de este comando es ejecutar liacutenea por liacutenea lo que se ensambloacute mostrando cada vez los contenidos de los registros Para salir del DEBUG se utiliza el comando q (quit)

Guardar y cargar los programas No seriacutea praacutectico tener que escribir todo un programa cada vez que se necesite para evitar eso es posible guardar un programa en el disco con la enorme ventaja de que ya ensamblado no seraacute necesario correr de nuevo DEBUG para ejecutarlo ya que cuando el DEBUG guardo nuestro programa en el disco eacuteste se guardo en binario (archivo con la extensioacuten com) Los pasos a seguir para guardar un programa ya almacenado en la memoria son

Obtener la longitud del programa restando la direccioacuten final de la direccioacuten inicial naturalmente en sistema hexadecimal

Darle un nombre al programa y una extensioacuten

Poner la longitud del programa en el registro CX

Ordenar a DEBUG que escriba el programa en el disco Utilizando como ejemplo el programa del ejemplo anterior tendremos una idea maacutes clara de coacutemo llevar estos pasos Al terminar de ensamblar el programa se veriacutea asiacute

0C1B0100 mov ax0002 0C1B0103 mov bx0004 0C1B0106 add axbx 0C1B0108 int 20 0C1B010A

Para almacenarlo en el disco hacemos lo siguiente - h 10a 100 020a 000a - n pruebacom - r cx CX 0000 000a -w Writing 000A bytes

Para obtener la longitud de un programa se utiliza el comando h el cual nos muestra la suma y resta de dos nuacutemeros en hexadecimal Para obtener la longitud del programa le proporcionamos como paraacutemetros el valor de la direccioacuten final de nuestro programa (10A) y el valor de la direccioacuten inicial (0100) El primer resultado que nos muestra el comando es la suma de los paraacutemetros y el segundo es la resta El comando n nos permite poner un nombre al programa El comando r cx nos permite cambiar el contenido del registro CX al valor que obtuvimos del tamantildeo del archivo con h en este caso 000a ya que nos interesa el resultado de la resta de la direccioacuten inicial a la direccioacuten final

Por uacuteltimo el comando w escribe nuestro programa en el disco indicaacutendonos cuantos bytes escribioacute

NOTA Si se trabaja en una ventana de DOS de Windows Vista o 7 es probable que al momento de guardar su programa el DEBUG escriba mas coacutedigo que el sentildealado por el registro CX por consiguiente seraacute necesario limpiar el registro BX esto es ponerlo a ceros y despueacutes utilizar el comando w Por ejemplo _r bx BX 000E 0000 w

Para cargar un archivo ya guardado son necesarios dos pasos

Proporcionar el nombre del archivo que se cargaraacute a memoria

Cargarlo utilizando el comando l (load) Para obtener el resultado correcto de los siguientes pasos es necesario que previamente se haya creado el programa anterior Dentro del DEBUG escribimos lo siguiente

- n pruebacom - l - u 100 109 0C3D0100 B80200 MOV AX0002 0C3D0103 BB0400 MOV BX0004 0C3D0106 01D8 ADD AXBX 0C3D0108 CD20 INT 20

El uacuteltimo comando u se utiliza para verificar que el programa se cargoacute en memoria lo que hace es desensamblar el coacutedigo y mostrarlo ya desensamblado Los paraacutemetros le indican a DEBUG desde donde y hasta donde desensamblar DEBUG siempre carga los programas en memoria en la direccioacuten 100H a menos que se le indique alguna otra Un programa que realiza un conteo en pantalla Con el DEBUG es posible escribir un programa que realice un conteo en pantalla por razones de comprensioacuten nuestro programa solo realizara un conteo de 9 a 0 (conteo descendente) 0B3B0100 B90A00 MOV CX000A CX=10 en decimal 0B3B0103 88CA MOV DLCL 0B3B0105 80C22F ADD DL2F sumamos 02Fh a DL 0B3B0108 B402 MOV AH02 funcioacuten 02 de INT 21 para imprimir un caracter 0B3B010A CD21 INT 21

0B3B010C E2F5 LOOP 0103 CX=0 Si no salta a 0103 0B3B010E CD20 INT 20 termina el programa En la liacutenea 0103 se puede observar que el valor del registro CX en su parte baja (en CL) se almacena en el registro DL Si se omitiera la liacutenea 0105 entonces cuando se ejecutara la liacutenea 010A solo se imprimiriacutea en pantalla el coacutedigo ASCII del valor que contenga DL (el coacutedigo ASCII de 0Ah que es 10 en decimal es un caraacutecter especial no imprimible) Para conseguir el ldquoefectordquo de que el programa realiza el conteo en decimal se hace un corrimiento de 02F (47 en decimal) Por ejemplo cuando se ejecuta la liacutenea 0105 DL tendriacutea el valor de 39h=57d (02Fh+0Ah=39h=57d) y el coacutedigo ASCII de 57d es el caraacutecter ldquo9rdquo El sentencia LOOP decrementa CX en 1 si CX es diferente a 0 salta a la liacutenea 0103 El proceso se repite y el programa imprime en pantalla 9876543210 Seriacutea interesante que el programa anterior fuera modificado para que la numeracioacuten se imprimiera de la siguiente manera 9 8 7 6 5 4 3 2 1 0

NOTA Como se dijo anteriormente cuando el DEBUG almacena un programa en el disco este archivo se graba en binario esto es en ejecutable Por lo tanto no es necesario cargar el DEBUG para volver a ejecutar nuestro programa sino que se hace de manera directa desde DOS El problema surge cuando al ejecutar nuestro programa el resultado no se puede observar porque el DOS borra la pantalla despueacutes de terminar de ejecutar el programa Para evitar el borrado automaacutetico seraacute necesario agregarle a nuestro programa antes de la INT 20h una instruccioacuten para la lectura de un caraacutecter desde el teclado Para tal efecto utilizaremos la funcioacuten 08 de la INT 21h (un buen truco para que el programa haga una pausa) asiacute el programa esperara hasta que el usuario presiona una tecla permitiendo observar el resultado Ejemplo mov ah08 Int 21 Int 20

Condiciones ciclos y bifurcaciones Estas estructuras o formas de control le dan a la maacutequina un cierto grado de decisioacuten basado en la informacioacuten que recibe La forma maacutes sencilla de comprender este tema es por medio de ejemplos Vamos a crear tres programas que hagan lo mismo desplegar un nuacutemero determinado de veces una cadena de caracteres en la pantalla

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV CX000F veces que se desplegara la cadena 0C1B0128 MOV DX0102 copia cadena al registro DX 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F LOOP 012D si CXgt0 salta a 012D 0C1B0131 INT 20 termina el programa

Por medio del comando e es posible introducir una cadena de caracteres en una determinada localidad de memoria dada como paraacutemetro la cadena se introduce entre comillas le sigue un espacio luego el valor hexadecimal del retorno de carro un espacio el valor de liacutenea nueva y por uacuteltimo el siacutembolo $ que el ensamblador interpreta como final de la cadena La interrupcioacuten 21 utiliza el valor almacenado en el registro AH para ejecutar una determinada funcioacuten en este caso mostrar la cadena en pantalla la cadena que muestra es la que estaacute almacenada en el registro DX La instruccioacuten LOOP decrementa automaacuteticamente el registro CX en uno y si no ha llegado el valor de este registro a cero salta a la posicioacuten de memoria indicada como paraacutemetro lo cual crea un ciclo que se repite el nuacutemero de veces especificado por el valor de CX La interrupcioacuten 20 termina la ejecucioacuten del programa Otra forma de realizar la misma funcioacuten pero sin utilizar el comando LOOP es la siguiente

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV BX000F veces que se desplegara la cadena 0C1B0128 MOV DX0102 copia cadena al registro DX 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F DEC BX decrementa en 1 a BX 0C1B0130 JNZ 012D si BX es diferente a 0 salta a 012D 0C1B0132 INT 20 termina el programa

En este caso se utiliza el registro BX como contador para el programa y por medio de la instruccioacuten DEC se disminuye su valor en 1 La instruccioacuten JNZ verifica si el valor de BX es diferente a 0 esto con base en la bandera NZ en caso afirmativo salta hacia la direccioacuten 012D En caso contrario continuacutea la ejecucioacuten normal del programa y por lo tanto se termina Una uacuteltima variante del programa es utilizando de nuevo a CX como contador pero en lugar de utilizar LOOP utilizaremos decrementos a CX y comparacioacuten de CX a 0

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV DX0102 copia cadena al registro DX 0C1B0128 MOV CX000F veces que se desplegara la cadena 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F DEC CX decrementa en 1 a CX 0C1B0130 JCXZ 0134 si CX es igual a 0 salta a 0134 0C1B0132 JMP 012D salta a la direccioacuten 012D 0C1B0134 INT 20 termina el programa

En este ejemplo se usoacute la instruccioacuten JCXZ para controlar la condicioacuten de salto el significado de tal funcioacuten es salta si CX=0 El tipo de control a utilizar dependeraacute de las necesidades de programacioacuten en determinado momento

Manipulacioacuten de Posiciones de Memoria Con el DEBUG es posible almacenar y recuperar datos numeacutericos en memoria por medio de un programa a traveacutes de los registros del microprocesador Por ejemplo el siguiente programa almacena previamente dos valores numeacutericos en la posicioacuten 0300h y 0400h respectivamente despueacutes el programa los recupera realiza la operacioacuten de suma con esos valores y el resultado lo almacena en la posicioacuten 0500h -a 100 0B1C0100 mov ax0002 ax=2 0B1C0103 mov [0300]ax almacenamos 2 en la direccioacuten 0300h 0B1C0106 mov ax0004 ax=4 0B1C0109 mov [0400]ax almacenamos 4 en la direccioacuten 0400h 0B1C010C mov ax[0300] recuperamos el dato1 en AX 0B1C010F mov bx[0400] recuperamos el dato2 en BX 0B1C0113 add axbx hacemos la operacioacuten de suma en AX 0B1C0115 mov [0500]ax almacenamos el 6 en la direccioacuten 0500h 0B1C0118 int 21 0B1C011A - Un nuacutemero entre corchetes [numero_hex] indica una posicioacuten de memoria y su manejo se hace a traveacutes de registros ya que no es posible almacenar valores numeacutericos de manera directa Ejecutamos el programa -g 118 AX=0006 BX=0004 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=0B1C ES=0B1C SS=0B1C CS=0B1C IP=0118 NV UP EI PL NZ NA PE NC 0B1C0118 CD21 INT 21 - Para ver si el resultado se almaceno en la direccioacuten correcta hacemos

Como se puede observar en la direccioacuten 0B1C0500 se encuentra el 06 y en 0B1C0501 se encuentra el 00 que es el resultado de la operacioacuten 2+4 Perohellip Porque aparece el 06 y despueacutes el 00 pareceriacutea que el resultado fue de 0600 pero no es asiacute lo que sucedes que los datos se almacenan en memoria de la siguiente manera

Como se hizo la operacioacuten AX=AX+BX entonces el resultado es de 16 bits (dos bytes) AX=6 entonces AX=0000 0000 0000 0110 (16 bits) por lo tanto los 8 bits de menor peso de AX son 0000 0110 y deben almacenarse en la direccioacuten 0500 y en la direccioacuten 0501 se almacena 0000 0000

0 0 0 0 0 1 1 0 0500

0 0 0 0 0 0 0 0 0501

x x x x x x x x 0502

x x x x x x x x 0503

x x x x x x x x 0504

x x x x x x x x 0505

Interrupciones Definicioacuten de interrupcioacuten

Una interrupcioacuten es una instruccioacuten que detiene la ejecucioacuten de un programa para permitir el uso del microprocesador en un proceso prioritario Una vez concluido este uacuteltimo proceso se devuelve el control a la aplicacioacuten anterior

Por ejemplo cuando estamos trabajando con un procesador de palabras y en ese momento llega un aviso de uno de los puertos de comunicaciones se detiene temporalmente la aplicacioacuten que estaacutebamos utilizando para permitir el uso del microprocesador al manejo de la informacioacuten que estaacute llegando en ese momento Una vez terminada la transferencia de informacioacuten se reanudan las funciones normales del procesador de palabras Las interrupciones ocurren muy seguido sencillamente la interrupcioacuten que actualiza la hora del diacutea ocurre aproximadamente 18 veces por segundo Para lograr administrar todas estas interrupciones la computadora cuenta con un espacio de memoria llamado memoria baja donde se almacenan las direcciones de cierta localidad de memoria donde se encuentran un juego de instrucciones que el microprocesador ejecutaraacute para despueacutes regresar a la aplicacioacuten que estaba en proceso En los programas anteriores hicimos uso de la interrupcioacuten nuacutemero 20H para terminar la ejecucioacuten de nuestros programas y en otros ejemplos utilizamos otra interrupcioacuten para mostrar informacioacuten en pantalla (INT 21h) Utilizando DEBUG tecleamos

- a100 2C1B0100 JMP 011D 2C1B0102 [ENTER] - E 102 Hola como estas 0D 0A $ - A011D 2C1B011D MOV DX0102 2C1B0120 MOV AH09 2C1B0122 INT 21 2C1B0123 INT 20

Orden

creciente

de la

memoria

En este programa la interrupcioacuten 21h manda al monitor la cadena localizada en la direccioacuten a la que apunta el registro DX El valor que se le da a AH determina cual de las opciones de la interrupcioacuten 21h seraacute utilizada ya que esta interrupcioacuten cuenta con varias opciones El manejo directo de interrupciones es una de las partes maacutes fuertes del lenguaje ensamblador ya que con ellas es posible controlar eficientemente todos los dispositivos internos y externos de una computadora gracias al completo control que se tiene sobre operaciones de entrada y salida Maacutes del DEBUG Una caracteriacutestica poco conocida es que DEBUG puede aceptar entradas desde un archivo Script que puede ser un simple archivo de texto ASCII en el que cada comando esteacute separado del anterior por un INTRO Despueacutes del uacuteltimo que debe ser una Q para salir de DEBUG es conveniente dejar una liacutenea en blanco pulsando INTRO dos veces Las liacuteneas pueden contener comentarios Cualquier cosa a partir del caracter punto y coma () hasta el final de la liacutenea seraacute ignorado esto es un comentario D aquiacute se mostraraacute algo Suponiendo que tengamos un archivo Script de nombre Ordenestxt puede ser utilizado como entrada para DEBUG mediante un comando de redireccioacuten en la siguiente forma DEBUG lt ordenestxt Tambieacuten puede conseguirse que el programa redireccione la salida hacia un archivo que puede ser inspeccionado maacutes 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 podriacutea obtenerse un archivo Resulttxt con el siguiente comando DEBUG lt ordenestxt gt Resulttxt Errores Cuando DEBUG no sabe interpretar un comando muestra un mensaje de error y un indicador ^ debajo del sitio del comando donde estaacute el error Entradas y Salidas DEBUG asume que los datos numeacutericos proporcionados son hexadecimales y cuando se trate de direcciones de memoria deben introducirse en forma segmentada A su vez los resultados son mostrados tambieacuten 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

Cada fila muestra 16 posiciones de memoria a partir de la posicioacuten sentildealada por las columnas de la izquierda que las muestran como segmentodesplazamiento El bloque central muestra el contenido hexadecimal de cada byte mientras que el bloque derecho contiene la representacioacuten ASCII Por ejemplo la 3ra fila muestra el contenido de las posiciones 0B770120 a 0B77012F (ambas inclusive) Sus tres uacuteltimos bytes contienen respectivamente los caracteres r 9 y 2 que corresponden a las cantidades 72h 39h y 32h del bloque central Que como sabemos equivalen a los decimales 114 57 y 50 que son precisamente los valores ASCII de los caracteres ldquorrdquo ldquo9rdquo y ldquo2rdquo anteriormente mencionados

Nota Por razoacuten de que eacuteste tipo de salida pueda ser listado a impresora el bloque derecho no contiene en realidad la representacioacuten ASCII de todos los caracteres (algunos ni siquiera tienen una representacioacuten imprimible) En realidad solo se muestran los caracteres imprimibles del primer bloque (US-ASCII) El resto estaacute 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 caraacutecter imprimible Esto no significa que dichas posiciones representen efectivamente tales valores para la aplicacioacuten que las utiliza Por ejemplo puede que en realidad las dos posiciones de memoria mencionadas (dos octetos o bytes) en vez de los caracteres ldquo5rdquo y ldquoardquo representen una palabra de 16 bits en formato Little Endian que a su vez representan una cantidad entera (un nuacutemero) Comandos Aunque su descripcioacuten completa llenariacutea todo un capiacutetulo a continuacioacuten comentamos algunas de las opciones maacutes interesantes relativas a inspeccioacuten del coacutedigo y de contenidos de memoria La opcioacuten D (Dump) permite obtener un volcado del contenido de la memoria (de DEBUG) La sintaxis acepta dos formas D [direccioacuten-inicial] [L posiciones-desde-direccioacuten-inicial ] D [direccioacuten-inicial][direccioacuten-final] Naturalmente para que exista algo en el buacutefer de memoria (al principio quizaacutes solo contiene basura) es preciso indicarle que lea algo Este algo puede ser un rango de direcciones de memoria RAM una direccioacuten absoluta de disco (sector) un archivo o el contenido de los registros del procesador Para empezar puede indicaacutersele que cargue un archivo xxxxyz que tenemos en el directorio actual o en el PATH cuyo contenido queremos ver Cgt DEBUG xxxxyz -D aquiacute se obtendriacutea una salida anaacuteloga a la comentada

Hemos visto un ejemplo al tratar de los servicios de interrupciones del PC aquiacute mostraremos otro Sabemos que el punto de inicio de la BIOS es la direccioacuten F000FFF0 y que desde eacutesta posicioacuten hasta el final de la memoria DOS hay 16 bytes Puede obtenerse un volcado de estas posiciones con el siguiente comando -D F000FFF0 La salida en un equipo puede ser F000FFF0 CD 19 E0 00 F0 30 36 2F-33 30 2F 39 37 00 FC 38 0630978 En este caso el comando solo muestra una liacutenea porque ha alcanzado el final de la memoria Puede verse que la fecha de la BIOS del sistema ocupa las uacuteltimas posiciones Si se ordena el volcado de una direccioacuten suficientemente alejada del final de la memoria sin indicar ninguacuten nuacutemero de posiciones por defecto se toma el valor 128 (8 filas de 16 posiciones) Si desea una cantidad distinta hay que antildeadir una L (Long) y el nuacutemero de posiciones hasta un maacuteximo de 64 KB (FFFF) Todos los nuacutemeros deben ser expresados en hexadecimal Por consiguiente los dos comandos que siguen son equivalentes (recuerde que 80 es el equivalente hexadecimal de 128) D FE000000 D FE000000 L 80 He aquiacute el resultado

Sabemos que esta zona corresponde al aacuterea de la BIOS del Sistema Otra opcioacuten muy interesante nos permite buscar determinados contenidos a traveacutes de la memoria utilizando el prefijo S (Search) Existen dos sintaxis alternativas S direccioacuten-de-inicio L longitud-a-explorar contenido-a-buscar S direccioacuten-de-inicio direccioacuten-final L contenido-a-buscar El contenido debe ser proporcionado en hexadecimal (tal como apareceriacutea en la columna central del ejemplo anterior) o entre comillas si es un texto ASCII Por ejemplo en un equipo IBM deseo ver algunas caracteriacutesticas de la BIOS Seacute que estos datos se alojan a partir de la posicioacuten F0000000 hasta el final de la memoria Es decir una longitud de 64 Kbytes (FFFF) a partir de la posicioacuten de inicio y que seguramente los datos buscados estaraacuten cerca de la identificacioacuten de la propia BIOS (la cadena IBM) Por lo que se utiliza la siguiente sintaxis [3] -s f0000000 L ffff IBM

y se obtiene la siguiente salida F000E00E F000E111 con las direcciones donde se ha encontrado la ocurrencia buscada A continuacioacuten puedo explorar las proximidades de cada posicioacuten Por ejemplo para la primera -D f000e000

Si lo que se busca estaacute en un archivo primero hay que cargarlo Lo que se puede hacer de dos formas en la propia invocacioacuten de DEBUG o mediante los comandos N y L Por ejemplo si queremos inspeccionar el contenido del archivo morecom podemos utilizar dos formas CWINDOWSgtDEBUG cwindowscommandmorecom CWINDOWSgtDEBUG - N cwindowscommandmorecom - L La sintaxis para el prefijo N es N [path-name]nombre-de-archivo En ambos casos el contenido del archivo seraacute cargado en memoria y podraacute ser utilizado Atencioacuten despueacutes de la orden L (Load) DEBUG le avisaraacute si no encuentra el archivo pero seguiraacute su funcionamiento En tal caso simplemente piensa que N sentildeala el nombre de un nuevo archivo que crearaacute con el contenido de la memoria -de DEBUG- cuando posteriormente seleccione la opcioacuten escribir W (Write)[4]

Nota Como ya habraacute deducido DEBUG permite leer un archivo realizar modificaciones en eacutel (con la opcioacuten E) y escribir el archivo modificado bajo otro nombre con NW

A continuacioacuten podemos comprobar el tamantildeo del archivo cargado Para ello usamos la opcioacuten 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 17A70100 E8CD0F CALL 10D0 -

Aquiacute nos interesa especialmente el contenido del registro CX cuyo valor 2917h (1519d) en este caso sentildeala el tamantildeo del archivo en bytes Tambieacuten podiacuteamos haber utilizado directamente el comando R CX que nos proporciona el valor de dicho registro -R CX CX 2917 -

Nota A continuacioacuten del valor correspondiente DEBUG muestra dos puntos () sentildealando que puede cambiar el valor del registro introduciendo un nuevo nuacutemero Pulse INTRO para dejar las cosas como estaacuten y volver al prompt (-) de DEBUG

Al llegar a este punto es importante sentildealar que a excepcioacuten de los archivos exe DEBUG carga los archivos a partir de la direccioacuten 100h (256d) de su memoria De forma que el primer octeto del archivo se carga en la direccioacuten 100 el segundo en 101 etc En nuestro caso el archivo se extenderaacute desde la posicioacuten 100h hasta 2A17h (100h + 2917h) A continuacioacuten para buscar la cadena Microsoft en el archivo utilizamos cualquiera de los siguientes comandos - S 100 L 2917 Microsoft - S 100 2a17 Microsoft El primer comando sentildeala el punto de inicio y el tamantildeo de la zona a buscar el segundo utiliza los puntos inicial y final de la exploracioacuten Con ambos se obtiene la misma respuesta 17A71083 17A710B2

Truco Debido a la forma especial en que se cargan los ejecutables exe si quiere inspeccionar la forma nativa de uno de estos archivos (como es su imagen en el disco) debe hacer una copia del archivo renombrarlo con cualquier otra terminacioacuten (o sin ella) y cargar esta copia En caso contrario DEBUG se prepararaacute para funcionar como un verdadero depurador de tiempo de ejecucioacuten (run-time) para lo que cargaraacute el archivo y lo acomodaraacute en memoria de forma que pueda ejecutarse [5]

Como ejercicio compruebe las distintas longitudes y aspecto (especialmente al principio) de un mismo archivo exe cargaacutendolo con DEBUG de las dos formas (busque en su sistema un exe lo maacutes pequentildeo posible) Ademaacutes de la capacidad de leer archivos antes mencionada quizaacutes una de las opciones maacutes interesantes (y peligrosas) de DEBUG es la posibilidad de leerescribir el contenido de disco a bajo nivel mediante los prefijos L (Load) y W (Write) Se utiliza la siguiente sintaxis L [Direccioacuten] [Unidad] [Primer_sector] [Nuacutemero] W [Direccioacuten] [Unidad] [Primer_sector] [Nuacutemero] El significado de los paraacutemetros es como sigue

Direccioacuten Posicioacuten de la memoria de DEBUG a partir de la cual se instalaraacuten los datos leiacutedos del disco o se tomaraacuten para el proceso de escritura (aquiacute se utiliza generalmente el valor 100h)

Unidad Valor numeacuterico que indica la loacutegica a utilizar 0 = A 1 = B 2 = C 3 = D etc [6]

Primer sector A partir del que se realizaraacute la lectura o se comenzaraacute a escribir

Nuacutemero Nuacutemero de sectores que se desea cargarescribir Como DEBUG no puede leerescribir maacutes de 64 Kbytes (2

16 = 65536) y los sectores de disco son de 512 bytes

el maacuteximo nuacutemero de sectores es 128 (80h) Asiacute pues el valor maacuteximo aquiacute es 80 Ejemplo Para obtener el contenido del sector de arranque (Master boot sector MBR) de un disquete en A utilizaremos el comando CWINDOWSgtDEBUG - L 100 0 0 1 - D 100 L 200 Como el resultado no cabe en una pantalla ingeniaremos un procedimiento para conservarlo en un archivo (maacutes adelante nos serviraacute para otro propoacutesito) Para ello creamos un archivo scripttxt con el siguiente contenido (dos INTRO despueacutes de la Q) L 100 0 0 1 D 100 L 200 Q A continuacioacuten invocamos DEBUG con el comando CWINDOWSgtDEBUG lt Dbuzonscripttxt gt Dbuzonresultadtxt Despueacutes de un breve parpadeo del disco y del disquete vuelve el prompt del DOS La operacioacuten ha concluido y en el directorio correspondiente de la unidad D tenemos el archivo resultadtxt con el volcado del sector de arranque del disquete ademaacutes de los ecos de los comandos introducidos (los hemos mantenido para orientacioacuten del lector) Otra forma de poder visualizar el contenido del Sector de Arranque del disco es utilizando el DEBUG Por ejemplo dentro del DEBUG tecleamos lo siguiente -L 100 0 0 1

-D 100 L 200

177C0100 EB 3E 90 2B 79 73 57 29-49 48 43 00 02 01 01 00 gt+ysW)IHC

177C0110 02 E0 00 40 0B F0 09 00-12 00 02 00 00 00 00 00

177C0120 00 00 00 00 00 00 29 5D-3B DD 10 4E 4F 20 4E 41 )]NO NA

177C0130 4D 45 20 20 20 20 46 41-54 31 32 20 20 20 F1 7D ME FAT12

177C0140 FA 33 C9 8E D1 BC FC 7B-16 07 BD 78 00 C5 76 00 3xv

177C0150 1E 56 16 55 BF 22 05 89-7E 00 89 4E 02 B1 0B FC VU~N

177C0160 F3 A4 06 1F BD 00 7C C6-45 FE 0F 8B 46 18 88 45 |EFE

177C0170 F9 FB 38 66 24 7C 04 CD-13 72 3C 8A 46 10 98 F7 8f$|rltF

177C0180 66 16 03 46 1C 13 56 1E-03 46 0E 13 D1 50 52 89 fFVFPR

177C0190 46 FC 89 56 FE B8 20 00-8B 76 11 F7 E6 8B 5E 0B FV v^

177C01A0 03 C3 48 F7 F3 01 46 FC-11 4E FE 5A 58 BB 00 07 HFNZX

177C01B0 8B FB B1 01 E8 94 00 72-47 38 2D 74 19 B1 0B 56 rG8-tV

177C01C0 8B 76 3E F3 A6 5E 74 4A-4E 74 0B 03 F9 83 C7 15 vgt^tJNt

177C01D0 3B FB 72 E5 EB D7 2B C9-B8 D8 7D 87 46 3E 3C D8 r+Fgtlt

177C01E0 75 99 BE 80 7D AC 98 03-F0 AC 84 C0 74 17 3C FF utlt

177C01F0 74 09 B4 0E BB 07 00 CD-10 EB EE BE 83 7D EB E5 t

177C0200 BE 81 7D EB E0 33 C0 CD-16 5E 1F 8F 04 8F 44 02 3^D

177C0210 CD 19 BE 82 7D 8B 7D 0F-83 FF 02 72 C8 8B C7 48 rH

177C0220 48 8A 4E 0D F7 E1 03 46-FC 13 56 FE BB 00 07 53 HNFVS

177C0230 B1 04 E8 16 00 5B 72 C8-81 3F 4D 5A 75 A7 81 BF [rMZu

177C0240 00 02 42 4A 75 9F EA 00-02 70 00 50 52 51 91 92 BJupPRQ

177C0250 33 D2 F7 76 18 91 F7 76-18 42 87 CA F7 76 1A 8A 3vvBv

177C0260 F2 8A 56 24 8A E8 D0 CC-D0 CC 0A CC B8 01 02 CD V$

177C0270 13 59 5A 58 72 09 40 75-01 42 03 5E 0B E2 CC C3 YZXruB^

177C0280 03 18 01 27 0D 0A 44 69-73 63 6F 20 69 6E 63 6F Disco inco

177C0290 72 72 65 63 74 6F 20 20-20 FF 0D 0A 45 72 72 6F rrecto Erro

177C02A0 72 20 45 2F 53 20 20 20-20 20 FF 0D 0A 43 61 6D r ES Cam

177C02B0 62 69 65 20 65 6C 20 64-69 73 63 6F 20 79 20 70 bie el disco y p

177C02C0 72 65 73 69 6F 6E 65 20-75 6E 61 20 74 65 63 6C resione una tecl

177C02D0 61 20 20 20 20 0D 0A 00-49 4F 20 20 20 20 20 20 a IO

177C02E0 53 59 53 4D 53 44 4F 53-20 20 20 53 59 53 80 01 SYSMSDOS SYS

177C02F0 00 57 49 4E 42 4F 4F 54-20 53 59 53 00 00 55 AA WINBOOT SYSU

-

-Q

FIN [1] En las primeras versiones de MS-DOS era un modesto programita DEBUGCOM de apenas 16 KB La versioacuten que acompantildea a Windows98 es ya un ejecutable en formato EXE de 21 KB [2] En realidad DEBUG es una utilidad de enorme potencia que requeririacutea todo un libro para ella sola Puede encontrarse una amplia descripcioacuten de esta herramienta en el libro de Paul Somerson PC Magazine DOS Powers Tools [3] Desgraciadamente no hay una convencioacuten estaacutendar sobre la colocacioacuten de los datos en la BIOS de forma que cada fabricante sigue sus propias reglas y es imposible por tanto utilizarla para cualquier tipo de identificacioacuten del sistema [4] En palabras del mencionado Paul Somerson Desgraciadamente debido a que DEBUG es un programa tan increiacuteblemente potente tambieacuten es increiacuteblemente peligroso Hay un dicho que afirma que El software no puede destruir el hardware Desgraciadamente esto no es cierto Ademaacutes de enviar mecanismos sensibles de la unidad de disco a tierra de nadie es posible hacer saltar monitores o transformadores Repito si sigue al pie de la letra las instrucciones y hace caso a todos los avisos todo iraacute bien [5] Recuerde que la imagen de un ejecutable exe cargado en memoria es distinta de su imagen en disco Solo en los ejecutables com la imagen en disco es una imagen exacta de su disposicioacuten en memoria [6] Es evidente que un pequentildeo error de nuacutemero en este paraacutemetro puede acarrear consecuencias nefastas Por ejemplo si cree que estaacute jugando con el disquete e inadvertidamente se dirige al disco duro (relea la nota [4])

Page 7: El Comando DEBUG

Comandos del DEBUG D DUMP D ltdireccioacuten1gt ltdireccioacuten2gt Muestra el contenido de una zona de memoria en hexadecimal y en ASCII Sin paraacutemetros muestra los primeros 128 bytes a partir de la posicioacuten a la que se llegoacute en el uacuteltimo d Si se le da un rango mostraraacute ese rango Ambas direcciones son opcionales La 1ra es la direccioacuten de inicio de despliegue la 2da es la direccioacuten de fin Ejemplo

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

E EDIT E ltdireccioacutengtltlistagt Permite editar byte por byte una zona de memoria Muestra -en hexadecimal- el byte de esa posicioacuten 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 siacute se ha hecho Para terminar la edicioacuten se pulsa INTRO Los cambios pueden ser especificados en la liacutenea de comandos en cualquier combinacioacuten de nuacutemeros hexadecimales o caracteres ASCII los caracteres ASCII deben estar entre comillas simples o dobles Por ejemplo E 100 Benjamin Iglesiasrsquo Establece el patroacuten 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 ltlistagt se entra en un modo especial en el que DEBUG despliega los valores de ltdireccioacutengt 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 ltregistrogt Sin paraacutemetros muestra el contenido de los registros de la CPU asiacute como la proacutexima instruccioacuten a ejecutarR [REGISTRO] muestra el contenido del registro especificado y cambia

el prompt de - a invitando a que se cambie su valor Pulsando Enter sin maacutes lo deja como estaba Ejemplo R ltregistrogt Donde ltregistrogt 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 sinoacutenimos A ASSEMBLE A ltdireccioacutengt Sin paraacutemetros ensambla las instrucciones que se introduzcan guardaacutendolas en la direccioacuten siguiente a la que se llegoacute en el uacuteltimo a Cuando se utiliza este comando se le puede dar como paraacutemetro la direccioacuten donde se desea que se inicie el ensamblado si se omite el paraacutemetro el ensamblado se iniciaraacute en la localizacioacuten especificada por CSIP usualmente 0100H que es la localizacioacuten donde deben iniciar los programas con extensioacuten COM y seraacute la localizacioacuten que utilizaremos debido a que DEBUG solo puede crear este tipo especiacutefico de programas La sintaxis es A ltdireccioacutengt Praacutecticamente cualquier mnemoteacutecnico es soportado por DEBUG incluyendo los especificadores de override de segmento (CS DS ES SS) Una excepcioacuten 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 instruccioacuten MOV que como veremos maacutes adelante sirve para copiar datos de la memoria a los registros y viceversa ademaacutes de copiar datos entre registros que es justo lo que vamos a usar en el ejemplo -a 20480106 mov axbx 20480108 mov bxcx 2048010A ltRETgt -u 106 108 20480106 89D8 MOV AXBX 20480108 89CB MOV BXCX Como veremos maacutes adelante la instruccioacuten U sirve para hacer volcados de memoria pero no viendo el contenido de la misma sino interpretaacutendola como instrucciones en lenguaje ensamblador Ejemplo 2 -r cs CS 2048 2050 -a 200 20500200 mov axbx 20500202 ltRETgt -u 200 200 20500200 89D8 MOV AXBX

F FILL F ltbloquegt ltvalor de rellenogt Este comando llena un bloque de memoria con un valor especiacutefico o una serie de valores La sintaxis es F ltbloquegt ltvalor de rellenogt ltbloquegt es la direccioacuten de inicio y final o si se preceden con L la direccioacuten de inicio y la longitud del bloque ltvalor de rellenogt es(son) el(los) valor(es) con los que debe de llenarse el bloque Si ltvalor de rellenogt 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 liacuteneas llena (con 0rsquos) el bloque DS00FF F DS0000 DS00FF 0 DS0000 LFF 0 Ejemplo -f 100 105 66 -d 100 105 20480100 66 66 66 66 66 66 ffffff Q QUIT Q Salir de DEBUG y volver al DOS P PROCEED P lt=direccioacutengtltnuacutemerogt Similar al comando T pero al encontrarse un CALL o INT lo ejecuta de golpe sin entrar en su interior (ojo iexclesto uacuteltimo falla al tracear sobre memoria ROM) Trace puede ser incoacutemodo si no se quiere depurar el coacutedigo de las rutinas de interrupcioacuten o si ya se sabe el coacutedigo que hay en las subrutinas y tan soacutelo interesa seguir avanzando sin entrar en ellas En estos casos se usa p por lo que si ejecutamos una interrupcioacuten de MS-DOS no sabriacuteamos 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 20480107 3D5000 CMP AX0050 -a 100 20480100 mov ax0200 20480103 mov dl61 20480105 int 21 20480107 -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 20480103 B261 MOV DL61 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 20480105 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 20480107 3D5000 CMP AX0050 T TRACE T lt=direccioacutengt ltvalorgt Ejecuta una instruccioacuten del programa (a partir de CSIP) mostrando a continuacioacuten el estado de los registros y la siguiente instruccioacuten Ejecutar T10 equivaldriacutea a ejecutar 16 veces el comando T Si la instruccioacuten es CALL o INT se ejecutaraacute como tal introducieacutendose 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 20480100 3D0000 CMP AX0000 -r bx BX 0000 2 -a 100 20480100 mov axbx 20480102 -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 20480102 00AC01D8 ADD [SI+D801]CH DSD801=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 20480100 3D0000 CMP AX0000 -a 100 20480100 mov axbx 20480102 mov cxbx 20480104 -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 20480102 89D9 MOV CXBX 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 20480104 01D8 ADD AXBX

N NAME N ltnombre_archivogt Se asigna un nombre al programa que estaacute siendo creado o modificado Se puede indicar la trayectoria de directorios L LOAD L ltbuffergt ltnumdiscogt ltsectorinigt ltnumsectorgt ltbuffergt es la direccioacuten en donde se carga la informacioacuten ltnumdiscogt es el nuacutemero (opcional) del disco de donde se leeraacute la informacioacuten (0=A 1=B 2=C etc) ltsectorinigt es el sector de disco absoluto (en hexadecimal) a leer ltnumsectorgt es la cantidad de sectores a leer No se pueden leer maacutes de 80H (128) sectores Si no se suministra la combinacioacuten ltnumdiscogt ltsectorinigt ltnumsectorgt DEBUG presume que se desea leer un archivo En este caso ltbuffergt es opcional Debe usarse el comando N (ver maacutes adelante) para especificar el archivo a leer Eacuteste se carga en CS0100 Ejemplo Se va a leer el sector 0 del disco A y se vuelca a partir de la direccioacuten DS100 como se puede observar el disco contiene mucha informacioacuten ( ESTO NO QUIERE DECIR QUE TENGA QUE SALIR LO MISMO EN SU VOLCADO )

l 100 0 0 1 -d 100 300

W WRITE W ltdireccioacutengt Graba el contenido de una zona de memoria a disco Si no se indica la direccioacuten se graba desde CS100h hasta CS100h+nuacutemero_bytes el nuacutemero de bytes se indica en BXCX (no es una direccioacuten segmentada sino un valor de 32 bits) Si se trata de un EXE no se permitiraacute grabarlo (para modificarlos hay que renombrarles para cambiarles la extensioacuten aunque de esta manera no seraacuten montados al cargarlos) La sintaxis es W ltbuffergt ltnumdiscogt ltsectorinigt ltnumsectorgt ltbuffergt es la direccioacuten de donde se carga la informacioacuten ltnumdiscogt es el nuacutemero (opcional) del disco en donde se escribiraacute la informacioacuten (0=A 1=B 2=C etc) ltsectorinigt es el sector de disco absoluto (en hexadecimal) en donde empieza la escritura ltnumsectorgt es la cantidad de sectores a leer No se pueden escribir maacutes de 80H (128) sectores Si no se suministra la combinacioacuten ltnumdiscogt ltsectorinigt ltnumsectorgt DEBUG presume que el inicio de archivo es CS100 En este caso ltbuffergt es opcional Debe usarse el comando N (ver arriba) para especificar el archivo a escribir Antes de escribir BXCX debe ajustarse al nuacutemero de bytes que desean grabarse W no puede escribir a archivos con la extensioacuten EXE o HEX [5] Ejemplo

N ltnomarchivogt BXCX lt--- 2000 W

S SEARCH S ltrangogt ltlistagt Busca una cadena de bytes por la memoria Para buscar la cadena PEPE terminada por cero en un aacuterea de 512 bytes desde DS100 se hariacutea S 100 L 200 PEPE0 (por defecto se busca en DS) No se encontrariacutea sin embargo pepe (en minuacutesculas) C COMPARE C ltrangogt ltdireccioacutengt Compara dos zonas de memoria mostrando las diferencias Por ejemplo para comparar 5 bytes de DS100 y DS200 se hace C 100 L 5 200 M MOVE M ltrangogt ltdireccioacutengt Maacutes que mover copia una zona de memoria en otra de manera inteligente (controlando los posibles solapamientos de los bloques) I INPUT I ltpuertogt Visualiza la lectura del puerto de ES indicado

O OUTPUT O ltpuertogt ltvalorgt Enviacutea un valor a un puerto de ES H HEX H ltvalor1gt ltvalor2gt Muestra la suma y resta de valor1 y valor2 ambos operandos de un maacuteximo de 16 bits (si hay desbordamiento se trunca el resultado que tampoco excede los 16 bits) Resultado ltresultado_1gt Es la suma ( ltvalor1gt + ltvalor2gt) ltresultado_2gt es la resta (ltvalor1gt - ltvalor2gt ) Ejemplo -h 0003 0002 0005 0001 -h 0000 0001 0001 FFFF como se observa el resultado de la segunda operacioacuten es FFFF que es el equivalente en complemento a 2 de -1 G GO G =ltiniciogt ltquiebre1gt ltquiebre2gt ltquiebre10gt Este comando ejecuta el coacutedigo en memoria Si se estaacute depurando un programa permite ejecutar el coacutedigo cargado en memoria Tambieacuten permite establecer puntos de quiebre (breakpoints) que son direcciones en las que se detiene la ejecucioacuten del programa La sintaxis es G =ltiniciogt ltquiebre1gt ltquiebre2gt ltquiebre10gt ltiniciogt es la direccioacuten de inicio de ejecucioacuten ltquiebre1gt hasta ltquiebre10gt son direcciones opcionales de paro del programa Si no se especifica ltiniciogt Go inicia con la direccioacuten contenida en CSIP Para lograr los quiebres DEBUG reemplaza el coacutedigo en las direcciones de quiebre por el valor hexadecimal CC que es el coacutedigo de interrupcioacuten Si DEBUG llega a CC todos los puntos de quiebre son restituidos los registros se despliegan (como con el comando R [veacutease adelante]) y se para la ejecucioacuten U UNASSEMBLE U ltrangogt Este comando desensambla el contenido de la memoria a partir de la posicioacuten actual Registros y Banderas del DEBUG La mayoriacutea de los comandos de DEBUG ejecutan una accioacuten y vuelven al indicador del shell pero si es un comando largo como puede ser mostrar un trozo grande de coacutedigo puede detenerse pulsando CTRL-Pausa o interrumpirse con CTRL-C para volver al shell Por ejemplo al teclear lo siguiente

- r [Enter]

-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 17A70100 E8CD0F CALL 10D0 - Se desplegaran todos los contenidos de los registros internos del microprocesador una forma alternativa de mostrarlos es usar el comando r utilizando como paraacutemetro el nombre del registro cuyo valor se quiera visualizar Por ejemplo

- r bx Esta instruccioacuten desplegaraacute uacutenicamente el contenido del registro BX y cambia el indicador del DEBUG de - a Estando asiacute el prompt es posible cambiar el valor del registro que se visualizoacute tecleando el nuevo valor y a continuacioacuten [Enter] o se puede dejar el valor anterior presionando [Enter] sin teclear ninguacuten valor Es posible cambiar el valor del registro de banderas asiacute como utilizarlo como estructura de control en nuestros programas como se veraacute maacutes adelante Cada bit del registro tiene un nombre y significado especial la lista dada a continuacioacuten describe el valor de cada bit tanto apagado como prendido y su relacioacuten con las operaciones del microprocesador

Overflow (O) NV = no hay desbordamiento OV = si lo hay Direction (D) UP = hacia adelante DN = hacia atraacutes Interrupts (I) DI = desactivadas EI = activadas Sign (S) PL = positivo NG = negativo Zero (Z) NZ = no es cero ZR = s lo es Auxiliary Carry (A) NA = no hay acarreo auxiliar

AC = hay acarreo auxiliar Parity (P) PO = paridad non PE = paridad par Carry (C) NC = no hay acarreo CY = Si lo hay

La estructura del ensamblador En el lenguaje ensamblador las liacuteneas de coacutedigo constan de dos partes la primera es el nombre de la instruccioacuten que se va a ejecutar y la segunda son los paraacutemetros del comando u operandos Por ejemplo

add ahbh Aquiacute add es el comando a ejecutar (en este caso una adicioacuten) y tanto ah como bh son los paraacutemetros El nombre de las instrucciones en este lenguaje estaacute formado por dos tres o cuatro letras a estas instrucciones tambieacuten se les llama nombres mnemoacutenicos o coacutedigos de operacioacuten ya que representan alguna funcioacuten que habraacute de realizar el microprocesador Existen algunos comandos que no requieren paraacutemetros para su operacioacuten asiacute como otros que requieren solo un paraacutemetro Algunas veces se utilizaraacuten las instrucciones como sigue

add al[170] Los corchetes en el segundo paraacutemetro nos indican que vamos a trabajar con el contenido de la posicioacuten de memoria nuacutemero 170 y no con el valor 170 a esto se le conoce como direccionamiento directo Primer programa en ensamblador con el DEBUG Vamos a crear un programa que sirva para ilustrar lo que hemos estado viendo lo que haremos seraacute una suma de dos valores que introduciremos directamente en el programa El primer paso es iniciar el DEBUG este paso consiste uacutenicamente en teclear DEBUG [Enter] en el prompt del sistema operativo Para ensamblar un programa en el DEBUG se utiliza el comando a (assemble) cuando se utiliza este comando se le puede dar como paraacutemetro la direccioacuten donde se desea que se inicie el ensamblado Si se omite el paraacutemetro el ensamblado se iniciaraacute en la localidad especificada por CSIP usualmente 0100H que es la localidad donde deben iniciar los programas con extensioacuten COM y seraacute la localidad que utilizaremos debido a que DEBUG solo puede crear este tipo especiacutefico de programas

Aunque en este momento no es necesario darle un paraacutemetro al comando a es recomendable hacerlo para evitar problemas una vez que se haga uso de los registros CSIP por lo tanto tecleamos

- a 100 [Enter] Al hacer esto apareceraacute en la pantalla algo como 0C1B0100 y el cursor se posiciona a la derecha de estos nuacutemeros noacutetese que los primeros cuatro diacutegitos (en sistema hexadecimal) pueden ser diferentes pero los uacuteltimos cuatro deben ser 0100 ya que es la direccioacuten que indicamos como inicio Ahora podemos introducir las instrucciones

0C1B0100 mov ax0002 coloca el valor 0002 en el registro ax 0C1B0103 mov bx0004 coloca el valor 0004 en el registro bx 0C1B0106 add axbx le adiciona al contenido de ax el contenido de bx 0C1B0108 int 20 provoca la terminacioacuten del programa 0C1B010A

No es necesario escribir los comentarios que van despueacutes del Una vez escrito el uacuteltimo comando int 20 se le da [Enter] sin escribir nada maacutes para volver al prompt del DEBUG La uacuteltima liacutenea escrita no es propiamente una instruccioacuten de ensamblador es una llamada a una interrupcioacuten del sistema operativo estas interrupciones seraacuten tratadas maacutes a fondo en un capiacutetulo posterior por el momento solo es necesario saber que nos ahorran un gran nuacutemero de liacuteneas y son muy uacutetiles para accesar a funciones del sistema operativo Para ejecutar el programa que escribimos se utiliza el comando g al utilizarlo veremos que aparece un mensaje que dice Program terminated normally Naturalmente con un mensaje como eacuteste no podemos estar seguros que el programa haya hecho la suma pero existe una forma sencilla de verificarlo utilizando el comando r del DEBUG podemos ver los contenidos de todos los registros del microprocesador simplemente teclee

- r [Enter] Apareceraacute en pantalla cada registro con su respectivo valor actual -R AX=0006 BX=0004 CX=0000 DX=0000 SP=FFFE BP=0000 SI=0000 DI=0000 DS=0C1B ES=0C1B SS=0C1B CS=0C1B IP=010A NV UP EI PL NZ NA PO NC 17A70100 E8CD0F CALL 10D0 - Existe la posibilidad de que los registros contengan valores diferentes pero AX y BX deben ser los mismos ya que son los que acabamos de modificar Otra forma de ver los valores mientras se ejecuta el programa es utilizando como paraacutemetro para g la direccioacuten donde queremos que termine la ejecucioacuten y muestre los valores de los registros en este caso seraacute g108 esta instruccioacuten ejecuta el programa se detiene en la direccioacuten 108 y muestra los contenidos de los registros Tambieacuten se puede llevar un seguimiento de lo que pasa en los registros utilizando el comando t (trace) la funcioacuten de este comando es ejecutar liacutenea por liacutenea lo que se ensambloacute mostrando cada vez los contenidos de los registros Para salir del DEBUG se utiliza el comando q (quit)

Guardar y cargar los programas No seriacutea praacutectico tener que escribir todo un programa cada vez que se necesite para evitar eso es posible guardar un programa en el disco con la enorme ventaja de que ya ensamblado no seraacute necesario correr de nuevo DEBUG para ejecutarlo ya que cuando el DEBUG guardo nuestro programa en el disco eacuteste se guardo en binario (archivo con la extensioacuten com) Los pasos a seguir para guardar un programa ya almacenado en la memoria son

Obtener la longitud del programa restando la direccioacuten final de la direccioacuten inicial naturalmente en sistema hexadecimal

Darle un nombre al programa y una extensioacuten

Poner la longitud del programa en el registro CX

Ordenar a DEBUG que escriba el programa en el disco Utilizando como ejemplo el programa del ejemplo anterior tendremos una idea maacutes clara de coacutemo llevar estos pasos Al terminar de ensamblar el programa se veriacutea asiacute

0C1B0100 mov ax0002 0C1B0103 mov bx0004 0C1B0106 add axbx 0C1B0108 int 20 0C1B010A

Para almacenarlo en el disco hacemos lo siguiente - h 10a 100 020a 000a - n pruebacom - r cx CX 0000 000a -w Writing 000A bytes

Para obtener la longitud de un programa se utiliza el comando h el cual nos muestra la suma y resta de dos nuacutemeros en hexadecimal Para obtener la longitud del programa le proporcionamos como paraacutemetros el valor de la direccioacuten final de nuestro programa (10A) y el valor de la direccioacuten inicial (0100) El primer resultado que nos muestra el comando es la suma de los paraacutemetros y el segundo es la resta El comando n nos permite poner un nombre al programa El comando r cx nos permite cambiar el contenido del registro CX al valor que obtuvimos del tamantildeo del archivo con h en este caso 000a ya que nos interesa el resultado de la resta de la direccioacuten inicial a la direccioacuten final

Por uacuteltimo el comando w escribe nuestro programa en el disco indicaacutendonos cuantos bytes escribioacute

NOTA Si se trabaja en una ventana de DOS de Windows Vista o 7 es probable que al momento de guardar su programa el DEBUG escriba mas coacutedigo que el sentildealado por el registro CX por consiguiente seraacute necesario limpiar el registro BX esto es ponerlo a ceros y despueacutes utilizar el comando w Por ejemplo _r bx BX 000E 0000 w

Para cargar un archivo ya guardado son necesarios dos pasos

Proporcionar el nombre del archivo que se cargaraacute a memoria

Cargarlo utilizando el comando l (load) Para obtener el resultado correcto de los siguientes pasos es necesario que previamente se haya creado el programa anterior Dentro del DEBUG escribimos lo siguiente

- n pruebacom - l - u 100 109 0C3D0100 B80200 MOV AX0002 0C3D0103 BB0400 MOV BX0004 0C3D0106 01D8 ADD AXBX 0C3D0108 CD20 INT 20

El uacuteltimo comando u se utiliza para verificar que el programa se cargoacute en memoria lo que hace es desensamblar el coacutedigo y mostrarlo ya desensamblado Los paraacutemetros le indican a DEBUG desde donde y hasta donde desensamblar DEBUG siempre carga los programas en memoria en la direccioacuten 100H a menos que se le indique alguna otra Un programa que realiza un conteo en pantalla Con el DEBUG es posible escribir un programa que realice un conteo en pantalla por razones de comprensioacuten nuestro programa solo realizara un conteo de 9 a 0 (conteo descendente) 0B3B0100 B90A00 MOV CX000A CX=10 en decimal 0B3B0103 88CA MOV DLCL 0B3B0105 80C22F ADD DL2F sumamos 02Fh a DL 0B3B0108 B402 MOV AH02 funcioacuten 02 de INT 21 para imprimir un caracter 0B3B010A CD21 INT 21

0B3B010C E2F5 LOOP 0103 CX=0 Si no salta a 0103 0B3B010E CD20 INT 20 termina el programa En la liacutenea 0103 se puede observar que el valor del registro CX en su parte baja (en CL) se almacena en el registro DL Si se omitiera la liacutenea 0105 entonces cuando se ejecutara la liacutenea 010A solo se imprimiriacutea en pantalla el coacutedigo ASCII del valor que contenga DL (el coacutedigo ASCII de 0Ah que es 10 en decimal es un caraacutecter especial no imprimible) Para conseguir el ldquoefectordquo de que el programa realiza el conteo en decimal se hace un corrimiento de 02F (47 en decimal) Por ejemplo cuando se ejecuta la liacutenea 0105 DL tendriacutea el valor de 39h=57d (02Fh+0Ah=39h=57d) y el coacutedigo ASCII de 57d es el caraacutecter ldquo9rdquo El sentencia LOOP decrementa CX en 1 si CX es diferente a 0 salta a la liacutenea 0103 El proceso se repite y el programa imprime en pantalla 9876543210 Seriacutea interesante que el programa anterior fuera modificado para que la numeracioacuten se imprimiera de la siguiente manera 9 8 7 6 5 4 3 2 1 0

NOTA Como se dijo anteriormente cuando el DEBUG almacena un programa en el disco este archivo se graba en binario esto es en ejecutable Por lo tanto no es necesario cargar el DEBUG para volver a ejecutar nuestro programa sino que se hace de manera directa desde DOS El problema surge cuando al ejecutar nuestro programa el resultado no se puede observar porque el DOS borra la pantalla despueacutes de terminar de ejecutar el programa Para evitar el borrado automaacutetico seraacute necesario agregarle a nuestro programa antes de la INT 20h una instruccioacuten para la lectura de un caraacutecter desde el teclado Para tal efecto utilizaremos la funcioacuten 08 de la INT 21h (un buen truco para que el programa haga una pausa) asiacute el programa esperara hasta que el usuario presiona una tecla permitiendo observar el resultado Ejemplo mov ah08 Int 21 Int 20

Condiciones ciclos y bifurcaciones Estas estructuras o formas de control le dan a la maacutequina un cierto grado de decisioacuten basado en la informacioacuten que recibe La forma maacutes sencilla de comprender este tema es por medio de ejemplos Vamos a crear tres programas que hagan lo mismo desplegar un nuacutemero determinado de veces una cadena de caracteres en la pantalla

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV CX000F veces que se desplegara la cadena 0C1B0128 MOV DX0102 copia cadena al registro DX 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F LOOP 012D si CXgt0 salta a 012D 0C1B0131 INT 20 termina el programa

Por medio del comando e es posible introducir una cadena de caracteres en una determinada localidad de memoria dada como paraacutemetro la cadena se introduce entre comillas le sigue un espacio luego el valor hexadecimal del retorno de carro un espacio el valor de liacutenea nueva y por uacuteltimo el siacutembolo $ que el ensamblador interpreta como final de la cadena La interrupcioacuten 21 utiliza el valor almacenado en el registro AH para ejecutar una determinada funcioacuten en este caso mostrar la cadena en pantalla la cadena que muestra es la que estaacute almacenada en el registro DX La instruccioacuten LOOP decrementa automaacuteticamente el registro CX en uno y si no ha llegado el valor de este registro a cero salta a la posicioacuten de memoria indicada como paraacutemetro lo cual crea un ciclo que se repite el nuacutemero de veces especificado por el valor de CX La interrupcioacuten 20 termina la ejecucioacuten del programa Otra forma de realizar la misma funcioacuten pero sin utilizar el comando LOOP es la siguiente

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV BX000F veces que se desplegara la cadena 0C1B0128 MOV DX0102 copia cadena al registro DX 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F DEC BX decrementa en 1 a BX 0C1B0130 JNZ 012D si BX es diferente a 0 salta a 012D 0C1B0132 INT 20 termina el programa

En este caso se utiliza el registro BX como contador para el programa y por medio de la instruccioacuten DEC se disminuye su valor en 1 La instruccioacuten JNZ verifica si el valor de BX es diferente a 0 esto con base en la bandera NZ en caso afirmativo salta hacia la direccioacuten 012D En caso contrario continuacutea la ejecucioacuten normal del programa y por lo tanto se termina Una uacuteltima variante del programa es utilizando de nuevo a CX como contador pero en lugar de utilizar LOOP utilizaremos decrementos a CX y comparacioacuten de CX a 0

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV DX0102 copia cadena al registro DX 0C1B0128 MOV CX000F veces que se desplegara la cadena 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F DEC CX decrementa en 1 a CX 0C1B0130 JCXZ 0134 si CX es igual a 0 salta a 0134 0C1B0132 JMP 012D salta a la direccioacuten 012D 0C1B0134 INT 20 termina el programa

En este ejemplo se usoacute la instruccioacuten JCXZ para controlar la condicioacuten de salto el significado de tal funcioacuten es salta si CX=0 El tipo de control a utilizar dependeraacute de las necesidades de programacioacuten en determinado momento

Manipulacioacuten de Posiciones de Memoria Con el DEBUG es posible almacenar y recuperar datos numeacutericos en memoria por medio de un programa a traveacutes de los registros del microprocesador Por ejemplo el siguiente programa almacena previamente dos valores numeacutericos en la posicioacuten 0300h y 0400h respectivamente despueacutes el programa los recupera realiza la operacioacuten de suma con esos valores y el resultado lo almacena en la posicioacuten 0500h -a 100 0B1C0100 mov ax0002 ax=2 0B1C0103 mov [0300]ax almacenamos 2 en la direccioacuten 0300h 0B1C0106 mov ax0004 ax=4 0B1C0109 mov [0400]ax almacenamos 4 en la direccioacuten 0400h 0B1C010C mov ax[0300] recuperamos el dato1 en AX 0B1C010F mov bx[0400] recuperamos el dato2 en BX 0B1C0113 add axbx hacemos la operacioacuten de suma en AX 0B1C0115 mov [0500]ax almacenamos el 6 en la direccioacuten 0500h 0B1C0118 int 21 0B1C011A - Un nuacutemero entre corchetes [numero_hex] indica una posicioacuten de memoria y su manejo se hace a traveacutes de registros ya que no es posible almacenar valores numeacutericos de manera directa Ejecutamos el programa -g 118 AX=0006 BX=0004 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=0B1C ES=0B1C SS=0B1C CS=0B1C IP=0118 NV UP EI PL NZ NA PE NC 0B1C0118 CD21 INT 21 - Para ver si el resultado se almaceno en la direccioacuten correcta hacemos

Como se puede observar en la direccioacuten 0B1C0500 se encuentra el 06 y en 0B1C0501 se encuentra el 00 que es el resultado de la operacioacuten 2+4 Perohellip Porque aparece el 06 y despueacutes el 00 pareceriacutea que el resultado fue de 0600 pero no es asiacute lo que sucedes que los datos se almacenan en memoria de la siguiente manera

Como se hizo la operacioacuten AX=AX+BX entonces el resultado es de 16 bits (dos bytes) AX=6 entonces AX=0000 0000 0000 0110 (16 bits) por lo tanto los 8 bits de menor peso de AX son 0000 0110 y deben almacenarse en la direccioacuten 0500 y en la direccioacuten 0501 se almacena 0000 0000

0 0 0 0 0 1 1 0 0500

0 0 0 0 0 0 0 0 0501

x x x x x x x x 0502

x x x x x x x x 0503

x x x x x x x x 0504

x x x x x x x x 0505

Interrupciones Definicioacuten de interrupcioacuten

Una interrupcioacuten es una instruccioacuten que detiene la ejecucioacuten de un programa para permitir el uso del microprocesador en un proceso prioritario Una vez concluido este uacuteltimo proceso se devuelve el control a la aplicacioacuten anterior

Por ejemplo cuando estamos trabajando con un procesador de palabras y en ese momento llega un aviso de uno de los puertos de comunicaciones se detiene temporalmente la aplicacioacuten que estaacutebamos utilizando para permitir el uso del microprocesador al manejo de la informacioacuten que estaacute llegando en ese momento Una vez terminada la transferencia de informacioacuten se reanudan las funciones normales del procesador de palabras Las interrupciones ocurren muy seguido sencillamente la interrupcioacuten que actualiza la hora del diacutea ocurre aproximadamente 18 veces por segundo Para lograr administrar todas estas interrupciones la computadora cuenta con un espacio de memoria llamado memoria baja donde se almacenan las direcciones de cierta localidad de memoria donde se encuentran un juego de instrucciones que el microprocesador ejecutaraacute para despueacutes regresar a la aplicacioacuten que estaba en proceso En los programas anteriores hicimos uso de la interrupcioacuten nuacutemero 20H para terminar la ejecucioacuten de nuestros programas y en otros ejemplos utilizamos otra interrupcioacuten para mostrar informacioacuten en pantalla (INT 21h) Utilizando DEBUG tecleamos

- a100 2C1B0100 JMP 011D 2C1B0102 [ENTER] - E 102 Hola como estas 0D 0A $ - A011D 2C1B011D MOV DX0102 2C1B0120 MOV AH09 2C1B0122 INT 21 2C1B0123 INT 20

Orden

creciente

de la

memoria

En este programa la interrupcioacuten 21h manda al monitor la cadena localizada en la direccioacuten a la que apunta el registro DX El valor que se le da a AH determina cual de las opciones de la interrupcioacuten 21h seraacute utilizada ya que esta interrupcioacuten cuenta con varias opciones El manejo directo de interrupciones es una de las partes maacutes fuertes del lenguaje ensamblador ya que con ellas es posible controlar eficientemente todos los dispositivos internos y externos de una computadora gracias al completo control que se tiene sobre operaciones de entrada y salida Maacutes del DEBUG Una caracteriacutestica poco conocida es que DEBUG puede aceptar entradas desde un archivo Script que puede ser un simple archivo de texto ASCII en el que cada comando esteacute separado del anterior por un INTRO Despueacutes del uacuteltimo que debe ser una Q para salir de DEBUG es conveniente dejar una liacutenea en blanco pulsando INTRO dos veces Las liacuteneas pueden contener comentarios Cualquier cosa a partir del caracter punto y coma () hasta el final de la liacutenea seraacute ignorado esto es un comentario D aquiacute se mostraraacute algo Suponiendo que tengamos un archivo Script de nombre Ordenestxt puede ser utilizado como entrada para DEBUG mediante un comando de redireccioacuten en la siguiente forma DEBUG lt ordenestxt Tambieacuten puede conseguirse que el programa redireccione la salida hacia un archivo que puede ser inspeccionado maacutes 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 podriacutea obtenerse un archivo Resulttxt con el siguiente comando DEBUG lt ordenestxt gt Resulttxt Errores Cuando DEBUG no sabe interpretar un comando muestra un mensaje de error y un indicador ^ debajo del sitio del comando donde estaacute el error Entradas y Salidas DEBUG asume que los datos numeacutericos proporcionados son hexadecimales y cuando se trate de direcciones de memoria deben introducirse en forma segmentada A su vez los resultados son mostrados tambieacuten 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

Cada fila muestra 16 posiciones de memoria a partir de la posicioacuten sentildealada por las columnas de la izquierda que las muestran como segmentodesplazamiento El bloque central muestra el contenido hexadecimal de cada byte mientras que el bloque derecho contiene la representacioacuten ASCII Por ejemplo la 3ra fila muestra el contenido de las posiciones 0B770120 a 0B77012F (ambas inclusive) Sus tres uacuteltimos bytes contienen respectivamente los caracteres r 9 y 2 que corresponden a las cantidades 72h 39h y 32h del bloque central Que como sabemos equivalen a los decimales 114 57 y 50 que son precisamente los valores ASCII de los caracteres ldquorrdquo ldquo9rdquo y ldquo2rdquo anteriormente mencionados

Nota Por razoacuten de que eacuteste tipo de salida pueda ser listado a impresora el bloque derecho no contiene en realidad la representacioacuten ASCII de todos los caracteres (algunos ni siquiera tienen una representacioacuten imprimible) En realidad solo se muestran los caracteres imprimibles del primer bloque (US-ASCII) El resto estaacute 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 caraacutecter imprimible Esto no significa que dichas posiciones representen efectivamente tales valores para la aplicacioacuten que las utiliza Por ejemplo puede que en realidad las dos posiciones de memoria mencionadas (dos octetos o bytes) en vez de los caracteres ldquo5rdquo y ldquoardquo representen una palabra de 16 bits en formato Little Endian que a su vez representan una cantidad entera (un nuacutemero) Comandos Aunque su descripcioacuten completa llenariacutea todo un capiacutetulo a continuacioacuten comentamos algunas de las opciones maacutes interesantes relativas a inspeccioacuten del coacutedigo y de contenidos de memoria La opcioacuten D (Dump) permite obtener un volcado del contenido de la memoria (de DEBUG) La sintaxis acepta dos formas D [direccioacuten-inicial] [L posiciones-desde-direccioacuten-inicial ] D [direccioacuten-inicial][direccioacuten-final] Naturalmente para que exista algo en el buacutefer de memoria (al principio quizaacutes solo contiene basura) es preciso indicarle que lea algo Este algo puede ser un rango de direcciones de memoria RAM una direccioacuten absoluta de disco (sector) un archivo o el contenido de los registros del procesador Para empezar puede indicaacutersele que cargue un archivo xxxxyz que tenemos en el directorio actual o en el PATH cuyo contenido queremos ver Cgt DEBUG xxxxyz -D aquiacute se obtendriacutea una salida anaacuteloga a la comentada

Hemos visto un ejemplo al tratar de los servicios de interrupciones del PC aquiacute mostraremos otro Sabemos que el punto de inicio de la BIOS es la direccioacuten F000FFF0 y que desde eacutesta posicioacuten hasta el final de la memoria DOS hay 16 bytes Puede obtenerse un volcado de estas posiciones con el siguiente comando -D F000FFF0 La salida en un equipo puede ser F000FFF0 CD 19 E0 00 F0 30 36 2F-33 30 2F 39 37 00 FC 38 0630978 En este caso el comando solo muestra una liacutenea porque ha alcanzado el final de la memoria Puede verse que la fecha de la BIOS del sistema ocupa las uacuteltimas posiciones Si se ordena el volcado de una direccioacuten suficientemente alejada del final de la memoria sin indicar ninguacuten nuacutemero de posiciones por defecto se toma el valor 128 (8 filas de 16 posiciones) Si desea una cantidad distinta hay que antildeadir una L (Long) y el nuacutemero de posiciones hasta un maacuteximo de 64 KB (FFFF) Todos los nuacutemeros deben ser expresados en hexadecimal Por consiguiente los dos comandos que siguen son equivalentes (recuerde que 80 es el equivalente hexadecimal de 128) D FE000000 D FE000000 L 80 He aquiacute el resultado

Sabemos que esta zona corresponde al aacuterea de la BIOS del Sistema Otra opcioacuten muy interesante nos permite buscar determinados contenidos a traveacutes de la memoria utilizando el prefijo S (Search) Existen dos sintaxis alternativas S direccioacuten-de-inicio L longitud-a-explorar contenido-a-buscar S direccioacuten-de-inicio direccioacuten-final L contenido-a-buscar El contenido debe ser proporcionado en hexadecimal (tal como apareceriacutea en la columna central del ejemplo anterior) o entre comillas si es un texto ASCII Por ejemplo en un equipo IBM deseo ver algunas caracteriacutesticas de la BIOS Seacute que estos datos se alojan a partir de la posicioacuten F0000000 hasta el final de la memoria Es decir una longitud de 64 Kbytes (FFFF) a partir de la posicioacuten de inicio y que seguramente los datos buscados estaraacuten cerca de la identificacioacuten de la propia BIOS (la cadena IBM) Por lo que se utiliza la siguiente sintaxis [3] -s f0000000 L ffff IBM

y se obtiene la siguiente salida F000E00E F000E111 con las direcciones donde se ha encontrado la ocurrencia buscada A continuacioacuten puedo explorar las proximidades de cada posicioacuten Por ejemplo para la primera -D f000e000

Si lo que se busca estaacute en un archivo primero hay que cargarlo Lo que se puede hacer de dos formas en la propia invocacioacuten de DEBUG o mediante los comandos N y L Por ejemplo si queremos inspeccionar el contenido del archivo morecom podemos utilizar dos formas CWINDOWSgtDEBUG cwindowscommandmorecom CWINDOWSgtDEBUG - N cwindowscommandmorecom - L La sintaxis para el prefijo N es N [path-name]nombre-de-archivo En ambos casos el contenido del archivo seraacute cargado en memoria y podraacute ser utilizado Atencioacuten despueacutes de la orden L (Load) DEBUG le avisaraacute si no encuentra el archivo pero seguiraacute su funcionamiento En tal caso simplemente piensa que N sentildeala el nombre de un nuevo archivo que crearaacute con el contenido de la memoria -de DEBUG- cuando posteriormente seleccione la opcioacuten escribir W (Write)[4]

Nota Como ya habraacute deducido DEBUG permite leer un archivo realizar modificaciones en eacutel (con la opcioacuten E) y escribir el archivo modificado bajo otro nombre con NW

A continuacioacuten podemos comprobar el tamantildeo del archivo cargado Para ello usamos la opcioacuten 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 17A70100 E8CD0F CALL 10D0 -

Aquiacute nos interesa especialmente el contenido del registro CX cuyo valor 2917h (1519d) en este caso sentildeala el tamantildeo del archivo en bytes Tambieacuten podiacuteamos haber utilizado directamente el comando R CX que nos proporciona el valor de dicho registro -R CX CX 2917 -

Nota A continuacioacuten del valor correspondiente DEBUG muestra dos puntos () sentildealando que puede cambiar el valor del registro introduciendo un nuevo nuacutemero Pulse INTRO para dejar las cosas como estaacuten y volver al prompt (-) de DEBUG

Al llegar a este punto es importante sentildealar que a excepcioacuten de los archivos exe DEBUG carga los archivos a partir de la direccioacuten 100h (256d) de su memoria De forma que el primer octeto del archivo se carga en la direccioacuten 100 el segundo en 101 etc En nuestro caso el archivo se extenderaacute desde la posicioacuten 100h hasta 2A17h (100h + 2917h) A continuacioacuten para buscar la cadena Microsoft en el archivo utilizamos cualquiera de los siguientes comandos - S 100 L 2917 Microsoft - S 100 2a17 Microsoft El primer comando sentildeala el punto de inicio y el tamantildeo de la zona a buscar el segundo utiliza los puntos inicial y final de la exploracioacuten Con ambos se obtiene la misma respuesta 17A71083 17A710B2

Truco Debido a la forma especial en que se cargan los ejecutables exe si quiere inspeccionar la forma nativa de uno de estos archivos (como es su imagen en el disco) debe hacer una copia del archivo renombrarlo con cualquier otra terminacioacuten (o sin ella) y cargar esta copia En caso contrario DEBUG se prepararaacute para funcionar como un verdadero depurador de tiempo de ejecucioacuten (run-time) para lo que cargaraacute el archivo y lo acomodaraacute en memoria de forma que pueda ejecutarse [5]

Como ejercicio compruebe las distintas longitudes y aspecto (especialmente al principio) de un mismo archivo exe cargaacutendolo con DEBUG de las dos formas (busque en su sistema un exe lo maacutes pequentildeo posible) Ademaacutes de la capacidad de leer archivos antes mencionada quizaacutes una de las opciones maacutes interesantes (y peligrosas) de DEBUG es la posibilidad de leerescribir el contenido de disco a bajo nivel mediante los prefijos L (Load) y W (Write) Se utiliza la siguiente sintaxis L [Direccioacuten] [Unidad] [Primer_sector] [Nuacutemero] W [Direccioacuten] [Unidad] [Primer_sector] [Nuacutemero] El significado de los paraacutemetros es como sigue

Direccioacuten Posicioacuten de la memoria de DEBUG a partir de la cual se instalaraacuten los datos leiacutedos del disco o se tomaraacuten para el proceso de escritura (aquiacute se utiliza generalmente el valor 100h)

Unidad Valor numeacuterico que indica la loacutegica a utilizar 0 = A 1 = B 2 = C 3 = D etc [6]

Primer sector A partir del que se realizaraacute la lectura o se comenzaraacute a escribir

Nuacutemero Nuacutemero de sectores que se desea cargarescribir Como DEBUG no puede leerescribir maacutes de 64 Kbytes (2

16 = 65536) y los sectores de disco son de 512 bytes

el maacuteximo nuacutemero de sectores es 128 (80h) Asiacute pues el valor maacuteximo aquiacute es 80 Ejemplo Para obtener el contenido del sector de arranque (Master boot sector MBR) de un disquete en A utilizaremos el comando CWINDOWSgtDEBUG - L 100 0 0 1 - D 100 L 200 Como el resultado no cabe en una pantalla ingeniaremos un procedimiento para conservarlo en un archivo (maacutes adelante nos serviraacute para otro propoacutesito) Para ello creamos un archivo scripttxt con el siguiente contenido (dos INTRO despueacutes de la Q) L 100 0 0 1 D 100 L 200 Q A continuacioacuten invocamos DEBUG con el comando CWINDOWSgtDEBUG lt Dbuzonscripttxt gt Dbuzonresultadtxt Despueacutes de un breve parpadeo del disco y del disquete vuelve el prompt del DOS La operacioacuten ha concluido y en el directorio correspondiente de la unidad D tenemos el archivo resultadtxt con el volcado del sector de arranque del disquete ademaacutes de los ecos de los comandos introducidos (los hemos mantenido para orientacioacuten del lector) Otra forma de poder visualizar el contenido del Sector de Arranque del disco es utilizando el DEBUG Por ejemplo dentro del DEBUG tecleamos lo siguiente -L 100 0 0 1

-D 100 L 200

177C0100 EB 3E 90 2B 79 73 57 29-49 48 43 00 02 01 01 00 gt+ysW)IHC

177C0110 02 E0 00 40 0B F0 09 00-12 00 02 00 00 00 00 00

177C0120 00 00 00 00 00 00 29 5D-3B DD 10 4E 4F 20 4E 41 )]NO NA

177C0130 4D 45 20 20 20 20 46 41-54 31 32 20 20 20 F1 7D ME FAT12

177C0140 FA 33 C9 8E D1 BC FC 7B-16 07 BD 78 00 C5 76 00 3xv

177C0150 1E 56 16 55 BF 22 05 89-7E 00 89 4E 02 B1 0B FC VU~N

177C0160 F3 A4 06 1F BD 00 7C C6-45 FE 0F 8B 46 18 88 45 |EFE

177C0170 F9 FB 38 66 24 7C 04 CD-13 72 3C 8A 46 10 98 F7 8f$|rltF

177C0180 66 16 03 46 1C 13 56 1E-03 46 0E 13 D1 50 52 89 fFVFPR

177C0190 46 FC 89 56 FE B8 20 00-8B 76 11 F7 E6 8B 5E 0B FV v^

177C01A0 03 C3 48 F7 F3 01 46 FC-11 4E FE 5A 58 BB 00 07 HFNZX

177C01B0 8B FB B1 01 E8 94 00 72-47 38 2D 74 19 B1 0B 56 rG8-tV

177C01C0 8B 76 3E F3 A6 5E 74 4A-4E 74 0B 03 F9 83 C7 15 vgt^tJNt

177C01D0 3B FB 72 E5 EB D7 2B C9-B8 D8 7D 87 46 3E 3C D8 r+Fgtlt

177C01E0 75 99 BE 80 7D AC 98 03-F0 AC 84 C0 74 17 3C FF utlt

177C01F0 74 09 B4 0E BB 07 00 CD-10 EB EE BE 83 7D EB E5 t

177C0200 BE 81 7D EB E0 33 C0 CD-16 5E 1F 8F 04 8F 44 02 3^D

177C0210 CD 19 BE 82 7D 8B 7D 0F-83 FF 02 72 C8 8B C7 48 rH

177C0220 48 8A 4E 0D F7 E1 03 46-FC 13 56 FE BB 00 07 53 HNFVS

177C0230 B1 04 E8 16 00 5B 72 C8-81 3F 4D 5A 75 A7 81 BF [rMZu

177C0240 00 02 42 4A 75 9F EA 00-02 70 00 50 52 51 91 92 BJupPRQ

177C0250 33 D2 F7 76 18 91 F7 76-18 42 87 CA F7 76 1A 8A 3vvBv

177C0260 F2 8A 56 24 8A E8 D0 CC-D0 CC 0A CC B8 01 02 CD V$

177C0270 13 59 5A 58 72 09 40 75-01 42 03 5E 0B E2 CC C3 YZXruB^

177C0280 03 18 01 27 0D 0A 44 69-73 63 6F 20 69 6E 63 6F Disco inco

177C0290 72 72 65 63 74 6F 20 20-20 FF 0D 0A 45 72 72 6F rrecto Erro

177C02A0 72 20 45 2F 53 20 20 20-20 20 FF 0D 0A 43 61 6D r ES Cam

177C02B0 62 69 65 20 65 6C 20 64-69 73 63 6F 20 79 20 70 bie el disco y p

177C02C0 72 65 73 69 6F 6E 65 20-75 6E 61 20 74 65 63 6C resione una tecl

177C02D0 61 20 20 20 20 0D 0A 00-49 4F 20 20 20 20 20 20 a IO

177C02E0 53 59 53 4D 53 44 4F 53-20 20 20 53 59 53 80 01 SYSMSDOS SYS

177C02F0 00 57 49 4E 42 4F 4F 54-20 53 59 53 00 00 55 AA WINBOOT SYSU

-

-Q

FIN [1] En las primeras versiones de MS-DOS era un modesto programita DEBUGCOM de apenas 16 KB La versioacuten que acompantildea a Windows98 es ya un ejecutable en formato EXE de 21 KB [2] En realidad DEBUG es una utilidad de enorme potencia que requeririacutea todo un libro para ella sola Puede encontrarse una amplia descripcioacuten de esta herramienta en el libro de Paul Somerson PC Magazine DOS Powers Tools [3] Desgraciadamente no hay una convencioacuten estaacutendar sobre la colocacioacuten de los datos en la BIOS de forma que cada fabricante sigue sus propias reglas y es imposible por tanto utilizarla para cualquier tipo de identificacioacuten del sistema [4] En palabras del mencionado Paul Somerson Desgraciadamente debido a que DEBUG es un programa tan increiacuteblemente potente tambieacuten es increiacuteblemente peligroso Hay un dicho que afirma que El software no puede destruir el hardware Desgraciadamente esto no es cierto Ademaacutes de enviar mecanismos sensibles de la unidad de disco a tierra de nadie es posible hacer saltar monitores o transformadores Repito si sigue al pie de la letra las instrucciones y hace caso a todos los avisos todo iraacute bien [5] Recuerde que la imagen de un ejecutable exe cargado en memoria es distinta de su imagen en disco Solo en los ejecutables com la imagen en disco es una imagen exacta de su disposicioacuten en memoria [6] Es evidente que un pequentildeo error de nuacutemero en este paraacutemetro puede acarrear consecuencias nefastas Por ejemplo si cree que estaacute jugando con el disquete e inadvertidamente se dirige al disco duro (relea la nota [4])

Page 8: El Comando DEBUG

el prompt de - a invitando a que se cambie su valor Pulsando Enter sin maacutes lo deja como estaba Ejemplo R ltregistrogt Donde ltregistrogt 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 sinoacutenimos A ASSEMBLE A ltdireccioacutengt Sin paraacutemetros ensambla las instrucciones que se introduzcan guardaacutendolas en la direccioacuten siguiente a la que se llegoacute en el uacuteltimo a Cuando se utiliza este comando se le puede dar como paraacutemetro la direccioacuten donde se desea que se inicie el ensamblado si se omite el paraacutemetro el ensamblado se iniciaraacute en la localizacioacuten especificada por CSIP usualmente 0100H que es la localizacioacuten donde deben iniciar los programas con extensioacuten COM y seraacute la localizacioacuten que utilizaremos debido a que DEBUG solo puede crear este tipo especiacutefico de programas La sintaxis es A ltdireccioacutengt Praacutecticamente cualquier mnemoteacutecnico es soportado por DEBUG incluyendo los especificadores de override de segmento (CS DS ES SS) Una excepcioacuten 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 instruccioacuten MOV que como veremos maacutes adelante sirve para copiar datos de la memoria a los registros y viceversa ademaacutes de copiar datos entre registros que es justo lo que vamos a usar en el ejemplo -a 20480106 mov axbx 20480108 mov bxcx 2048010A ltRETgt -u 106 108 20480106 89D8 MOV AXBX 20480108 89CB MOV BXCX Como veremos maacutes adelante la instruccioacuten U sirve para hacer volcados de memoria pero no viendo el contenido de la misma sino interpretaacutendola como instrucciones en lenguaje ensamblador Ejemplo 2 -r cs CS 2048 2050 -a 200 20500200 mov axbx 20500202 ltRETgt -u 200 200 20500200 89D8 MOV AXBX

F FILL F ltbloquegt ltvalor de rellenogt Este comando llena un bloque de memoria con un valor especiacutefico o una serie de valores La sintaxis es F ltbloquegt ltvalor de rellenogt ltbloquegt es la direccioacuten de inicio y final o si se preceden con L la direccioacuten de inicio y la longitud del bloque ltvalor de rellenogt es(son) el(los) valor(es) con los que debe de llenarse el bloque Si ltvalor de rellenogt 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 liacuteneas llena (con 0rsquos) el bloque DS00FF F DS0000 DS00FF 0 DS0000 LFF 0 Ejemplo -f 100 105 66 -d 100 105 20480100 66 66 66 66 66 66 ffffff Q QUIT Q Salir de DEBUG y volver al DOS P PROCEED P lt=direccioacutengtltnuacutemerogt Similar al comando T pero al encontrarse un CALL o INT lo ejecuta de golpe sin entrar en su interior (ojo iexclesto uacuteltimo falla al tracear sobre memoria ROM) Trace puede ser incoacutemodo si no se quiere depurar el coacutedigo de las rutinas de interrupcioacuten o si ya se sabe el coacutedigo que hay en las subrutinas y tan soacutelo interesa seguir avanzando sin entrar en ellas En estos casos se usa p por lo que si ejecutamos una interrupcioacuten de MS-DOS no sabriacuteamos 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 20480107 3D5000 CMP AX0050 -a 100 20480100 mov ax0200 20480103 mov dl61 20480105 int 21 20480107 -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 20480103 B261 MOV DL61 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 20480105 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 20480107 3D5000 CMP AX0050 T TRACE T lt=direccioacutengt ltvalorgt Ejecuta una instruccioacuten del programa (a partir de CSIP) mostrando a continuacioacuten el estado de los registros y la siguiente instruccioacuten Ejecutar T10 equivaldriacutea a ejecutar 16 veces el comando T Si la instruccioacuten es CALL o INT se ejecutaraacute como tal introducieacutendose 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 20480100 3D0000 CMP AX0000 -r bx BX 0000 2 -a 100 20480100 mov axbx 20480102 -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 20480102 00AC01D8 ADD [SI+D801]CH DSD801=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 20480100 3D0000 CMP AX0000 -a 100 20480100 mov axbx 20480102 mov cxbx 20480104 -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 20480102 89D9 MOV CXBX 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 20480104 01D8 ADD AXBX

N NAME N ltnombre_archivogt Se asigna un nombre al programa que estaacute siendo creado o modificado Se puede indicar la trayectoria de directorios L LOAD L ltbuffergt ltnumdiscogt ltsectorinigt ltnumsectorgt ltbuffergt es la direccioacuten en donde se carga la informacioacuten ltnumdiscogt es el nuacutemero (opcional) del disco de donde se leeraacute la informacioacuten (0=A 1=B 2=C etc) ltsectorinigt es el sector de disco absoluto (en hexadecimal) a leer ltnumsectorgt es la cantidad de sectores a leer No se pueden leer maacutes de 80H (128) sectores Si no se suministra la combinacioacuten ltnumdiscogt ltsectorinigt ltnumsectorgt DEBUG presume que se desea leer un archivo En este caso ltbuffergt es opcional Debe usarse el comando N (ver maacutes adelante) para especificar el archivo a leer Eacuteste se carga en CS0100 Ejemplo Se va a leer el sector 0 del disco A y se vuelca a partir de la direccioacuten DS100 como se puede observar el disco contiene mucha informacioacuten ( ESTO NO QUIERE DECIR QUE TENGA QUE SALIR LO MISMO EN SU VOLCADO )

l 100 0 0 1 -d 100 300

W WRITE W ltdireccioacutengt Graba el contenido de una zona de memoria a disco Si no se indica la direccioacuten se graba desde CS100h hasta CS100h+nuacutemero_bytes el nuacutemero de bytes se indica en BXCX (no es una direccioacuten segmentada sino un valor de 32 bits) Si se trata de un EXE no se permitiraacute grabarlo (para modificarlos hay que renombrarles para cambiarles la extensioacuten aunque de esta manera no seraacuten montados al cargarlos) La sintaxis es W ltbuffergt ltnumdiscogt ltsectorinigt ltnumsectorgt ltbuffergt es la direccioacuten de donde se carga la informacioacuten ltnumdiscogt es el nuacutemero (opcional) del disco en donde se escribiraacute la informacioacuten (0=A 1=B 2=C etc) ltsectorinigt es el sector de disco absoluto (en hexadecimal) en donde empieza la escritura ltnumsectorgt es la cantidad de sectores a leer No se pueden escribir maacutes de 80H (128) sectores Si no se suministra la combinacioacuten ltnumdiscogt ltsectorinigt ltnumsectorgt DEBUG presume que el inicio de archivo es CS100 En este caso ltbuffergt es opcional Debe usarse el comando N (ver arriba) para especificar el archivo a escribir Antes de escribir BXCX debe ajustarse al nuacutemero de bytes que desean grabarse W no puede escribir a archivos con la extensioacuten EXE o HEX [5] Ejemplo

N ltnomarchivogt BXCX lt--- 2000 W

S SEARCH S ltrangogt ltlistagt Busca una cadena de bytes por la memoria Para buscar la cadena PEPE terminada por cero en un aacuterea de 512 bytes desde DS100 se hariacutea S 100 L 200 PEPE0 (por defecto se busca en DS) No se encontrariacutea sin embargo pepe (en minuacutesculas) C COMPARE C ltrangogt ltdireccioacutengt Compara dos zonas de memoria mostrando las diferencias Por ejemplo para comparar 5 bytes de DS100 y DS200 se hace C 100 L 5 200 M MOVE M ltrangogt ltdireccioacutengt Maacutes que mover copia una zona de memoria en otra de manera inteligente (controlando los posibles solapamientos de los bloques) I INPUT I ltpuertogt Visualiza la lectura del puerto de ES indicado

O OUTPUT O ltpuertogt ltvalorgt Enviacutea un valor a un puerto de ES H HEX H ltvalor1gt ltvalor2gt Muestra la suma y resta de valor1 y valor2 ambos operandos de un maacuteximo de 16 bits (si hay desbordamiento se trunca el resultado que tampoco excede los 16 bits) Resultado ltresultado_1gt Es la suma ( ltvalor1gt + ltvalor2gt) ltresultado_2gt es la resta (ltvalor1gt - ltvalor2gt ) Ejemplo -h 0003 0002 0005 0001 -h 0000 0001 0001 FFFF como se observa el resultado de la segunda operacioacuten es FFFF que es el equivalente en complemento a 2 de -1 G GO G =ltiniciogt ltquiebre1gt ltquiebre2gt ltquiebre10gt Este comando ejecuta el coacutedigo en memoria Si se estaacute depurando un programa permite ejecutar el coacutedigo cargado en memoria Tambieacuten permite establecer puntos de quiebre (breakpoints) que son direcciones en las que se detiene la ejecucioacuten del programa La sintaxis es G =ltiniciogt ltquiebre1gt ltquiebre2gt ltquiebre10gt ltiniciogt es la direccioacuten de inicio de ejecucioacuten ltquiebre1gt hasta ltquiebre10gt son direcciones opcionales de paro del programa Si no se especifica ltiniciogt Go inicia con la direccioacuten contenida en CSIP Para lograr los quiebres DEBUG reemplaza el coacutedigo en las direcciones de quiebre por el valor hexadecimal CC que es el coacutedigo de interrupcioacuten Si DEBUG llega a CC todos los puntos de quiebre son restituidos los registros se despliegan (como con el comando R [veacutease adelante]) y se para la ejecucioacuten U UNASSEMBLE U ltrangogt Este comando desensambla el contenido de la memoria a partir de la posicioacuten actual Registros y Banderas del DEBUG La mayoriacutea de los comandos de DEBUG ejecutan una accioacuten y vuelven al indicador del shell pero si es un comando largo como puede ser mostrar un trozo grande de coacutedigo puede detenerse pulsando CTRL-Pausa o interrumpirse con CTRL-C para volver al shell Por ejemplo al teclear lo siguiente

- r [Enter]

-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 17A70100 E8CD0F CALL 10D0 - Se desplegaran todos los contenidos de los registros internos del microprocesador una forma alternativa de mostrarlos es usar el comando r utilizando como paraacutemetro el nombre del registro cuyo valor se quiera visualizar Por ejemplo

- r bx Esta instruccioacuten desplegaraacute uacutenicamente el contenido del registro BX y cambia el indicador del DEBUG de - a Estando asiacute el prompt es posible cambiar el valor del registro que se visualizoacute tecleando el nuevo valor y a continuacioacuten [Enter] o se puede dejar el valor anterior presionando [Enter] sin teclear ninguacuten valor Es posible cambiar el valor del registro de banderas asiacute como utilizarlo como estructura de control en nuestros programas como se veraacute maacutes adelante Cada bit del registro tiene un nombre y significado especial la lista dada a continuacioacuten describe el valor de cada bit tanto apagado como prendido y su relacioacuten con las operaciones del microprocesador

Overflow (O) NV = no hay desbordamiento OV = si lo hay Direction (D) UP = hacia adelante DN = hacia atraacutes Interrupts (I) DI = desactivadas EI = activadas Sign (S) PL = positivo NG = negativo Zero (Z) NZ = no es cero ZR = s lo es Auxiliary Carry (A) NA = no hay acarreo auxiliar

AC = hay acarreo auxiliar Parity (P) PO = paridad non PE = paridad par Carry (C) NC = no hay acarreo CY = Si lo hay

La estructura del ensamblador En el lenguaje ensamblador las liacuteneas de coacutedigo constan de dos partes la primera es el nombre de la instruccioacuten que se va a ejecutar y la segunda son los paraacutemetros del comando u operandos Por ejemplo

add ahbh Aquiacute add es el comando a ejecutar (en este caso una adicioacuten) y tanto ah como bh son los paraacutemetros El nombre de las instrucciones en este lenguaje estaacute formado por dos tres o cuatro letras a estas instrucciones tambieacuten se les llama nombres mnemoacutenicos o coacutedigos de operacioacuten ya que representan alguna funcioacuten que habraacute de realizar el microprocesador Existen algunos comandos que no requieren paraacutemetros para su operacioacuten asiacute como otros que requieren solo un paraacutemetro Algunas veces se utilizaraacuten las instrucciones como sigue

add al[170] Los corchetes en el segundo paraacutemetro nos indican que vamos a trabajar con el contenido de la posicioacuten de memoria nuacutemero 170 y no con el valor 170 a esto se le conoce como direccionamiento directo Primer programa en ensamblador con el DEBUG Vamos a crear un programa que sirva para ilustrar lo que hemos estado viendo lo que haremos seraacute una suma de dos valores que introduciremos directamente en el programa El primer paso es iniciar el DEBUG este paso consiste uacutenicamente en teclear DEBUG [Enter] en el prompt del sistema operativo Para ensamblar un programa en el DEBUG se utiliza el comando a (assemble) cuando se utiliza este comando se le puede dar como paraacutemetro la direccioacuten donde se desea que se inicie el ensamblado Si se omite el paraacutemetro el ensamblado se iniciaraacute en la localidad especificada por CSIP usualmente 0100H que es la localidad donde deben iniciar los programas con extensioacuten COM y seraacute la localidad que utilizaremos debido a que DEBUG solo puede crear este tipo especiacutefico de programas

Aunque en este momento no es necesario darle un paraacutemetro al comando a es recomendable hacerlo para evitar problemas una vez que se haga uso de los registros CSIP por lo tanto tecleamos

- a 100 [Enter] Al hacer esto apareceraacute en la pantalla algo como 0C1B0100 y el cursor se posiciona a la derecha de estos nuacutemeros noacutetese que los primeros cuatro diacutegitos (en sistema hexadecimal) pueden ser diferentes pero los uacuteltimos cuatro deben ser 0100 ya que es la direccioacuten que indicamos como inicio Ahora podemos introducir las instrucciones

0C1B0100 mov ax0002 coloca el valor 0002 en el registro ax 0C1B0103 mov bx0004 coloca el valor 0004 en el registro bx 0C1B0106 add axbx le adiciona al contenido de ax el contenido de bx 0C1B0108 int 20 provoca la terminacioacuten del programa 0C1B010A

No es necesario escribir los comentarios que van despueacutes del Una vez escrito el uacuteltimo comando int 20 se le da [Enter] sin escribir nada maacutes para volver al prompt del DEBUG La uacuteltima liacutenea escrita no es propiamente una instruccioacuten de ensamblador es una llamada a una interrupcioacuten del sistema operativo estas interrupciones seraacuten tratadas maacutes a fondo en un capiacutetulo posterior por el momento solo es necesario saber que nos ahorran un gran nuacutemero de liacuteneas y son muy uacutetiles para accesar a funciones del sistema operativo Para ejecutar el programa que escribimos se utiliza el comando g al utilizarlo veremos que aparece un mensaje que dice Program terminated normally Naturalmente con un mensaje como eacuteste no podemos estar seguros que el programa haya hecho la suma pero existe una forma sencilla de verificarlo utilizando el comando r del DEBUG podemos ver los contenidos de todos los registros del microprocesador simplemente teclee

- r [Enter] Apareceraacute en pantalla cada registro con su respectivo valor actual -R AX=0006 BX=0004 CX=0000 DX=0000 SP=FFFE BP=0000 SI=0000 DI=0000 DS=0C1B ES=0C1B SS=0C1B CS=0C1B IP=010A NV UP EI PL NZ NA PO NC 17A70100 E8CD0F CALL 10D0 - Existe la posibilidad de que los registros contengan valores diferentes pero AX y BX deben ser los mismos ya que son los que acabamos de modificar Otra forma de ver los valores mientras se ejecuta el programa es utilizando como paraacutemetro para g la direccioacuten donde queremos que termine la ejecucioacuten y muestre los valores de los registros en este caso seraacute g108 esta instruccioacuten ejecuta el programa se detiene en la direccioacuten 108 y muestra los contenidos de los registros Tambieacuten se puede llevar un seguimiento de lo que pasa en los registros utilizando el comando t (trace) la funcioacuten de este comando es ejecutar liacutenea por liacutenea lo que se ensambloacute mostrando cada vez los contenidos de los registros Para salir del DEBUG se utiliza el comando q (quit)

Guardar y cargar los programas No seriacutea praacutectico tener que escribir todo un programa cada vez que se necesite para evitar eso es posible guardar un programa en el disco con la enorme ventaja de que ya ensamblado no seraacute necesario correr de nuevo DEBUG para ejecutarlo ya que cuando el DEBUG guardo nuestro programa en el disco eacuteste se guardo en binario (archivo con la extensioacuten com) Los pasos a seguir para guardar un programa ya almacenado en la memoria son

Obtener la longitud del programa restando la direccioacuten final de la direccioacuten inicial naturalmente en sistema hexadecimal

Darle un nombre al programa y una extensioacuten

Poner la longitud del programa en el registro CX

Ordenar a DEBUG que escriba el programa en el disco Utilizando como ejemplo el programa del ejemplo anterior tendremos una idea maacutes clara de coacutemo llevar estos pasos Al terminar de ensamblar el programa se veriacutea asiacute

0C1B0100 mov ax0002 0C1B0103 mov bx0004 0C1B0106 add axbx 0C1B0108 int 20 0C1B010A

Para almacenarlo en el disco hacemos lo siguiente - h 10a 100 020a 000a - n pruebacom - r cx CX 0000 000a -w Writing 000A bytes

Para obtener la longitud de un programa se utiliza el comando h el cual nos muestra la suma y resta de dos nuacutemeros en hexadecimal Para obtener la longitud del programa le proporcionamos como paraacutemetros el valor de la direccioacuten final de nuestro programa (10A) y el valor de la direccioacuten inicial (0100) El primer resultado que nos muestra el comando es la suma de los paraacutemetros y el segundo es la resta El comando n nos permite poner un nombre al programa El comando r cx nos permite cambiar el contenido del registro CX al valor que obtuvimos del tamantildeo del archivo con h en este caso 000a ya que nos interesa el resultado de la resta de la direccioacuten inicial a la direccioacuten final

Por uacuteltimo el comando w escribe nuestro programa en el disco indicaacutendonos cuantos bytes escribioacute

NOTA Si se trabaja en una ventana de DOS de Windows Vista o 7 es probable que al momento de guardar su programa el DEBUG escriba mas coacutedigo que el sentildealado por el registro CX por consiguiente seraacute necesario limpiar el registro BX esto es ponerlo a ceros y despueacutes utilizar el comando w Por ejemplo _r bx BX 000E 0000 w

Para cargar un archivo ya guardado son necesarios dos pasos

Proporcionar el nombre del archivo que se cargaraacute a memoria

Cargarlo utilizando el comando l (load) Para obtener el resultado correcto de los siguientes pasos es necesario que previamente se haya creado el programa anterior Dentro del DEBUG escribimos lo siguiente

- n pruebacom - l - u 100 109 0C3D0100 B80200 MOV AX0002 0C3D0103 BB0400 MOV BX0004 0C3D0106 01D8 ADD AXBX 0C3D0108 CD20 INT 20

El uacuteltimo comando u se utiliza para verificar que el programa se cargoacute en memoria lo que hace es desensamblar el coacutedigo y mostrarlo ya desensamblado Los paraacutemetros le indican a DEBUG desde donde y hasta donde desensamblar DEBUG siempre carga los programas en memoria en la direccioacuten 100H a menos que se le indique alguna otra Un programa que realiza un conteo en pantalla Con el DEBUG es posible escribir un programa que realice un conteo en pantalla por razones de comprensioacuten nuestro programa solo realizara un conteo de 9 a 0 (conteo descendente) 0B3B0100 B90A00 MOV CX000A CX=10 en decimal 0B3B0103 88CA MOV DLCL 0B3B0105 80C22F ADD DL2F sumamos 02Fh a DL 0B3B0108 B402 MOV AH02 funcioacuten 02 de INT 21 para imprimir un caracter 0B3B010A CD21 INT 21

0B3B010C E2F5 LOOP 0103 CX=0 Si no salta a 0103 0B3B010E CD20 INT 20 termina el programa En la liacutenea 0103 se puede observar que el valor del registro CX en su parte baja (en CL) se almacena en el registro DL Si se omitiera la liacutenea 0105 entonces cuando se ejecutara la liacutenea 010A solo se imprimiriacutea en pantalla el coacutedigo ASCII del valor que contenga DL (el coacutedigo ASCII de 0Ah que es 10 en decimal es un caraacutecter especial no imprimible) Para conseguir el ldquoefectordquo de que el programa realiza el conteo en decimal se hace un corrimiento de 02F (47 en decimal) Por ejemplo cuando se ejecuta la liacutenea 0105 DL tendriacutea el valor de 39h=57d (02Fh+0Ah=39h=57d) y el coacutedigo ASCII de 57d es el caraacutecter ldquo9rdquo El sentencia LOOP decrementa CX en 1 si CX es diferente a 0 salta a la liacutenea 0103 El proceso se repite y el programa imprime en pantalla 9876543210 Seriacutea interesante que el programa anterior fuera modificado para que la numeracioacuten se imprimiera de la siguiente manera 9 8 7 6 5 4 3 2 1 0

NOTA Como se dijo anteriormente cuando el DEBUG almacena un programa en el disco este archivo se graba en binario esto es en ejecutable Por lo tanto no es necesario cargar el DEBUG para volver a ejecutar nuestro programa sino que se hace de manera directa desde DOS El problema surge cuando al ejecutar nuestro programa el resultado no se puede observar porque el DOS borra la pantalla despueacutes de terminar de ejecutar el programa Para evitar el borrado automaacutetico seraacute necesario agregarle a nuestro programa antes de la INT 20h una instruccioacuten para la lectura de un caraacutecter desde el teclado Para tal efecto utilizaremos la funcioacuten 08 de la INT 21h (un buen truco para que el programa haga una pausa) asiacute el programa esperara hasta que el usuario presiona una tecla permitiendo observar el resultado Ejemplo mov ah08 Int 21 Int 20

Condiciones ciclos y bifurcaciones Estas estructuras o formas de control le dan a la maacutequina un cierto grado de decisioacuten basado en la informacioacuten que recibe La forma maacutes sencilla de comprender este tema es por medio de ejemplos Vamos a crear tres programas que hagan lo mismo desplegar un nuacutemero determinado de veces una cadena de caracteres en la pantalla

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV CX000F veces que se desplegara la cadena 0C1B0128 MOV DX0102 copia cadena al registro DX 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F LOOP 012D si CXgt0 salta a 012D 0C1B0131 INT 20 termina el programa

Por medio del comando e es posible introducir una cadena de caracteres en una determinada localidad de memoria dada como paraacutemetro la cadena se introduce entre comillas le sigue un espacio luego el valor hexadecimal del retorno de carro un espacio el valor de liacutenea nueva y por uacuteltimo el siacutembolo $ que el ensamblador interpreta como final de la cadena La interrupcioacuten 21 utiliza el valor almacenado en el registro AH para ejecutar una determinada funcioacuten en este caso mostrar la cadena en pantalla la cadena que muestra es la que estaacute almacenada en el registro DX La instruccioacuten LOOP decrementa automaacuteticamente el registro CX en uno y si no ha llegado el valor de este registro a cero salta a la posicioacuten de memoria indicada como paraacutemetro lo cual crea un ciclo que se repite el nuacutemero de veces especificado por el valor de CX La interrupcioacuten 20 termina la ejecucioacuten del programa Otra forma de realizar la misma funcioacuten pero sin utilizar el comando LOOP es la siguiente

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV BX000F veces que se desplegara la cadena 0C1B0128 MOV DX0102 copia cadena al registro DX 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F DEC BX decrementa en 1 a BX 0C1B0130 JNZ 012D si BX es diferente a 0 salta a 012D 0C1B0132 INT 20 termina el programa

En este caso se utiliza el registro BX como contador para el programa y por medio de la instruccioacuten DEC se disminuye su valor en 1 La instruccioacuten JNZ verifica si el valor de BX es diferente a 0 esto con base en la bandera NZ en caso afirmativo salta hacia la direccioacuten 012D En caso contrario continuacutea la ejecucioacuten normal del programa y por lo tanto se termina Una uacuteltima variante del programa es utilizando de nuevo a CX como contador pero en lugar de utilizar LOOP utilizaremos decrementos a CX y comparacioacuten de CX a 0

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV DX0102 copia cadena al registro DX 0C1B0128 MOV CX000F veces que se desplegara la cadena 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F DEC CX decrementa en 1 a CX 0C1B0130 JCXZ 0134 si CX es igual a 0 salta a 0134 0C1B0132 JMP 012D salta a la direccioacuten 012D 0C1B0134 INT 20 termina el programa

En este ejemplo se usoacute la instruccioacuten JCXZ para controlar la condicioacuten de salto el significado de tal funcioacuten es salta si CX=0 El tipo de control a utilizar dependeraacute de las necesidades de programacioacuten en determinado momento

Manipulacioacuten de Posiciones de Memoria Con el DEBUG es posible almacenar y recuperar datos numeacutericos en memoria por medio de un programa a traveacutes de los registros del microprocesador Por ejemplo el siguiente programa almacena previamente dos valores numeacutericos en la posicioacuten 0300h y 0400h respectivamente despueacutes el programa los recupera realiza la operacioacuten de suma con esos valores y el resultado lo almacena en la posicioacuten 0500h -a 100 0B1C0100 mov ax0002 ax=2 0B1C0103 mov [0300]ax almacenamos 2 en la direccioacuten 0300h 0B1C0106 mov ax0004 ax=4 0B1C0109 mov [0400]ax almacenamos 4 en la direccioacuten 0400h 0B1C010C mov ax[0300] recuperamos el dato1 en AX 0B1C010F mov bx[0400] recuperamos el dato2 en BX 0B1C0113 add axbx hacemos la operacioacuten de suma en AX 0B1C0115 mov [0500]ax almacenamos el 6 en la direccioacuten 0500h 0B1C0118 int 21 0B1C011A - Un nuacutemero entre corchetes [numero_hex] indica una posicioacuten de memoria y su manejo se hace a traveacutes de registros ya que no es posible almacenar valores numeacutericos de manera directa Ejecutamos el programa -g 118 AX=0006 BX=0004 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=0B1C ES=0B1C SS=0B1C CS=0B1C IP=0118 NV UP EI PL NZ NA PE NC 0B1C0118 CD21 INT 21 - Para ver si el resultado se almaceno en la direccioacuten correcta hacemos

Como se puede observar en la direccioacuten 0B1C0500 se encuentra el 06 y en 0B1C0501 se encuentra el 00 que es el resultado de la operacioacuten 2+4 Perohellip Porque aparece el 06 y despueacutes el 00 pareceriacutea que el resultado fue de 0600 pero no es asiacute lo que sucedes que los datos se almacenan en memoria de la siguiente manera

Como se hizo la operacioacuten AX=AX+BX entonces el resultado es de 16 bits (dos bytes) AX=6 entonces AX=0000 0000 0000 0110 (16 bits) por lo tanto los 8 bits de menor peso de AX son 0000 0110 y deben almacenarse en la direccioacuten 0500 y en la direccioacuten 0501 se almacena 0000 0000

0 0 0 0 0 1 1 0 0500

0 0 0 0 0 0 0 0 0501

x x x x x x x x 0502

x x x x x x x x 0503

x x x x x x x x 0504

x x x x x x x x 0505

Interrupciones Definicioacuten de interrupcioacuten

Una interrupcioacuten es una instruccioacuten que detiene la ejecucioacuten de un programa para permitir el uso del microprocesador en un proceso prioritario Una vez concluido este uacuteltimo proceso se devuelve el control a la aplicacioacuten anterior

Por ejemplo cuando estamos trabajando con un procesador de palabras y en ese momento llega un aviso de uno de los puertos de comunicaciones se detiene temporalmente la aplicacioacuten que estaacutebamos utilizando para permitir el uso del microprocesador al manejo de la informacioacuten que estaacute llegando en ese momento Una vez terminada la transferencia de informacioacuten se reanudan las funciones normales del procesador de palabras Las interrupciones ocurren muy seguido sencillamente la interrupcioacuten que actualiza la hora del diacutea ocurre aproximadamente 18 veces por segundo Para lograr administrar todas estas interrupciones la computadora cuenta con un espacio de memoria llamado memoria baja donde se almacenan las direcciones de cierta localidad de memoria donde se encuentran un juego de instrucciones que el microprocesador ejecutaraacute para despueacutes regresar a la aplicacioacuten que estaba en proceso En los programas anteriores hicimos uso de la interrupcioacuten nuacutemero 20H para terminar la ejecucioacuten de nuestros programas y en otros ejemplos utilizamos otra interrupcioacuten para mostrar informacioacuten en pantalla (INT 21h) Utilizando DEBUG tecleamos

- a100 2C1B0100 JMP 011D 2C1B0102 [ENTER] - E 102 Hola como estas 0D 0A $ - A011D 2C1B011D MOV DX0102 2C1B0120 MOV AH09 2C1B0122 INT 21 2C1B0123 INT 20

Orden

creciente

de la

memoria

En este programa la interrupcioacuten 21h manda al monitor la cadena localizada en la direccioacuten a la que apunta el registro DX El valor que se le da a AH determina cual de las opciones de la interrupcioacuten 21h seraacute utilizada ya que esta interrupcioacuten cuenta con varias opciones El manejo directo de interrupciones es una de las partes maacutes fuertes del lenguaje ensamblador ya que con ellas es posible controlar eficientemente todos los dispositivos internos y externos de una computadora gracias al completo control que se tiene sobre operaciones de entrada y salida Maacutes del DEBUG Una caracteriacutestica poco conocida es que DEBUG puede aceptar entradas desde un archivo Script que puede ser un simple archivo de texto ASCII en el que cada comando esteacute separado del anterior por un INTRO Despueacutes del uacuteltimo que debe ser una Q para salir de DEBUG es conveniente dejar una liacutenea en blanco pulsando INTRO dos veces Las liacuteneas pueden contener comentarios Cualquier cosa a partir del caracter punto y coma () hasta el final de la liacutenea seraacute ignorado esto es un comentario D aquiacute se mostraraacute algo Suponiendo que tengamos un archivo Script de nombre Ordenestxt puede ser utilizado como entrada para DEBUG mediante un comando de redireccioacuten en la siguiente forma DEBUG lt ordenestxt Tambieacuten puede conseguirse que el programa redireccione la salida hacia un archivo que puede ser inspeccionado maacutes 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 podriacutea obtenerse un archivo Resulttxt con el siguiente comando DEBUG lt ordenestxt gt Resulttxt Errores Cuando DEBUG no sabe interpretar un comando muestra un mensaje de error y un indicador ^ debajo del sitio del comando donde estaacute el error Entradas y Salidas DEBUG asume que los datos numeacutericos proporcionados son hexadecimales y cuando se trate de direcciones de memoria deben introducirse en forma segmentada A su vez los resultados son mostrados tambieacuten 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

Cada fila muestra 16 posiciones de memoria a partir de la posicioacuten sentildealada por las columnas de la izquierda que las muestran como segmentodesplazamiento El bloque central muestra el contenido hexadecimal de cada byte mientras que el bloque derecho contiene la representacioacuten ASCII Por ejemplo la 3ra fila muestra el contenido de las posiciones 0B770120 a 0B77012F (ambas inclusive) Sus tres uacuteltimos bytes contienen respectivamente los caracteres r 9 y 2 que corresponden a las cantidades 72h 39h y 32h del bloque central Que como sabemos equivalen a los decimales 114 57 y 50 que son precisamente los valores ASCII de los caracteres ldquorrdquo ldquo9rdquo y ldquo2rdquo anteriormente mencionados

Nota Por razoacuten de que eacuteste tipo de salida pueda ser listado a impresora el bloque derecho no contiene en realidad la representacioacuten ASCII de todos los caracteres (algunos ni siquiera tienen una representacioacuten imprimible) En realidad solo se muestran los caracteres imprimibles del primer bloque (US-ASCII) El resto estaacute 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 caraacutecter imprimible Esto no significa que dichas posiciones representen efectivamente tales valores para la aplicacioacuten que las utiliza Por ejemplo puede que en realidad las dos posiciones de memoria mencionadas (dos octetos o bytes) en vez de los caracteres ldquo5rdquo y ldquoardquo representen una palabra de 16 bits en formato Little Endian que a su vez representan una cantidad entera (un nuacutemero) Comandos Aunque su descripcioacuten completa llenariacutea todo un capiacutetulo a continuacioacuten comentamos algunas de las opciones maacutes interesantes relativas a inspeccioacuten del coacutedigo y de contenidos de memoria La opcioacuten D (Dump) permite obtener un volcado del contenido de la memoria (de DEBUG) La sintaxis acepta dos formas D [direccioacuten-inicial] [L posiciones-desde-direccioacuten-inicial ] D [direccioacuten-inicial][direccioacuten-final] Naturalmente para que exista algo en el buacutefer de memoria (al principio quizaacutes solo contiene basura) es preciso indicarle que lea algo Este algo puede ser un rango de direcciones de memoria RAM una direccioacuten absoluta de disco (sector) un archivo o el contenido de los registros del procesador Para empezar puede indicaacutersele que cargue un archivo xxxxyz que tenemos en el directorio actual o en el PATH cuyo contenido queremos ver Cgt DEBUG xxxxyz -D aquiacute se obtendriacutea una salida anaacuteloga a la comentada

Hemos visto un ejemplo al tratar de los servicios de interrupciones del PC aquiacute mostraremos otro Sabemos que el punto de inicio de la BIOS es la direccioacuten F000FFF0 y que desde eacutesta posicioacuten hasta el final de la memoria DOS hay 16 bytes Puede obtenerse un volcado de estas posiciones con el siguiente comando -D F000FFF0 La salida en un equipo puede ser F000FFF0 CD 19 E0 00 F0 30 36 2F-33 30 2F 39 37 00 FC 38 0630978 En este caso el comando solo muestra una liacutenea porque ha alcanzado el final de la memoria Puede verse que la fecha de la BIOS del sistema ocupa las uacuteltimas posiciones Si se ordena el volcado de una direccioacuten suficientemente alejada del final de la memoria sin indicar ninguacuten nuacutemero de posiciones por defecto se toma el valor 128 (8 filas de 16 posiciones) Si desea una cantidad distinta hay que antildeadir una L (Long) y el nuacutemero de posiciones hasta un maacuteximo de 64 KB (FFFF) Todos los nuacutemeros deben ser expresados en hexadecimal Por consiguiente los dos comandos que siguen son equivalentes (recuerde que 80 es el equivalente hexadecimal de 128) D FE000000 D FE000000 L 80 He aquiacute el resultado

Sabemos que esta zona corresponde al aacuterea de la BIOS del Sistema Otra opcioacuten muy interesante nos permite buscar determinados contenidos a traveacutes de la memoria utilizando el prefijo S (Search) Existen dos sintaxis alternativas S direccioacuten-de-inicio L longitud-a-explorar contenido-a-buscar S direccioacuten-de-inicio direccioacuten-final L contenido-a-buscar El contenido debe ser proporcionado en hexadecimal (tal como apareceriacutea en la columna central del ejemplo anterior) o entre comillas si es un texto ASCII Por ejemplo en un equipo IBM deseo ver algunas caracteriacutesticas de la BIOS Seacute que estos datos se alojan a partir de la posicioacuten F0000000 hasta el final de la memoria Es decir una longitud de 64 Kbytes (FFFF) a partir de la posicioacuten de inicio y que seguramente los datos buscados estaraacuten cerca de la identificacioacuten de la propia BIOS (la cadena IBM) Por lo que se utiliza la siguiente sintaxis [3] -s f0000000 L ffff IBM

y se obtiene la siguiente salida F000E00E F000E111 con las direcciones donde se ha encontrado la ocurrencia buscada A continuacioacuten puedo explorar las proximidades de cada posicioacuten Por ejemplo para la primera -D f000e000

Si lo que se busca estaacute en un archivo primero hay que cargarlo Lo que se puede hacer de dos formas en la propia invocacioacuten de DEBUG o mediante los comandos N y L Por ejemplo si queremos inspeccionar el contenido del archivo morecom podemos utilizar dos formas CWINDOWSgtDEBUG cwindowscommandmorecom CWINDOWSgtDEBUG - N cwindowscommandmorecom - L La sintaxis para el prefijo N es N [path-name]nombre-de-archivo En ambos casos el contenido del archivo seraacute cargado en memoria y podraacute ser utilizado Atencioacuten despueacutes de la orden L (Load) DEBUG le avisaraacute si no encuentra el archivo pero seguiraacute su funcionamiento En tal caso simplemente piensa que N sentildeala el nombre de un nuevo archivo que crearaacute con el contenido de la memoria -de DEBUG- cuando posteriormente seleccione la opcioacuten escribir W (Write)[4]

Nota Como ya habraacute deducido DEBUG permite leer un archivo realizar modificaciones en eacutel (con la opcioacuten E) y escribir el archivo modificado bajo otro nombre con NW

A continuacioacuten podemos comprobar el tamantildeo del archivo cargado Para ello usamos la opcioacuten 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 17A70100 E8CD0F CALL 10D0 -

Aquiacute nos interesa especialmente el contenido del registro CX cuyo valor 2917h (1519d) en este caso sentildeala el tamantildeo del archivo en bytes Tambieacuten podiacuteamos haber utilizado directamente el comando R CX que nos proporciona el valor de dicho registro -R CX CX 2917 -

Nota A continuacioacuten del valor correspondiente DEBUG muestra dos puntos () sentildealando que puede cambiar el valor del registro introduciendo un nuevo nuacutemero Pulse INTRO para dejar las cosas como estaacuten y volver al prompt (-) de DEBUG

Al llegar a este punto es importante sentildealar que a excepcioacuten de los archivos exe DEBUG carga los archivos a partir de la direccioacuten 100h (256d) de su memoria De forma que el primer octeto del archivo se carga en la direccioacuten 100 el segundo en 101 etc En nuestro caso el archivo se extenderaacute desde la posicioacuten 100h hasta 2A17h (100h + 2917h) A continuacioacuten para buscar la cadena Microsoft en el archivo utilizamos cualquiera de los siguientes comandos - S 100 L 2917 Microsoft - S 100 2a17 Microsoft El primer comando sentildeala el punto de inicio y el tamantildeo de la zona a buscar el segundo utiliza los puntos inicial y final de la exploracioacuten Con ambos se obtiene la misma respuesta 17A71083 17A710B2

Truco Debido a la forma especial en que se cargan los ejecutables exe si quiere inspeccionar la forma nativa de uno de estos archivos (como es su imagen en el disco) debe hacer una copia del archivo renombrarlo con cualquier otra terminacioacuten (o sin ella) y cargar esta copia En caso contrario DEBUG se prepararaacute para funcionar como un verdadero depurador de tiempo de ejecucioacuten (run-time) para lo que cargaraacute el archivo y lo acomodaraacute en memoria de forma que pueda ejecutarse [5]

Como ejercicio compruebe las distintas longitudes y aspecto (especialmente al principio) de un mismo archivo exe cargaacutendolo con DEBUG de las dos formas (busque en su sistema un exe lo maacutes pequentildeo posible) Ademaacutes de la capacidad de leer archivos antes mencionada quizaacutes una de las opciones maacutes interesantes (y peligrosas) de DEBUG es la posibilidad de leerescribir el contenido de disco a bajo nivel mediante los prefijos L (Load) y W (Write) Se utiliza la siguiente sintaxis L [Direccioacuten] [Unidad] [Primer_sector] [Nuacutemero] W [Direccioacuten] [Unidad] [Primer_sector] [Nuacutemero] El significado de los paraacutemetros es como sigue

Direccioacuten Posicioacuten de la memoria de DEBUG a partir de la cual se instalaraacuten los datos leiacutedos del disco o se tomaraacuten para el proceso de escritura (aquiacute se utiliza generalmente el valor 100h)

Unidad Valor numeacuterico que indica la loacutegica a utilizar 0 = A 1 = B 2 = C 3 = D etc [6]

Primer sector A partir del que se realizaraacute la lectura o se comenzaraacute a escribir

Nuacutemero Nuacutemero de sectores que se desea cargarescribir Como DEBUG no puede leerescribir maacutes de 64 Kbytes (2

16 = 65536) y los sectores de disco son de 512 bytes

el maacuteximo nuacutemero de sectores es 128 (80h) Asiacute pues el valor maacuteximo aquiacute es 80 Ejemplo Para obtener el contenido del sector de arranque (Master boot sector MBR) de un disquete en A utilizaremos el comando CWINDOWSgtDEBUG - L 100 0 0 1 - D 100 L 200 Como el resultado no cabe en una pantalla ingeniaremos un procedimiento para conservarlo en un archivo (maacutes adelante nos serviraacute para otro propoacutesito) Para ello creamos un archivo scripttxt con el siguiente contenido (dos INTRO despueacutes de la Q) L 100 0 0 1 D 100 L 200 Q A continuacioacuten invocamos DEBUG con el comando CWINDOWSgtDEBUG lt Dbuzonscripttxt gt Dbuzonresultadtxt Despueacutes de un breve parpadeo del disco y del disquete vuelve el prompt del DOS La operacioacuten ha concluido y en el directorio correspondiente de la unidad D tenemos el archivo resultadtxt con el volcado del sector de arranque del disquete ademaacutes de los ecos de los comandos introducidos (los hemos mantenido para orientacioacuten del lector) Otra forma de poder visualizar el contenido del Sector de Arranque del disco es utilizando el DEBUG Por ejemplo dentro del DEBUG tecleamos lo siguiente -L 100 0 0 1

-D 100 L 200

177C0100 EB 3E 90 2B 79 73 57 29-49 48 43 00 02 01 01 00 gt+ysW)IHC

177C0110 02 E0 00 40 0B F0 09 00-12 00 02 00 00 00 00 00

177C0120 00 00 00 00 00 00 29 5D-3B DD 10 4E 4F 20 4E 41 )]NO NA

177C0130 4D 45 20 20 20 20 46 41-54 31 32 20 20 20 F1 7D ME FAT12

177C0140 FA 33 C9 8E D1 BC FC 7B-16 07 BD 78 00 C5 76 00 3xv

177C0150 1E 56 16 55 BF 22 05 89-7E 00 89 4E 02 B1 0B FC VU~N

177C0160 F3 A4 06 1F BD 00 7C C6-45 FE 0F 8B 46 18 88 45 |EFE

177C0170 F9 FB 38 66 24 7C 04 CD-13 72 3C 8A 46 10 98 F7 8f$|rltF

177C0180 66 16 03 46 1C 13 56 1E-03 46 0E 13 D1 50 52 89 fFVFPR

177C0190 46 FC 89 56 FE B8 20 00-8B 76 11 F7 E6 8B 5E 0B FV v^

177C01A0 03 C3 48 F7 F3 01 46 FC-11 4E FE 5A 58 BB 00 07 HFNZX

177C01B0 8B FB B1 01 E8 94 00 72-47 38 2D 74 19 B1 0B 56 rG8-tV

177C01C0 8B 76 3E F3 A6 5E 74 4A-4E 74 0B 03 F9 83 C7 15 vgt^tJNt

177C01D0 3B FB 72 E5 EB D7 2B C9-B8 D8 7D 87 46 3E 3C D8 r+Fgtlt

177C01E0 75 99 BE 80 7D AC 98 03-F0 AC 84 C0 74 17 3C FF utlt

177C01F0 74 09 B4 0E BB 07 00 CD-10 EB EE BE 83 7D EB E5 t

177C0200 BE 81 7D EB E0 33 C0 CD-16 5E 1F 8F 04 8F 44 02 3^D

177C0210 CD 19 BE 82 7D 8B 7D 0F-83 FF 02 72 C8 8B C7 48 rH

177C0220 48 8A 4E 0D F7 E1 03 46-FC 13 56 FE BB 00 07 53 HNFVS

177C0230 B1 04 E8 16 00 5B 72 C8-81 3F 4D 5A 75 A7 81 BF [rMZu

177C0240 00 02 42 4A 75 9F EA 00-02 70 00 50 52 51 91 92 BJupPRQ

177C0250 33 D2 F7 76 18 91 F7 76-18 42 87 CA F7 76 1A 8A 3vvBv

177C0260 F2 8A 56 24 8A E8 D0 CC-D0 CC 0A CC B8 01 02 CD V$

177C0270 13 59 5A 58 72 09 40 75-01 42 03 5E 0B E2 CC C3 YZXruB^

177C0280 03 18 01 27 0D 0A 44 69-73 63 6F 20 69 6E 63 6F Disco inco

177C0290 72 72 65 63 74 6F 20 20-20 FF 0D 0A 45 72 72 6F rrecto Erro

177C02A0 72 20 45 2F 53 20 20 20-20 20 FF 0D 0A 43 61 6D r ES Cam

177C02B0 62 69 65 20 65 6C 20 64-69 73 63 6F 20 79 20 70 bie el disco y p

177C02C0 72 65 73 69 6F 6E 65 20-75 6E 61 20 74 65 63 6C resione una tecl

177C02D0 61 20 20 20 20 0D 0A 00-49 4F 20 20 20 20 20 20 a IO

177C02E0 53 59 53 4D 53 44 4F 53-20 20 20 53 59 53 80 01 SYSMSDOS SYS

177C02F0 00 57 49 4E 42 4F 4F 54-20 53 59 53 00 00 55 AA WINBOOT SYSU

-

-Q

FIN [1] En las primeras versiones de MS-DOS era un modesto programita DEBUGCOM de apenas 16 KB La versioacuten que acompantildea a Windows98 es ya un ejecutable en formato EXE de 21 KB [2] En realidad DEBUG es una utilidad de enorme potencia que requeririacutea todo un libro para ella sola Puede encontrarse una amplia descripcioacuten de esta herramienta en el libro de Paul Somerson PC Magazine DOS Powers Tools [3] Desgraciadamente no hay una convencioacuten estaacutendar sobre la colocacioacuten de los datos en la BIOS de forma que cada fabricante sigue sus propias reglas y es imposible por tanto utilizarla para cualquier tipo de identificacioacuten del sistema [4] En palabras del mencionado Paul Somerson Desgraciadamente debido a que DEBUG es un programa tan increiacuteblemente potente tambieacuten es increiacuteblemente peligroso Hay un dicho que afirma que El software no puede destruir el hardware Desgraciadamente esto no es cierto Ademaacutes de enviar mecanismos sensibles de la unidad de disco a tierra de nadie es posible hacer saltar monitores o transformadores Repito si sigue al pie de la letra las instrucciones y hace caso a todos los avisos todo iraacute bien [5] Recuerde que la imagen de un ejecutable exe cargado en memoria es distinta de su imagen en disco Solo en los ejecutables com la imagen en disco es una imagen exacta de su disposicioacuten en memoria [6] Es evidente que un pequentildeo error de nuacutemero en este paraacutemetro puede acarrear consecuencias nefastas Por ejemplo si cree que estaacute jugando con el disquete e inadvertidamente se dirige al disco duro (relea la nota [4])

Page 9: El Comando DEBUG

F FILL F ltbloquegt ltvalor de rellenogt Este comando llena un bloque de memoria con un valor especiacutefico o una serie de valores La sintaxis es F ltbloquegt ltvalor de rellenogt ltbloquegt es la direccioacuten de inicio y final o si se preceden con L la direccioacuten de inicio y la longitud del bloque ltvalor de rellenogt es(son) el(los) valor(es) con los que debe de llenarse el bloque Si ltvalor de rellenogt 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 liacuteneas llena (con 0rsquos) el bloque DS00FF F DS0000 DS00FF 0 DS0000 LFF 0 Ejemplo -f 100 105 66 -d 100 105 20480100 66 66 66 66 66 66 ffffff Q QUIT Q Salir de DEBUG y volver al DOS P PROCEED P lt=direccioacutengtltnuacutemerogt Similar al comando T pero al encontrarse un CALL o INT lo ejecuta de golpe sin entrar en su interior (ojo iexclesto uacuteltimo falla al tracear sobre memoria ROM) Trace puede ser incoacutemodo si no se quiere depurar el coacutedigo de las rutinas de interrupcioacuten o si ya se sabe el coacutedigo que hay en las subrutinas y tan soacutelo interesa seguir avanzando sin entrar en ellas En estos casos se usa p por lo que si ejecutamos una interrupcioacuten de MS-DOS no sabriacuteamos 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 20480107 3D5000 CMP AX0050 -a 100 20480100 mov ax0200 20480103 mov dl61 20480105 int 21 20480107 -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 20480103 B261 MOV DL61 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 20480105 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 20480107 3D5000 CMP AX0050 T TRACE T lt=direccioacutengt ltvalorgt Ejecuta una instruccioacuten del programa (a partir de CSIP) mostrando a continuacioacuten el estado de los registros y la siguiente instruccioacuten Ejecutar T10 equivaldriacutea a ejecutar 16 veces el comando T Si la instruccioacuten es CALL o INT se ejecutaraacute como tal introducieacutendose 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 20480100 3D0000 CMP AX0000 -r bx BX 0000 2 -a 100 20480100 mov axbx 20480102 -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 20480102 00AC01D8 ADD [SI+D801]CH DSD801=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 20480100 3D0000 CMP AX0000 -a 100 20480100 mov axbx 20480102 mov cxbx 20480104 -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 20480102 89D9 MOV CXBX 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 20480104 01D8 ADD AXBX

N NAME N ltnombre_archivogt Se asigna un nombre al programa que estaacute siendo creado o modificado Se puede indicar la trayectoria de directorios L LOAD L ltbuffergt ltnumdiscogt ltsectorinigt ltnumsectorgt ltbuffergt es la direccioacuten en donde se carga la informacioacuten ltnumdiscogt es el nuacutemero (opcional) del disco de donde se leeraacute la informacioacuten (0=A 1=B 2=C etc) ltsectorinigt es el sector de disco absoluto (en hexadecimal) a leer ltnumsectorgt es la cantidad de sectores a leer No se pueden leer maacutes de 80H (128) sectores Si no se suministra la combinacioacuten ltnumdiscogt ltsectorinigt ltnumsectorgt DEBUG presume que se desea leer un archivo En este caso ltbuffergt es opcional Debe usarse el comando N (ver maacutes adelante) para especificar el archivo a leer Eacuteste se carga en CS0100 Ejemplo Se va a leer el sector 0 del disco A y se vuelca a partir de la direccioacuten DS100 como se puede observar el disco contiene mucha informacioacuten ( ESTO NO QUIERE DECIR QUE TENGA QUE SALIR LO MISMO EN SU VOLCADO )

l 100 0 0 1 -d 100 300

W WRITE W ltdireccioacutengt Graba el contenido de una zona de memoria a disco Si no se indica la direccioacuten se graba desde CS100h hasta CS100h+nuacutemero_bytes el nuacutemero de bytes se indica en BXCX (no es una direccioacuten segmentada sino un valor de 32 bits) Si se trata de un EXE no se permitiraacute grabarlo (para modificarlos hay que renombrarles para cambiarles la extensioacuten aunque de esta manera no seraacuten montados al cargarlos) La sintaxis es W ltbuffergt ltnumdiscogt ltsectorinigt ltnumsectorgt ltbuffergt es la direccioacuten de donde se carga la informacioacuten ltnumdiscogt es el nuacutemero (opcional) del disco en donde se escribiraacute la informacioacuten (0=A 1=B 2=C etc) ltsectorinigt es el sector de disco absoluto (en hexadecimal) en donde empieza la escritura ltnumsectorgt es la cantidad de sectores a leer No se pueden escribir maacutes de 80H (128) sectores Si no se suministra la combinacioacuten ltnumdiscogt ltsectorinigt ltnumsectorgt DEBUG presume que el inicio de archivo es CS100 En este caso ltbuffergt es opcional Debe usarse el comando N (ver arriba) para especificar el archivo a escribir Antes de escribir BXCX debe ajustarse al nuacutemero de bytes que desean grabarse W no puede escribir a archivos con la extensioacuten EXE o HEX [5] Ejemplo

N ltnomarchivogt BXCX lt--- 2000 W

S SEARCH S ltrangogt ltlistagt Busca una cadena de bytes por la memoria Para buscar la cadena PEPE terminada por cero en un aacuterea de 512 bytes desde DS100 se hariacutea S 100 L 200 PEPE0 (por defecto se busca en DS) No se encontrariacutea sin embargo pepe (en minuacutesculas) C COMPARE C ltrangogt ltdireccioacutengt Compara dos zonas de memoria mostrando las diferencias Por ejemplo para comparar 5 bytes de DS100 y DS200 se hace C 100 L 5 200 M MOVE M ltrangogt ltdireccioacutengt Maacutes que mover copia una zona de memoria en otra de manera inteligente (controlando los posibles solapamientos de los bloques) I INPUT I ltpuertogt Visualiza la lectura del puerto de ES indicado

O OUTPUT O ltpuertogt ltvalorgt Enviacutea un valor a un puerto de ES H HEX H ltvalor1gt ltvalor2gt Muestra la suma y resta de valor1 y valor2 ambos operandos de un maacuteximo de 16 bits (si hay desbordamiento se trunca el resultado que tampoco excede los 16 bits) Resultado ltresultado_1gt Es la suma ( ltvalor1gt + ltvalor2gt) ltresultado_2gt es la resta (ltvalor1gt - ltvalor2gt ) Ejemplo -h 0003 0002 0005 0001 -h 0000 0001 0001 FFFF como se observa el resultado de la segunda operacioacuten es FFFF que es el equivalente en complemento a 2 de -1 G GO G =ltiniciogt ltquiebre1gt ltquiebre2gt ltquiebre10gt Este comando ejecuta el coacutedigo en memoria Si se estaacute depurando un programa permite ejecutar el coacutedigo cargado en memoria Tambieacuten permite establecer puntos de quiebre (breakpoints) que son direcciones en las que se detiene la ejecucioacuten del programa La sintaxis es G =ltiniciogt ltquiebre1gt ltquiebre2gt ltquiebre10gt ltiniciogt es la direccioacuten de inicio de ejecucioacuten ltquiebre1gt hasta ltquiebre10gt son direcciones opcionales de paro del programa Si no se especifica ltiniciogt Go inicia con la direccioacuten contenida en CSIP Para lograr los quiebres DEBUG reemplaza el coacutedigo en las direcciones de quiebre por el valor hexadecimal CC que es el coacutedigo de interrupcioacuten Si DEBUG llega a CC todos los puntos de quiebre son restituidos los registros se despliegan (como con el comando R [veacutease adelante]) y se para la ejecucioacuten U UNASSEMBLE U ltrangogt Este comando desensambla el contenido de la memoria a partir de la posicioacuten actual Registros y Banderas del DEBUG La mayoriacutea de los comandos de DEBUG ejecutan una accioacuten y vuelven al indicador del shell pero si es un comando largo como puede ser mostrar un trozo grande de coacutedigo puede detenerse pulsando CTRL-Pausa o interrumpirse con CTRL-C para volver al shell Por ejemplo al teclear lo siguiente

- r [Enter]

-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 17A70100 E8CD0F CALL 10D0 - Se desplegaran todos los contenidos de los registros internos del microprocesador una forma alternativa de mostrarlos es usar el comando r utilizando como paraacutemetro el nombre del registro cuyo valor se quiera visualizar Por ejemplo

- r bx Esta instruccioacuten desplegaraacute uacutenicamente el contenido del registro BX y cambia el indicador del DEBUG de - a Estando asiacute el prompt es posible cambiar el valor del registro que se visualizoacute tecleando el nuevo valor y a continuacioacuten [Enter] o se puede dejar el valor anterior presionando [Enter] sin teclear ninguacuten valor Es posible cambiar el valor del registro de banderas asiacute como utilizarlo como estructura de control en nuestros programas como se veraacute maacutes adelante Cada bit del registro tiene un nombre y significado especial la lista dada a continuacioacuten describe el valor de cada bit tanto apagado como prendido y su relacioacuten con las operaciones del microprocesador

Overflow (O) NV = no hay desbordamiento OV = si lo hay Direction (D) UP = hacia adelante DN = hacia atraacutes Interrupts (I) DI = desactivadas EI = activadas Sign (S) PL = positivo NG = negativo Zero (Z) NZ = no es cero ZR = s lo es Auxiliary Carry (A) NA = no hay acarreo auxiliar

AC = hay acarreo auxiliar Parity (P) PO = paridad non PE = paridad par Carry (C) NC = no hay acarreo CY = Si lo hay

La estructura del ensamblador En el lenguaje ensamblador las liacuteneas de coacutedigo constan de dos partes la primera es el nombre de la instruccioacuten que se va a ejecutar y la segunda son los paraacutemetros del comando u operandos Por ejemplo

add ahbh Aquiacute add es el comando a ejecutar (en este caso una adicioacuten) y tanto ah como bh son los paraacutemetros El nombre de las instrucciones en este lenguaje estaacute formado por dos tres o cuatro letras a estas instrucciones tambieacuten se les llama nombres mnemoacutenicos o coacutedigos de operacioacuten ya que representan alguna funcioacuten que habraacute de realizar el microprocesador Existen algunos comandos que no requieren paraacutemetros para su operacioacuten asiacute como otros que requieren solo un paraacutemetro Algunas veces se utilizaraacuten las instrucciones como sigue

add al[170] Los corchetes en el segundo paraacutemetro nos indican que vamos a trabajar con el contenido de la posicioacuten de memoria nuacutemero 170 y no con el valor 170 a esto se le conoce como direccionamiento directo Primer programa en ensamblador con el DEBUG Vamos a crear un programa que sirva para ilustrar lo que hemos estado viendo lo que haremos seraacute una suma de dos valores que introduciremos directamente en el programa El primer paso es iniciar el DEBUG este paso consiste uacutenicamente en teclear DEBUG [Enter] en el prompt del sistema operativo Para ensamblar un programa en el DEBUG se utiliza el comando a (assemble) cuando se utiliza este comando se le puede dar como paraacutemetro la direccioacuten donde se desea que se inicie el ensamblado Si se omite el paraacutemetro el ensamblado se iniciaraacute en la localidad especificada por CSIP usualmente 0100H que es la localidad donde deben iniciar los programas con extensioacuten COM y seraacute la localidad que utilizaremos debido a que DEBUG solo puede crear este tipo especiacutefico de programas

Aunque en este momento no es necesario darle un paraacutemetro al comando a es recomendable hacerlo para evitar problemas una vez que se haga uso de los registros CSIP por lo tanto tecleamos

- a 100 [Enter] Al hacer esto apareceraacute en la pantalla algo como 0C1B0100 y el cursor se posiciona a la derecha de estos nuacutemeros noacutetese que los primeros cuatro diacutegitos (en sistema hexadecimal) pueden ser diferentes pero los uacuteltimos cuatro deben ser 0100 ya que es la direccioacuten que indicamos como inicio Ahora podemos introducir las instrucciones

0C1B0100 mov ax0002 coloca el valor 0002 en el registro ax 0C1B0103 mov bx0004 coloca el valor 0004 en el registro bx 0C1B0106 add axbx le adiciona al contenido de ax el contenido de bx 0C1B0108 int 20 provoca la terminacioacuten del programa 0C1B010A

No es necesario escribir los comentarios que van despueacutes del Una vez escrito el uacuteltimo comando int 20 se le da [Enter] sin escribir nada maacutes para volver al prompt del DEBUG La uacuteltima liacutenea escrita no es propiamente una instruccioacuten de ensamblador es una llamada a una interrupcioacuten del sistema operativo estas interrupciones seraacuten tratadas maacutes a fondo en un capiacutetulo posterior por el momento solo es necesario saber que nos ahorran un gran nuacutemero de liacuteneas y son muy uacutetiles para accesar a funciones del sistema operativo Para ejecutar el programa que escribimos se utiliza el comando g al utilizarlo veremos que aparece un mensaje que dice Program terminated normally Naturalmente con un mensaje como eacuteste no podemos estar seguros que el programa haya hecho la suma pero existe una forma sencilla de verificarlo utilizando el comando r del DEBUG podemos ver los contenidos de todos los registros del microprocesador simplemente teclee

- r [Enter] Apareceraacute en pantalla cada registro con su respectivo valor actual -R AX=0006 BX=0004 CX=0000 DX=0000 SP=FFFE BP=0000 SI=0000 DI=0000 DS=0C1B ES=0C1B SS=0C1B CS=0C1B IP=010A NV UP EI PL NZ NA PO NC 17A70100 E8CD0F CALL 10D0 - Existe la posibilidad de que los registros contengan valores diferentes pero AX y BX deben ser los mismos ya que son los que acabamos de modificar Otra forma de ver los valores mientras se ejecuta el programa es utilizando como paraacutemetro para g la direccioacuten donde queremos que termine la ejecucioacuten y muestre los valores de los registros en este caso seraacute g108 esta instruccioacuten ejecuta el programa se detiene en la direccioacuten 108 y muestra los contenidos de los registros Tambieacuten se puede llevar un seguimiento de lo que pasa en los registros utilizando el comando t (trace) la funcioacuten de este comando es ejecutar liacutenea por liacutenea lo que se ensambloacute mostrando cada vez los contenidos de los registros Para salir del DEBUG se utiliza el comando q (quit)

Guardar y cargar los programas No seriacutea praacutectico tener que escribir todo un programa cada vez que se necesite para evitar eso es posible guardar un programa en el disco con la enorme ventaja de que ya ensamblado no seraacute necesario correr de nuevo DEBUG para ejecutarlo ya que cuando el DEBUG guardo nuestro programa en el disco eacuteste se guardo en binario (archivo con la extensioacuten com) Los pasos a seguir para guardar un programa ya almacenado en la memoria son

Obtener la longitud del programa restando la direccioacuten final de la direccioacuten inicial naturalmente en sistema hexadecimal

Darle un nombre al programa y una extensioacuten

Poner la longitud del programa en el registro CX

Ordenar a DEBUG que escriba el programa en el disco Utilizando como ejemplo el programa del ejemplo anterior tendremos una idea maacutes clara de coacutemo llevar estos pasos Al terminar de ensamblar el programa se veriacutea asiacute

0C1B0100 mov ax0002 0C1B0103 mov bx0004 0C1B0106 add axbx 0C1B0108 int 20 0C1B010A

Para almacenarlo en el disco hacemos lo siguiente - h 10a 100 020a 000a - n pruebacom - r cx CX 0000 000a -w Writing 000A bytes

Para obtener la longitud de un programa se utiliza el comando h el cual nos muestra la suma y resta de dos nuacutemeros en hexadecimal Para obtener la longitud del programa le proporcionamos como paraacutemetros el valor de la direccioacuten final de nuestro programa (10A) y el valor de la direccioacuten inicial (0100) El primer resultado que nos muestra el comando es la suma de los paraacutemetros y el segundo es la resta El comando n nos permite poner un nombre al programa El comando r cx nos permite cambiar el contenido del registro CX al valor que obtuvimos del tamantildeo del archivo con h en este caso 000a ya que nos interesa el resultado de la resta de la direccioacuten inicial a la direccioacuten final

Por uacuteltimo el comando w escribe nuestro programa en el disco indicaacutendonos cuantos bytes escribioacute

NOTA Si se trabaja en una ventana de DOS de Windows Vista o 7 es probable que al momento de guardar su programa el DEBUG escriba mas coacutedigo que el sentildealado por el registro CX por consiguiente seraacute necesario limpiar el registro BX esto es ponerlo a ceros y despueacutes utilizar el comando w Por ejemplo _r bx BX 000E 0000 w

Para cargar un archivo ya guardado son necesarios dos pasos

Proporcionar el nombre del archivo que se cargaraacute a memoria

Cargarlo utilizando el comando l (load) Para obtener el resultado correcto de los siguientes pasos es necesario que previamente se haya creado el programa anterior Dentro del DEBUG escribimos lo siguiente

- n pruebacom - l - u 100 109 0C3D0100 B80200 MOV AX0002 0C3D0103 BB0400 MOV BX0004 0C3D0106 01D8 ADD AXBX 0C3D0108 CD20 INT 20

El uacuteltimo comando u se utiliza para verificar que el programa se cargoacute en memoria lo que hace es desensamblar el coacutedigo y mostrarlo ya desensamblado Los paraacutemetros le indican a DEBUG desde donde y hasta donde desensamblar DEBUG siempre carga los programas en memoria en la direccioacuten 100H a menos que se le indique alguna otra Un programa que realiza un conteo en pantalla Con el DEBUG es posible escribir un programa que realice un conteo en pantalla por razones de comprensioacuten nuestro programa solo realizara un conteo de 9 a 0 (conteo descendente) 0B3B0100 B90A00 MOV CX000A CX=10 en decimal 0B3B0103 88CA MOV DLCL 0B3B0105 80C22F ADD DL2F sumamos 02Fh a DL 0B3B0108 B402 MOV AH02 funcioacuten 02 de INT 21 para imprimir un caracter 0B3B010A CD21 INT 21

0B3B010C E2F5 LOOP 0103 CX=0 Si no salta a 0103 0B3B010E CD20 INT 20 termina el programa En la liacutenea 0103 se puede observar que el valor del registro CX en su parte baja (en CL) se almacena en el registro DL Si se omitiera la liacutenea 0105 entonces cuando se ejecutara la liacutenea 010A solo se imprimiriacutea en pantalla el coacutedigo ASCII del valor que contenga DL (el coacutedigo ASCII de 0Ah que es 10 en decimal es un caraacutecter especial no imprimible) Para conseguir el ldquoefectordquo de que el programa realiza el conteo en decimal se hace un corrimiento de 02F (47 en decimal) Por ejemplo cuando se ejecuta la liacutenea 0105 DL tendriacutea el valor de 39h=57d (02Fh+0Ah=39h=57d) y el coacutedigo ASCII de 57d es el caraacutecter ldquo9rdquo El sentencia LOOP decrementa CX en 1 si CX es diferente a 0 salta a la liacutenea 0103 El proceso se repite y el programa imprime en pantalla 9876543210 Seriacutea interesante que el programa anterior fuera modificado para que la numeracioacuten se imprimiera de la siguiente manera 9 8 7 6 5 4 3 2 1 0

NOTA Como se dijo anteriormente cuando el DEBUG almacena un programa en el disco este archivo se graba en binario esto es en ejecutable Por lo tanto no es necesario cargar el DEBUG para volver a ejecutar nuestro programa sino que se hace de manera directa desde DOS El problema surge cuando al ejecutar nuestro programa el resultado no se puede observar porque el DOS borra la pantalla despueacutes de terminar de ejecutar el programa Para evitar el borrado automaacutetico seraacute necesario agregarle a nuestro programa antes de la INT 20h una instruccioacuten para la lectura de un caraacutecter desde el teclado Para tal efecto utilizaremos la funcioacuten 08 de la INT 21h (un buen truco para que el programa haga una pausa) asiacute el programa esperara hasta que el usuario presiona una tecla permitiendo observar el resultado Ejemplo mov ah08 Int 21 Int 20

Condiciones ciclos y bifurcaciones Estas estructuras o formas de control le dan a la maacutequina un cierto grado de decisioacuten basado en la informacioacuten que recibe La forma maacutes sencilla de comprender este tema es por medio de ejemplos Vamos a crear tres programas que hagan lo mismo desplegar un nuacutemero determinado de veces una cadena de caracteres en la pantalla

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV CX000F veces que se desplegara la cadena 0C1B0128 MOV DX0102 copia cadena al registro DX 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F LOOP 012D si CXgt0 salta a 012D 0C1B0131 INT 20 termina el programa

Por medio del comando e es posible introducir una cadena de caracteres en una determinada localidad de memoria dada como paraacutemetro la cadena se introduce entre comillas le sigue un espacio luego el valor hexadecimal del retorno de carro un espacio el valor de liacutenea nueva y por uacuteltimo el siacutembolo $ que el ensamblador interpreta como final de la cadena La interrupcioacuten 21 utiliza el valor almacenado en el registro AH para ejecutar una determinada funcioacuten en este caso mostrar la cadena en pantalla la cadena que muestra es la que estaacute almacenada en el registro DX La instruccioacuten LOOP decrementa automaacuteticamente el registro CX en uno y si no ha llegado el valor de este registro a cero salta a la posicioacuten de memoria indicada como paraacutemetro lo cual crea un ciclo que se repite el nuacutemero de veces especificado por el valor de CX La interrupcioacuten 20 termina la ejecucioacuten del programa Otra forma de realizar la misma funcioacuten pero sin utilizar el comando LOOP es la siguiente

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV BX000F veces que se desplegara la cadena 0C1B0128 MOV DX0102 copia cadena al registro DX 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F DEC BX decrementa en 1 a BX 0C1B0130 JNZ 012D si BX es diferente a 0 salta a 012D 0C1B0132 INT 20 termina el programa

En este caso se utiliza el registro BX como contador para el programa y por medio de la instruccioacuten DEC se disminuye su valor en 1 La instruccioacuten JNZ verifica si el valor de BX es diferente a 0 esto con base en la bandera NZ en caso afirmativo salta hacia la direccioacuten 012D En caso contrario continuacutea la ejecucioacuten normal del programa y por lo tanto se termina Una uacuteltima variante del programa es utilizando de nuevo a CX como contador pero en lugar de utilizar LOOP utilizaremos decrementos a CX y comparacioacuten de CX a 0

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV DX0102 copia cadena al registro DX 0C1B0128 MOV CX000F veces que se desplegara la cadena 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F DEC CX decrementa en 1 a CX 0C1B0130 JCXZ 0134 si CX es igual a 0 salta a 0134 0C1B0132 JMP 012D salta a la direccioacuten 012D 0C1B0134 INT 20 termina el programa

En este ejemplo se usoacute la instruccioacuten JCXZ para controlar la condicioacuten de salto el significado de tal funcioacuten es salta si CX=0 El tipo de control a utilizar dependeraacute de las necesidades de programacioacuten en determinado momento

Manipulacioacuten de Posiciones de Memoria Con el DEBUG es posible almacenar y recuperar datos numeacutericos en memoria por medio de un programa a traveacutes de los registros del microprocesador Por ejemplo el siguiente programa almacena previamente dos valores numeacutericos en la posicioacuten 0300h y 0400h respectivamente despueacutes el programa los recupera realiza la operacioacuten de suma con esos valores y el resultado lo almacena en la posicioacuten 0500h -a 100 0B1C0100 mov ax0002 ax=2 0B1C0103 mov [0300]ax almacenamos 2 en la direccioacuten 0300h 0B1C0106 mov ax0004 ax=4 0B1C0109 mov [0400]ax almacenamos 4 en la direccioacuten 0400h 0B1C010C mov ax[0300] recuperamos el dato1 en AX 0B1C010F mov bx[0400] recuperamos el dato2 en BX 0B1C0113 add axbx hacemos la operacioacuten de suma en AX 0B1C0115 mov [0500]ax almacenamos el 6 en la direccioacuten 0500h 0B1C0118 int 21 0B1C011A - Un nuacutemero entre corchetes [numero_hex] indica una posicioacuten de memoria y su manejo se hace a traveacutes de registros ya que no es posible almacenar valores numeacutericos de manera directa Ejecutamos el programa -g 118 AX=0006 BX=0004 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=0B1C ES=0B1C SS=0B1C CS=0B1C IP=0118 NV UP EI PL NZ NA PE NC 0B1C0118 CD21 INT 21 - Para ver si el resultado se almaceno en la direccioacuten correcta hacemos

Como se puede observar en la direccioacuten 0B1C0500 se encuentra el 06 y en 0B1C0501 se encuentra el 00 que es el resultado de la operacioacuten 2+4 Perohellip Porque aparece el 06 y despueacutes el 00 pareceriacutea que el resultado fue de 0600 pero no es asiacute lo que sucedes que los datos se almacenan en memoria de la siguiente manera

Como se hizo la operacioacuten AX=AX+BX entonces el resultado es de 16 bits (dos bytes) AX=6 entonces AX=0000 0000 0000 0110 (16 bits) por lo tanto los 8 bits de menor peso de AX son 0000 0110 y deben almacenarse en la direccioacuten 0500 y en la direccioacuten 0501 se almacena 0000 0000

0 0 0 0 0 1 1 0 0500

0 0 0 0 0 0 0 0 0501

x x x x x x x x 0502

x x x x x x x x 0503

x x x x x x x x 0504

x x x x x x x x 0505

Interrupciones Definicioacuten de interrupcioacuten

Una interrupcioacuten es una instruccioacuten que detiene la ejecucioacuten de un programa para permitir el uso del microprocesador en un proceso prioritario Una vez concluido este uacuteltimo proceso se devuelve el control a la aplicacioacuten anterior

Por ejemplo cuando estamos trabajando con un procesador de palabras y en ese momento llega un aviso de uno de los puertos de comunicaciones se detiene temporalmente la aplicacioacuten que estaacutebamos utilizando para permitir el uso del microprocesador al manejo de la informacioacuten que estaacute llegando en ese momento Una vez terminada la transferencia de informacioacuten se reanudan las funciones normales del procesador de palabras Las interrupciones ocurren muy seguido sencillamente la interrupcioacuten que actualiza la hora del diacutea ocurre aproximadamente 18 veces por segundo Para lograr administrar todas estas interrupciones la computadora cuenta con un espacio de memoria llamado memoria baja donde se almacenan las direcciones de cierta localidad de memoria donde se encuentran un juego de instrucciones que el microprocesador ejecutaraacute para despueacutes regresar a la aplicacioacuten que estaba en proceso En los programas anteriores hicimos uso de la interrupcioacuten nuacutemero 20H para terminar la ejecucioacuten de nuestros programas y en otros ejemplos utilizamos otra interrupcioacuten para mostrar informacioacuten en pantalla (INT 21h) Utilizando DEBUG tecleamos

- a100 2C1B0100 JMP 011D 2C1B0102 [ENTER] - E 102 Hola como estas 0D 0A $ - A011D 2C1B011D MOV DX0102 2C1B0120 MOV AH09 2C1B0122 INT 21 2C1B0123 INT 20

Orden

creciente

de la

memoria

En este programa la interrupcioacuten 21h manda al monitor la cadena localizada en la direccioacuten a la que apunta el registro DX El valor que se le da a AH determina cual de las opciones de la interrupcioacuten 21h seraacute utilizada ya que esta interrupcioacuten cuenta con varias opciones El manejo directo de interrupciones es una de las partes maacutes fuertes del lenguaje ensamblador ya que con ellas es posible controlar eficientemente todos los dispositivos internos y externos de una computadora gracias al completo control que se tiene sobre operaciones de entrada y salida Maacutes del DEBUG Una caracteriacutestica poco conocida es que DEBUG puede aceptar entradas desde un archivo Script que puede ser un simple archivo de texto ASCII en el que cada comando esteacute separado del anterior por un INTRO Despueacutes del uacuteltimo que debe ser una Q para salir de DEBUG es conveniente dejar una liacutenea en blanco pulsando INTRO dos veces Las liacuteneas pueden contener comentarios Cualquier cosa a partir del caracter punto y coma () hasta el final de la liacutenea seraacute ignorado esto es un comentario D aquiacute se mostraraacute algo Suponiendo que tengamos un archivo Script de nombre Ordenestxt puede ser utilizado como entrada para DEBUG mediante un comando de redireccioacuten en la siguiente forma DEBUG lt ordenestxt Tambieacuten puede conseguirse que el programa redireccione la salida hacia un archivo que puede ser inspeccionado maacutes 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 podriacutea obtenerse un archivo Resulttxt con el siguiente comando DEBUG lt ordenestxt gt Resulttxt Errores Cuando DEBUG no sabe interpretar un comando muestra un mensaje de error y un indicador ^ debajo del sitio del comando donde estaacute el error Entradas y Salidas DEBUG asume que los datos numeacutericos proporcionados son hexadecimales y cuando se trate de direcciones de memoria deben introducirse en forma segmentada A su vez los resultados son mostrados tambieacuten 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

Cada fila muestra 16 posiciones de memoria a partir de la posicioacuten sentildealada por las columnas de la izquierda que las muestran como segmentodesplazamiento El bloque central muestra el contenido hexadecimal de cada byte mientras que el bloque derecho contiene la representacioacuten ASCII Por ejemplo la 3ra fila muestra el contenido de las posiciones 0B770120 a 0B77012F (ambas inclusive) Sus tres uacuteltimos bytes contienen respectivamente los caracteres r 9 y 2 que corresponden a las cantidades 72h 39h y 32h del bloque central Que como sabemos equivalen a los decimales 114 57 y 50 que son precisamente los valores ASCII de los caracteres ldquorrdquo ldquo9rdquo y ldquo2rdquo anteriormente mencionados

Nota Por razoacuten de que eacuteste tipo de salida pueda ser listado a impresora el bloque derecho no contiene en realidad la representacioacuten ASCII de todos los caracteres (algunos ni siquiera tienen una representacioacuten imprimible) En realidad solo se muestran los caracteres imprimibles del primer bloque (US-ASCII) El resto estaacute 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 caraacutecter imprimible Esto no significa que dichas posiciones representen efectivamente tales valores para la aplicacioacuten que las utiliza Por ejemplo puede que en realidad las dos posiciones de memoria mencionadas (dos octetos o bytes) en vez de los caracteres ldquo5rdquo y ldquoardquo representen una palabra de 16 bits en formato Little Endian que a su vez representan una cantidad entera (un nuacutemero) Comandos Aunque su descripcioacuten completa llenariacutea todo un capiacutetulo a continuacioacuten comentamos algunas de las opciones maacutes interesantes relativas a inspeccioacuten del coacutedigo y de contenidos de memoria La opcioacuten D (Dump) permite obtener un volcado del contenido de la memoria (de DEBUG) La sintaxis acepta dos formas D [direccioacuten-inicial] [L posiciones-desde-direccioacuten-inicial ] D [direccioacuten-inicial][direccioacuten-final] Naturalmente para que exista algo en el buacutefer de memoria (al principio quizaacutes solo contiene basura) es preciso indicarle que lea algo Este algo puede ser un rango de direcciones de memoria RAM una direccioacuten absoluta de disco (sector) un archivo o el contenido de los registros del procesador Para empezar puede indicaacutersele que cargue un archivo xxxxyz que tenemos en el directorio actual o en el PATH cuyo contenido queremos ver Cgt DEBUG xxxxyz -D aquiacute se obtendriacutea una salida anaacuteloga a la comentada

Hemos visto un ejemplo al tratar de los servicios de interrupciones del PC aquiacute mostraremos otro Sabemos que el punto de inicio de la BIOS es la direccioacuten F000FFF0 y que desde eacutesta posicioacuten hasta el final de la memoria DOS hay 16 bytes Puede obtenerse un volcado de estas posiciones con el siguiente comando -D F000FFF0 La salida en un equipo puede ser F000FFF0 CD 19 E0 00 F0 30 36 2F-33 30 2F 39 37 00 FC 38 0630978 En este caso el comando solo muestra una liacutenea porque ha alcanzado el final de la memoria Puede verse que la fecha de la BIOS del sistema ocupa las uacuteltimas posiciones Si se ordena el volcado de una direccioacuten suficientemente alejada del final de la memoria sin indicar ninguacuten nuacutemero de posiciones por defecto se toma el valor 128 (8 filas de 16 posiciones) Si desea una cantidad distinta hay que antildeadir una L (Long) y el nuacutemero de posiciones hasta un maacuteximo de 64 KB (FFFF) Todos los nuacutemeros deben ser expresados en hexadecimal Por consiguiente los dos comandos que siguen son equivalentes (recuerde que 80 es el equivalente hexadecimal de 128) D FE000000 D FE000000 L 80 He aquiacute el resultado

Sabemos que esta zona corresponde al aacuterea de la BIOS del Sistema Otra opcioacuten muy interesante nos permite buscar determinados contenidos a traveacutes de la memoria utilizando el prefijo S (Search) Existen dos sintaxis alternativas S direccioacuten-de-inicio L longitud-a-explorar contenido-a-buscar S direccioacuten-de-inicio direccioacuten-final L contenido-a-buscar El contenido debe ser proporcionado en hexadecimal (tal como apareceriacutea en la columna central del ejemplo anterior) o entre comillas si es un texto ASCII Por ejemplo en un equipo IBM deseo ver algunas caracteriacutesticas de la BIOS Seacute que estos datos se alojan a partir de la posicioacuten F0000000 hasta el final de la memoria Es decir una longitud de 64 Kbytes (FFFF) a partir de la posicioacuten de inicio y que seguramente los datos buscados estaraacuten cerca de la identificacioacuten de la propia BIOS (la cadena IBM) Por lo que se utiliza la siguiente sintaxis [3] -s f0000000 L ffff IBM

y se obtiene la siguiente salida F000E00E F000E111 con las direcciones donde se ha encontrado la ocurrencia buscada A continuacioacuten puedo explorar las proximidades de cada posicioacuten Por ejemplo para la primera -D f000e000

Si lo que se busca estaacute en un archivo primero hay que cargarlo Lo que se puede hacer de dos formas en la propia invocacioacuten de DEBUG o mediante los comandos N y L Por ejemplo si queremos inspeccionar el contenido del archivo morecom podemos utilizar dos formas CWINDOWSgtDEBUG cwindowscommandmorecom CWINDOWSgtDEBUG - N cwindowscommandmorecom - L La sintaxis para el prefijo N es N [path-name]nombre-de-archivo En ambos casos el contenido del archivo seraacute cargado en memoria y podraacute ser utilizado Atencioacuten despueacutes de la orden L (Load) DEBUG le avisaraacute si no encuentra el archivo pero seguiraacute su funcionamiento En tal caso simplemente piensa que N sentildeala el nombre de un nuevo archivo que crearaacute con el contenido de la memoria -de DEBUG- cuando posteriormente seleccione la opcioacuten escribir W (Write)[4]

Nota Como ya habraacute deducido DEBUG permite leer un archivo realizar modificaciones en eacutel (con la opcioacuten E) y escribir el archivo modificado bajo otro nombre con NW

A continuacioacuten podemos comprobar el tamantildeo del archivo cargado Para ello usamos la opcioacuten 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 17A70100 E8CD0F CALL 10D0 -

Aquiacute nos interesa especialmente el contenido del registro CX cuyo valor 2917h (1519d) en este caso sentildeala el tamantildeo del archivo en bytes Tambieacuten podiacuteamos haber utilizado directamente el comando R CX que nos proporciona el valor de dicho registro -R CX CX 2917 -

Nota A continuacioacuten del valor correspondiente DEBUG muestra dos puntos () sentildealando que puede cambiar el valor del registro introduciendo un nuevo nuacutemero Pulse INTRO para dejar las cosas como estaacuten y volver al prompt (-) de DEBUG

Al llegar a este punto es importante sentildealar que a excepcioacuten de los archivos exe DEBUG carga los archivos a partir de la direccioacuten 100h (256d) de su memoria De forma que el primer octeto del archivo se carga en la direccioacuten 100 el segundo en 101 etc En nuestro caso el archivo se extenderaacute desde la posicioacuten 100h hasta 2A17h (100h + 2917h) A continuacioacuten para buscar la cadena Microsoft en el archivo utilizamos cualquiera de los siguientes comandos - S 100 L 2917 Microsoft - S 100 2a17 Microsoft El primer comando sentildeala el punto de inicio y el tamantildeo de la zona a buscar el segundo utiliza los puntos inicial y final de la exploracioacuten Con ambos se obtiene la misma respuesta 17A71083 17A710B2

Truco Debido a la forma especial en que se cargan los ejecutables exe si quiere inspeccionar la forma nativa de uno de estos archivos (como es su imagen en el disco) debe hacer una copia del archivo renombrarlo con cualquier otra terminacioacuten (o sin ella) y cargar esta copia En caso contrario DEBUG se prepararaacute para funcionar como un verdadero depurador de tiempo de ejecucioacuten (run-time) para lo que cargaraacute el archivo y lo acomodaraacute en memoria de forma que pueda ejecutarse [5]

Como ejercicio compruebe las distintas longitudes y aspecto (especialmente al principio) de un mismo archivo exe cargaacutendolo con DEBUG de las dos formas (busque en su sistema un exe lo maacutes pequentildeo posible) Ademaacutes de la capacidad de leer archivos antes mencionada quizaacutes una de las opciones maacutes interesantes (y peligrosas) de DEBUG es la posibilidad de leerescribir el contenido de disco a bajo nivel mediante los prefijos L (Load) y W (Write) Se utiliza la siguiente sintaxis L [Direccioacuten] [Unidad] [Primer_sector] [Nuacutemero] W [Direccioacuten] [Unidad] [Primer_sector] [Nuacutemero] El significado de los paraacutemetros es como sigue

Direccioacuten Posicioacuten de la memoria de DEBUG a partir de la cual se instalaraacuten los datos leiacutedos del disco o se tomaraacuten para el proceso de escritura (aquiacute se utiliza generalmente el valor 100h)

Unidad Valor numeacuterico que indica la loacutegica a utilizar 0 = A 1 = B 2 = C 3 = D etc [6]

Primer sector A partir del que se realizaraacute la lectura o se comenzaraacute a escribir

Nuacutemero Nuacutemero de sectores que se desea cargarescribir Como DEBUG no puede leerescribir maacutes de 64 Kbytes (2

16 = 65536) y los sectores de disco son de 512 bytes

el maacuteximo nuacutemero de sectores es 128 (80h) Asiacute pues el valor maacuteximo aquiacute es 80 Ejemplo Para obtener el contenido del sector de arranque (Master boot sector MBR) de un disquete en A utilizaremos el comando CWINDOWSgtDEBUG - L 100 0 0 1 - D 100 L 200 Como el resultado no cabe en una pantalla ingeniaremos un procedimiento para conservarlo en un archivo (maacutes adelante nos serviraacute para otro propoacutesito) Para ello creamos un archivo scripttxt con el siguiente contenido (dos INTRO despueacutes de la Q) L 100 0 0 1 D 100 L 200 Q A continuacioacuten invocamos DEBUG con el comando CWINDOWSgtDEBUG lt Dbuzonscripttxt gt Dbuzonresultadtxt Despueacutes de un breve parpadeo del disco y del disquete vuelve el prompt del DOS La operacioacuten ha concluido y en el directorio correspondiente de la unidad D tenemos el archivo resultadtxt con el volcado del sector de arranque del disquete ademaacutes de los ecos de los comandos introducidos (los hemos mantenido para orientacioacuten del lector) Otra forma de poder visualizar el contenido del Sector de Arranque del disco es utilizando el DEBUG Por ejemplo dentro del DEBUG tecleamos lo siguiente -L 100 0 0 1

-D 100 L 200

177C0100 EB 3E 90 2B 79 73 57 29-49 48 43 00 02 01 01 00 gt+ysW)IHC

177C0110 02 E0 00 40 0B F0 09 00-12 00 02 00 00 00 00 00

177C0120 00 00 00 00 00 00 29 5D-3B DD 10 4E 4F 20 4E 41 )]NO NA

177C0130 4D 45 20 20 20 20 46 41-54 31 32 20 20 20 F1 7D ME FAT12

177C0140 FA 33 C9 8E D1 BC FC 7B-16 07 BD 78 00 C5 76 00 3xv

177C0150 1E 56 16 55 BF 22 05 89-7E 00 89 4E 02 B1 0B FC VU~N

177C0160 F3 A4 06 1F BD 00 7C C6-45 FE 0F 8B 46 18 88 45 |EFE

177C0170 F9 FB 38 66 24 7C 04 CD-13 72 3C 8A 46 10 98 F7 8f$|rltF

177C0180 66 16 03 46 1C 13 56 1E-03 46 0E 13 D1 50 52 89 fFVFPR

177C0190 46 FC 89 56 FE B8 20 00-8B 76 11 F7 E6 8B 5E 0B FV v^

177C01A0 03 C3 48 F7 F3 01 46 FC-11 4E FE 5A 58 BB 00 07 HFNZX

177C01B0 8B FB B1 01 E8 94 00 72-47 38 2D 74 19 B1 0B 56 rG8-tV

177C01C0 8B 76 3E F3 A6 5E 74 4A-4E 74 0B 03 F9 83 C7 15 vgt^tJNt

177C01D0 3B FB 72 E5 EB D7 2B C9-B8 D8 7D 87 46 3E 3C D8 r+Fgtlt

177C01E0 75 99 BE 80 7D AC 98 03-F0 AC 84 C0 74 17 3C FF utlt

177C01F0 74 09 B4 0E BB 07 00 CD-10 EB EE BE 83 7D EB E5 t

177C0200 BE 81 7D EB E0 33 C0 CD-16 5E 1F 8F 04 8F 44 02 3^D

177C0210 CD 19 BE 82 7D 8B 7D 0F-83 FF 02 72 C8 8B C7 48 rH

177C0220 48 8A 4E 0D F7 E1 03 46-FC 13 56 FE BB 00 07 53 HNFVS

177C0230 B1 04 E8 16 00 5B 72 C8-81 3F 4D 5A 75 A7 81 BF [rMZu

177C0240 00 02 42 4A 75 9F EA 00-02 70 00 50 52 51 91 92 BJupPRQ

177C0250 33 D2 F7 76 18 91 F7 76-18 42 87 CA F7 76 1A 8A 3vvBv

177C0260 F2 8A 56 24 8A E8 D0 CC-D0 CC 0A CC B8 01 02 CD V$

177C0270 13 59 5A 58 72 09 40 75-01 42 03 5E 0B E2 CC C3 YZXruB^

177C0280 03 18 01 27 0D 0A 44 69-73 63 6F 20 69 6E 63 6F Disco inco

177C0290 72 72 65 63 74 6F 20 20-20 FF 0D 0A 45 72 72 6F rrecto Erro

177C02A0 72 20 45 2F 53 20 20 20-20 20 FF 0D 0A 43 61 6D r ES Cam

177C02B0 62 69 65 20 65 6C 20 64-69 73 63 6F 20 79 20 70 bie el disco y p

177C02C0 72 65 73 69 6F 6E 65 20-75 6E 61 20 74 65 63 6C resione una tecl

177C02D0 61 20 20 20 20 0D 0A 00-49 4F 20 20 20 20 20 20 a IO

177C02E0 53 59 53 4D 53 44 4F 53-20 20 20 53 59 53 80 01 SYSMSDOS SYS

177C02F0 00 57 49 4E 42 4F 4F 54-20 53 59 53 00 00 55 AA WINBOOT SYSU

-

-Q

FIN [1] En las primeras versiones de MS-DOS era un modesto programita DEBUGCOM de apenas 16 KB La versioacuten que acompantildea a Windows98 es ya un ejecutable en formato EXE de 21 KB [2] En realidad DEBUG es una utilidad de enorme potencia que requeririacutea todo un libro para ella sola Puede encontrarse una amplia descripcioacuten de esta herramienta en el libro de Paul Somerson PC Magazine DOS Powers Tools [3] Desgraciadamente no hay una convencioacuten estaacutendar sobre la colocacioacuten de los datos en la BIOS de forma que cada fabricante sigue sus propias reglas y es imposible por tanto utilizarla para cualquier tipo de identificacioacuten del sistema [4] En palabras del mencionado Paul Somerson Desgraciadamente debido a que DEBUG es un programa tan increiacuteblemente potente tambieacuten es increiacuteblemente peligroso Hay un dicho que afirma que El software no puede destruir el hardware Desgraciadamente esto no es cierto Ademaacutes de enviar mecanismos sensibles de la unidad de disco a tierra de nadie es posible hacer saltar monitores o transformadores Repito si sigue al pie de la letra las instrucciones y hace caso a todos los avisos todo iraacute bien [5] Recuerde que la imagen de un ejecutable exe cargado en memoria es distinta de su imagen en disco Solo en los ejecutables com la imagen en disco es una imagen exacta de su disposicioacuten en memoria [6] Es evidente que un pequentildeo error de nuacutemero en este paraacutemetro puede acarrear consecuencias nefastas Por ejemplo si cree que estaacute jugando con el disquete e inadvertidamente se dirige al disco duro (relea la nota [4])

Page 10: El Comando DEBUG

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 20480103 B261 MOV DL61 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 20480105 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 20480107 3D5000 CMP AX0050 T TRACE T lt=direccioacutengt ltvalorgt Ejecuta una instruccioacuten del programa (a partir de CSIP) mostrando a continuacioacuten el estado de los registros y la siguiente instruccioacuten Ejecutar T10 equivaldriacutea a ejecutar 16 veces el comando T Si la instruccioacuten es CALL o INT se ejecutaraacute como tal introducieacutendose 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 20480100 3D0000 CMP AX0000 -r bx BX 0000 2 -a 100 20480100 mov axbx 20480102 -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 20480102 00AC01D8 ADD [SI+D801]CH DSD801=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 20480100 3D0000 CMP AX0000 -a 100 20480100 mov axbx 20480102 mov cxbx 20480104 -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 20480102 89D9 MOV CXBX 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 20480104 01D8 ADD AXBX

N NAME N ltnombre_archivogt Se asigna un nombre al programa que estaacute siendo creado o modificado Se puede indicar la trayectoria de directorios L LOAD L ltbuffergt ltnumdiscogt ltsectorinigt ltnumsectorgt ltbuffergt es la direccioacuten en donde se carga la informacioacuten ltnumdiscogt es el nuacutemero (opcional) del disco de donde se leeraacute la informacioacuten (0=A 1=B 2=C etc) ltsectorinigt es el sector de disco absoluto (en hexadecimal) a leer ltnumsectorgt es la cantidad de sectores a leer No se pueden leer maacutes de 80H (128) sectores Si no se suministra la combinacioacuten ltnumdiscogt ltsectorinigt ltnumsectorgt DEBUG presume que se desea leer un archivo En este caso ltbuffergt es opcional Debe usarse el comando N (ver maacutes adelante) para especificar el archivo a leer Eacuteste se carga en CS0100 Ejemplo Se va a leer el sector 0 del disco A y se vuelca a partir de la direccioacuten DS100 como se puede observar el disco contiene mucha informacioacuten ( ESTO NO QUIERE DECIR QUE TENGA QUE SALIR LO MISMO EN SU VOLCADO )

l 100 0 0 1 -d 100 300

W WRITE W ltdireccioacutengt Graba el contenido de una zona de memoria a disco Si no se indica la direccioacuten se graba desde CS100h hasta CS100h+nuacutemero_bytes el nuacutemero de bytes se indica en BXCX (no es una direccioacuten segmentada sino un valor de 32 bits) Si se trata de un EXE no se permitiraacute grabarlo (para modificarlos hay que renombrarles para cambiarles la extensioacuten aunque de esta manera no seraacuten montados al cargarlos) La sintaxis es W ltbuffergt ltnumdiscogt ltsectorinigt ltnumsectorgt ltbuffergt es la direccioacuten de donde se carga la informacioacuten ltnumdiscogt es el nuacutemero (opcional) del disco en donde se escribiraacute la informacioacuten (0=A 1=B 2=C etc) ltsectorinigt es el sector de disco absoluto (en hexadecimal) en donde empieza la escritura ltnumsectorgt es la cantidad de sectores a leer No se pueden escribir maacutes de 80H (128) sectores Si no se suministra la combinacioacuten ltnumdiscogt ltsectorinigt ltnumsectorgt DEBUG presume que el inicio de archivo es CS100 En este caso ltbuffergt es opcional Debe usarse el comando N (ver arriba) para especificar el archivo a escribir Antes de escribir BXCX debe ajustarse al nuacutemero de bytes que desean grabarse W no puede escribir a archivos con la extensioacuten EXE o HEX [5] Ejemplo

N ltnomarchivogt BXCX lt--- 2000 W

S SEARCH S ltrangogt ltlistagt Busca una cadena de bytes por la memoria Para buscar la cadena PEPE terminada por cero en un aacuterea de 512 bytes desde DS100 se hariacutea S 100 L 200 PEPE0 (por defecto se busca en DS) No se encontrariacutea sin embargo pepe (en minuacutesculas) C COMPARE C ltrangogt ltdireccioacutengt Compara dos zonas de memoria mostrando las diferencias Por ejemplo para comparar 5 bytes de DS100 y DS200 se hace C 100 L 5 200 M MOVE M ltrangogt ltdireccioacutengt Maacutes que mover copia una zona de memoria en otra de manera inteligente (controlando los posibles solapamientos de los bloques) I INPUT I ltpuertogt Visualiza la lectura del puerto de ES indicado

O OUTPUT O ltpuertogt ltvalorgt Enviacutea un valor a un puerto de ES H HEX H ltvalor1gt ltvalor2gt Muestra la suma y resta de valor1 y valor2 ambos operandos de un maacuteximo de 16 bits (si hay desbordamiento se trunca el resultado que tampoco excede los 16 bits) Resultado ltresultado_1gt Es la suma ( ltvalor1gt + ltvalor2gt) ltresultado_2gt es la resta (ltvalor1gt - ltvalor2gt ) Ejemplo -h 0003 0002 0005 0001 -h 0000 0001 0001 FFFF como se observa el resultado de la segunda operacioacuten es FFFF que es el equivalente en complemento a 2 de -1 G GO G =ltiniciogt ltquiebre1gt ltquiebre2gt ltquiebre10gt Este comando ejecuta el coacutedigo en memoria Si se estaacute depurando un programa permite ejecutar el coacutedigo cargado en memoria Tambieacuten permite establecer puntos de quiebre (breakpoints) que son direcciones en las que se detiene la ejecucioacuten del programa La sintaxis es G =ltiniciogt ltquiebre1gt ltquiebre2gt ltquiebre10gt ltiniciogt es la direccioacuten de inicio de ejecucioacuten ltquiebre1gt hasta ltquiebre10gt son direcciones opcionales de paro del programa Si no se especifica ltiniciogt Go inicia con la direccioacuten contenida en CSIP Para lograr los quiebres DEBUG reemplaza el coacutedigo en las direcciones de quiebre por el valor hexadecimal CC que es el coacutedigo de interrupcioacuten Si DEBUG llega a CC todos los puntos de quiebre son restituidos los registros se despliegan (como con el comando R [veacutease adelante]) y se para la ejecucioacuten U UNASSEMBLE U ltrangogt Este comando desensambla el contenido de la memoria a partir de la posicioacuten actual Registros y Banderas del DEBUG La mayoriacutea de los comandos de DEBUG ejecutan una accioacuten y vuelven al indicador del shell pero si es un comando largo como puede ser mostrar un trozo grande de coacutedigo puede detenerse pulsando CTRL-Pausa o interrumpirse con CTRL-C para volver al shell Por ejemplo al teclear lo siguiente

- r [Enter]

-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 17A70100 E8CD0F CALL 10D0 - Se desplegaran todos los contenidos de los registros internos del microprocesador una forma alternativa de mostrarlos es usar el comando r utilizando como paraacutemetro el nombre del registro cuyo valor se quiera visualizar Por ejemplo

- r bx Esta instruccioacuten desplegaraacute uacutenicamente el contenido del registro BX y cambia el indicador del DEBUG de - a Estando asiacute el prompt es posible cambiar el valor del registro que se visualizoacute tecleando el nuevo valor y a continuacioacuten [Enter] o se puede dejar el valor anterior presionando [Enter] sin teclear ninguacuten valor Es posible cambiar el valor del registro de banderas asiacute como utilizarlo como estructura de control en nuestros programas como se veraacute maacutes adelante Cada bit del registro tiene un nombre y significado especial la lista dada a continuacioacuten describe el valor de cada bit tanto apagado como prendido y su relacioacuten con las operaciones del microprocesador

Overflow (O) NV = no hay desbordamiento OV = si lo hay Direction (D) UP = hacia adelante DN = hacia atraacutes Interrupts (I) DI = desactivadas EI = activadas Sign (S) PL = positivo NG = negativo Zero (Z) NZ = no es cero ZR = s lo es Auxiliary Carry (A) NA = no hay acarreo auxiliar

AC = hay acarreo auxiliar Parity (P) PO = paridad non PE = paridad par Carry (C) NC = no hay acarreo CY = Si lo hay

La estructura del ensamblador En el lenguaje ensamblador las liacuteneas de coacutedigo constan de dos partes la primera es el nombre de la instruccioacuten que se va a ejecutar y la segunda son los paraacutemetros del comando u operandos Por ejemplo

add ahbh Aquiacute add es el comando a ejecutar (en este caso una adicioacuten) y tanto ah como bh son los paraacutemetros El nombre de las instrucciones en este lenguaje estaacute formado por dos tres o cuatro letras a estas instrucciones tambieacuten se les llama nombres mnemoacutenicos o coacutedigos de operacioacuten ya que representan alguna funcioacuten que habraacute de realizar el microprocesador Existen algunos comandos que no requieren paraacutemetros para su operacioacuten asiacute como otros que requieren solo un paraacutemetro Algunas veces se utilizaraacuten las instrucciones como sigue

add al[170] Los corchetes en el segundo paraacutemetro nos indican que vamos a trabajar con el contenido de la posicioacuten de memoria nuacutemero 170 y no con el valor 170 a esto se le conoce como direccionamiento directo Primer programa en ensamblador con el DEBUG Vamos a crear un programa que sirva para ilustrar lo que hemos estado viendo lo que haremos seraacute una suma de dos valores que introduciremos directamente en el programa El primer paso es iniciar el DEBUG este paso consiste uacutenicamente en teclear DEBUG [Enter] en el prompt del sistema operativo Para ensamblar un programa en el DEBUG se utiliza el comando a (assemble) cuando se utiliza este comando se le puede dar como paraacutemetro la direccioacuten donde se desea que se inicie el ensamblado Si se omite el paraacutemetro el ensamblado se iniciaraacute en la localidad especificada por CSIP usualmente 0100H que es la localidad donde deben iniciar los programas con extensioacuten COM y seraacute la localidad que utilizaremos debido a que DEBUG solo puede crear este tipo especiacutefico de programas

Aunque en este momento no es necesario darle un paraacutemetro al comando a es recomendable hacerlo para evitar problemas una vez que se haga uso de los registros CSIP por lo tanto tecleamos

- a 100 [Enter] Al hacer esto apareceraacute en la pantalla algo como 0C1B0100 y el cursor se posiciona a la derecha de estos nuacutemeros noacutetese que los primeros cuatro diacutegitos (en sistema hexadecimal) pueden ser diferentes pero los uacuteltimos cuatro deben ser 0100 ya que es la direccioacuten que indicamos como inicio Ahora podemos introducir las instrucciones

0C1B0100 mov ax0002 coloca el valor 0002 en el registro ax 0C1B0103 mov bx0004 coloca el valor 0004 en el registro bx 0C1B0106 add axbx le adiciona al contenido de ax el contenido de bx 0C1B0108 int 20 provoca la terminacioacuten del programa 0C1B010A

No es necesario escribir los comentarios que van despueacutes del Una vez escrito el uacuteltimo comando int 20 se le da [Enter] sin escribir nada maacutes para volver al prompt del DEBUG La uacuteltima liacutenea escrita no es propiamente una instruccioacuten de ensamblador es una llamada a una interrupcioacuten del sistema operativo estas interrupciones seraacuten tratadas maacutes a fondo en un capiacutetulo posterior por el momento solo es necesario saber que nos ahorran un gran nuacutemero de liacuteneas y son muy uacutetiles para accesar a funciones del sistema operativo Para ejecutar el programa que escribimos se utiliza el comando g al utilizarlo veremos que aparece un mensaje que dice Program terminated normally Naturalmente con un mensaje como eacuteste no podemos estar seguros que el programa haya hecho la suma pero existe una forma sencilla de verificarlo utilizando el comando r del DEBUG podemos ver los contenidos de todos los registros del microprocesador simplemente teclee

- r [Enter] Apareceraacute en pantalla cada registro con su respectivo valor actual -R AX=0006 BX=0004 CX=0000 DX=0000 SP=FFFE BP=0000 SI=0000 DI=0000 DS=0C1B ES=0C1B SS=0C1B CS=0C1B IP=010A NV UP EI PL NZ NA PO NC 17A70100 E8CD0F CALL 10D0 - Existe la posibilidad de que los registros contengan valores diferentes pero AX y BX deben ser los mismos ya que son los que acabamos de modificar Otra forma de ver los valores mientras se ejecuta el programa es utilizando como paraacutemetro para g la direccioacuten donde queremos que termine la ejecucioacuten y muestre los valores de los registros en este caso seraacute g108 esta instruccioacuten ejecuta el programa se detiene en la direccioacuten 108 y muestra los contenidos de los registros Tambieacuten se puede llevar un seguimiento de lo que pasa en los registros utilizando el comando t (trace) la funcioacuten de este comando es ejecutar liacutenea por liacutenea lo que se ensambloacute mostrando cada vez los contenidos de los registros Para salir del DEBUG se utiliza el comando q (quit)

Guardar y cargar los programas No seriacutea praacutectico tener que escribir todo un programa cada vez que se necesite para evitar eso es posible guardar un programa en el disco con la enorme ventaja de que ya ensamblado no seraacute necesario correr de nuevo DEBUG para ejecutarlo ya que cuando el DEBUG guardo nuestro programa en el disco eacuteste se guardo en binario (archivo con la extensioacuten com) Los pasos a seguir para guardar un programa ya almacenado en la memoria son

Obtener la longitud del programa restando la direccioacuten final de la direccioacuten inicial naturalmente en sistema hexadecimal

Darle un nombre al programa y una extensioacuten

Poner la longitud del programa en el registro CX

Ordenar a DEBUG que escriba el programa en el disco Utilizando como ejemplo el programa del ejemplo anterior tendremos una idea maacutes clara de coacutemo llevar estos pasos Al terminar de ensamblar el programa se veriacutea asiacute

0C1B0100 mov ax0002 0C1B0103 mov bx0004 0C1B0106 add axbx 0C1B0108 int 20 0C1B010A

Para almacenarlo en el disco hacemos lo siguiente - h 10a 100 020a 000a - n pruebacom - r cx CX 0000 000a -w Writing 000A bytes

Para obtener la longitud de un programa se utiliza el comando h el cual nos muestra la suma y resta de dos nuacutemeros en hexadecimal Para obtener la longitud del programa le proporcionamos como paraacutemetros el valor de la direccioacuten final de nuestro programa (10A) y el valor de la direccioacuten inicial (0100) El primer resultado que nos muestra el comando es la suma de los paraacutemetros y el segundo es la resta El comando n nos permite poner un nombre al programa El comando r cx nos permite cambiar el contenido del registro CX al valor que obtuvimos del tamantildeo del archivo con h en este caso 000a ya que nos interesa el resultado de la resta de la direccioacuten inicial a la direccioacuten final

Por uacuteltimo el comando w escribe nuestro programa en el disco indicaacutendonos cuantos bytes escribioacute

NOTA Si se trabaja en una ventana de DOS de Windows Vista o 7 es probable que al momento de guardar su programa el DEBUG escriba mas coacutedigo que el sentildealado por el registro CX por consiguiente seraacute necesario limpiar el registro BX esto es ponerlo a ceros y despueacutes utilizar el comando w Por ejemplo _r bx BX 000E 0000 w

Para cargar un archivo ya guardado son necesarios dos pasos

Proporcionar el nombre del archivo que se cargaraacute a memoria

Cargarlo utilizando el comando l (load) Para obtener el resultado correcto de los siguientes pasos es necesario que previamente se haya creado el programa anterior Dentro del DEBUG escribimos lo siguiente

- n pruebacom - l - u 100 109 0C3D0100 B80200 MOV AX0002 0C3D0103 BB0400 MOV BX0004 0C3D0106 01D8 ADD AXBX 0C3D0108 CD20 INT 20

El uacuteltimo comando u se utiliza para verificar que el programa se cargoacute en memoria lo que hace es desensamblar el coacutedigo y mostrarlo ya desensamblado Los paraacutemetros le indican a DEBUG desde donde y hasta donde desensamblar DEBUG siempre carga los programas en memoria en la direccioacuten 100H a menos que se le indique alguna otra Un programa que realiza un conteo en pantalla Con el DEBUG es posible escribir un programa que realice un conteo en pantalla por razones de comprensioacuten nuestro programa solo realizara un conteo de 9 a 0 (conteo descendente) 0B3B0100 B90A00 MOV CX000A CX=10 en decimal 0B3B0103 88CA MOV DLCL 0B3B0105 80C22F ADD DL2F sumamos 02Fh a DL 0B3B0108 B402 MOV AH02 funcioacuten 02 de INT 21 para imprimir un caracter 0B3B010A CD21 INT 21

0B3B010C E2F5 LOOP 0103 CX=0 Si no salta a 0103 0B3B010E CD20 INT 20 termina el programa En la liacutenea 0103 se puede observar que el valor del registro CX en su parte baja (en CL) se almacena en el registro DL Si se omitiera la liacutenea 0105 entonces cuando se ejecutara la liacutenea 010A solo se imprimiriacutea en pantalla el coacutedigo ASCII del valor que contenga DL (el coacutedigo ASCII de 0Ah que es 10 en decimal es un caraacutecter especial no imprimible) Para conseguir el ldquoefectordquo de que el programa realiza el conteo en decimal se hace un corrimiento de 02F (47 en decimal) Por ejemplo cuando se ejecuta la liacutenea 0105 DL tendriacutea el valor de 39h=57d (02Fh+0Ah=39h=57d) y el coacutedigo ASCII de 57d es el caraacutecter ldquo9rdquo El sentencia LOOP decrementa CX en 1 si CX es diferente a 0 salta a la liacutenea 0103 El proceso se repite y el programa imprime en pantalla 9876543210 Seriacutea interesante que el programa anterior fuera modificado para que la numeracioacuten se imprimiera de la siguiente manera 9 8 7 6 5 4 3 2 1 0

NOTA Como se dijo anteriormente cuando el DEBUG almacena un programa en el disco este archivo se graba en binario esto es en ejecutable Por lo tanto no es necesario cargar el DEBUG para volver a ejecutar nuestro programa sino que se hace de manera directa desde DOS El problema surge cuando al ejecutar nuestro programa el resultado no se puede observar porque el DOS borra la pantalla despueacutes de terminar de ejecutar el programa Para evitar el borrado automaacutetico seraacute necesario agregarle a nuestro programa antes de la INT 20h una instruccioacuten para la lectura de un caraacutecter desde el teclado Para tal efecto utilizaremos la funcioacuten 08 de la INT 21h (un buen truco para que el programa haga una pausa) asiacute el programa esperara hasta que el usuario presiona una tecla permitiendo observar el resultado Ejemplo mov ah08 Int 21 Int 20

Condiciones ciclos y bifurcaciones Estas estructuras o formas de control le dan a la maacutequina un cierto grado de decisioacuten basado en la informacioacuten que recibe La forma maacutes sencilla de comprender este tema es por medio de ejemplos Vamos a crear tres programas que hagan lo mismo desplegar un nuacutemero determinado de veces una cadena de caracteres en la pantalla

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV CX000F veces que se desplegara la cadena 0C1B0128 MOV DX0102 copia cadena al registro DX 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F LOOP 012D si CXgt0 salta a 012D 0C1B0131 INT 20 termina el programa

Por medio del comando e es posible introducir una cadena de caracteres en una determinada localidad de memoria dada como paraacutemetro la cadena se introduce entre comillas le sigue un espacio luego el valor hexadecimal del retorno de carro un espacio el valor de liacutenea nueva y por uacuteltimo el siacutembolo $ que el ensamblador interpreta como final de la cadena La interrupcioacuten 21 utiliza el valor almacenado en el registro AH para ejecutar una determinada funcioacuten en este caso mostrar la cadena en pantalla la cadena que muestra es la que estaacute almacenada en el registro DX La instruccioacuten LOOP decrementa automaacuteticamente el registro CX en uno y si no ha llegado el valor de este registro a cero salta a la posicioacuten de memoria indicada como paraacutemetro lo cual crea un ciclo que se repite el nuacutemero de veces especificado por el valor de CX La interrupcioacuten 20 termina la ejecucioacuten del programa Otra forma de realizar la misma funcioacuten pero sin utilizar el comando LOOP es la siguiente

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV BX000F veces que se desplegara la cadena 0C1B0128 MOV DX0102 copia cadena al registro DX 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F DEC BX decrementa en 1 a BX 0C1B0130 JNZ 012D si BX es diferente a 0 salta a 012D 0C1B0132 INT 20 termina el programa

En este caso se utiliza el registro BX como contador para el programa y por medio de la instruccioacuten DEC se disminuye su valor en 1 La instruccioacuten JNZ verifica si el valor de BX es diferente a 0 esto con base en la bandera NZ en caso afirmativo salta hacia la direccioacuten 012D En caso contrario continuacutea la ejecucioacuten normal del programa y por lo tanto se termina Una uacuteltima variante del programa es utilizando de nuevo a CX como contador pero en lugar de utilizar LOOP utilizaremos decrementos a CX y comparacioacuten de CX a 0

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV DX0102 copia cadena al registro DX 0C1B0128 MOV CX000F veces que se desplegara la cadena 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F DEC CX decrementa en 1 a CX 0C1B0130 JCXZ 0134 si CX es igual a 0 salta a 0134 0C1B0132 JMP 012D salta a la direccioacuten 012D 0C1B0134 INT 20 termina el programa

En este ejemplo se usoacute la instruccioacuten JCXZ para controlar la condicioacuten de salto el significado de tal funcioacuten es salta si CX=0 El tipo de control a utilizar dependeraacute de las necesidades de programacioacuten en determinado momento

Manipulacioacuten de Posiciones de Memoria Con el DEBUG es posible almacenar y recuperar datos numeacutericos en memoria por medio de un programa a traveacutes de los registros del microprocesador Por ejemplo el siguiente programa almacena previamente dos valores numeacutericos en la posicioacuten 0300h y 0400h respectivamente despueacutes el programa los recupera realiza la operacioacuten de suma con esos valores y el resultado lo almacena en la posicioacuten 0500h -a 100 0B1C0100 mov ax0002 ax=2 0B1C0103 mov [0300]ax almacenamos 2 en la direccioacuten 0300h 0B1C0106 mov ax0004 ax=4 0B1C0109 mov [0400]ax almacenamos 4 en la direccioacuten 0400h 0B1C010C mov ax[0300] recuperamos el dato1 en AX 0B1C010F mov bx[0400] recuperamos el dato2 en BX 0B1C0113 add axbx hacemos la operacioacuten de suma en AX 0B1C0115 mov [0500]ax almacenamos el 6 en la direccioacuten 0500h 0B1C0118 int 21 0B1C011A - Un nuacutemero entre corchetes [numero_hex] indica una posicioacuten de memoria y su manejo se hace a traveacutes de registros ya que no es posible almacenar valores numeacutericos de manera directa Ejecutamos el programa -g 118 AX=0006 BX=0004 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=0B1C ES=0B1C SS=0B1C CS=0B1C IP=0118 NV UP EI PL NZ NA PE NC 0B1C0118 CD21 INT 21 - Para ver si el resultado se almaceno en la direccioacuten correcta hacemos

Como se puede observar en la direccioacuten 0B1C0500 se encuentra el 06 y en 0B1C0501 se encuentra el 00 que es el resultado de la operacioacuten 2+4 Perohellip Porque aparece el 06 y despueacutes el 00 pareceriacutea que el resultado fue de 0600 pero no es asiacute lo que sucedes que los datos se almacenan en memoria de la siguiente manera

Como se hizo la operacioacuten AX=AX+BX entonces el resultado es de 16 bits (dos bytes) AX=6 entonces AX=0000 0000 0000 0110 (16 bits) por lo tanto los 8 bits de menor peso de AX son 0000 0110 y deben almacenarse en la direccioacuten 0500 y en la direccioacuten 0501 se almacena 0000 0000

0 0 0 0 0 1 1 0 0500

0 0 0 0 0 0 0 0 0501

x x x x x x x x 0502

x x x x x x x x 0503

x x x x x x x x 0504

x x x x x x x x 0505

Interrupciones Definicioacuten de interrupcioacuten

Una interrupcioacuten es una instruccioacuten que detiene la ejecucioacuten de un programa para permitir el uso del microprocesador en un proceso prioritario Una vez concluido este uacuteltimo proceso se devuelve el control a la aplicacioacuten anterior

Por ejemplo cuando estamos trabajando con un procesador de palabras y en ese momento llega un aviso de uno de los puertos de comunicaciones se detiene temporalmente la aplicacioacuten que estaacutebamos utilizando para permitir el uso del microprocesador al manejo de la informacioacuten que estaacute llegando en ese momento Una vez terminada la transferencia de informacioacuten se reanudan las funciones normales del procesador de palabras Las interrupciones ocurren muy seguido sencillamente la interrupcioacuten que actualiza la hora del diacutea ocurre aproximadamente 18 veces por segundo Para lograr administrar todas estas interrupciones la computadora cuenta con un espacio de memoria llamado memoria baja donde se almacenan las direcciones de cierta localidad de memoria donde se encuentran un juego de instrucciones que el microprocesador ejecutaraacute para despueacutes regresar a la aplicacioacuten que estaba en proceso En los programas anteriores hicimos uso de la interrupcioacuten nuacutemero 20H para terminar la ejecucioacuten de nuestros programas y en otros ejemplos utilizamos otra interrupcioacuten para mostrar informacioacuten en pantalla (INT 21h) Utilizando DEBUG tecleamos

- a100 2C1B0100 JMP 011D 2C1B0102 [ENTER] - E 102 Hola como estas 0D 0A $ - A011D 2C1B011D MOV DX0102 2C1B0120 MOV AH09 2C1B0122 INT 21 2C1B0123 INT 20

Orden

creciente

de la

memoria

En este programa la interrupcioacuten 21h manda al monitor la cadena localizada en la direccioacuten a la que apunta el registro DX El valor que se le da a AH determina cual de las opciones de la interrupcioacuten 21h seraacute utilizada ya que esta interrupcioacuten cuenta con varias opciones El manejo directo de interrupciones es una de las partes maacutes fuertes del lenguaje ensamblador ya que con ellas es posible controlar eficientemente todos los dispositivos internos y externos de una computadora gracias al completo control que se tiene sobre operaciones de entrada y salida Maacutes del DEBUG Una caracteriacutestica poco conocida es que DEBUG puede aceptar entradas desde un archivo Script que puede ser un simple archivo de texto ASCII en el que cada comando esteacute separado del anterior por un INTRO Despueacutes del uacuteltimo que debe ser una Q para salir de DEBUG es conveniente dejar una liacutenea en blanco pulsando INTRO dos veces Las liacuteneas pueden contener comentarios Cualquier cosa a partir del caracter punto y coma () hasta el final de la liacutenea seraacute ignorado esto es un comentario D aquiacute se mostraraacute algo Suponiendo que tengamos un archivo Script de nombre Ordenestxt puede ser utilizado como entrada para DEBUG mediante un comando de redireccioacuten en la siguiente forma DEBUG lt ordenestxt Tambieacuten puede conseguirse que el programa redireccione la salida hacia un archivo que puede ser inspeccionado maacutes 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 podriacutea obtenerse un archivo Resulttxt con el siguiente comando DEBUG lt ordenestxt gt Resulttxt Errores Cuando DEBUG no sabe interpretar un comando muestra un mensaje de error y un indicador ^ debajo del sitio del comando donde estaacute el error Entradas y Salidas DEBUG asume que los datos numeacutericos proporcionados son hexadecimales y cuando se trate de direcciones de memoria deben introducirse en forma segmentada A su vez los resultados son mostrados tambieacuten 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

Cada fila muestra 16 posiciones de memoria a partir de la posicioacuten sentildealada por las columnas de la izquierda que las muestran como segmentodesplazamiento El bloque central muestra el contenido hexadecimal de cada byte mientras que el bloque derecho contiene la representacioacuten ASCII Por ejemplo la 3ra fila muestra el contenido de las posiciones 0B770120 a 0B77012F (ambas inclusive) Sus tres uacuteltimos bytes contienen respectivamente los caracteres r 9 y 2 que corresponden a las cantidades 72h 39h y 32h del bloque central Que como sabemos equivalen a los decimales 114 57 y 50 que son precisamente los valores ASCII de los caracteres ldquorrdquo ldquo9rdquo y ldquo2rdquo anteriormente mencionados

Nota Por razoacuten de que eacuteste tipo de salida pueda ser listado a impresora el bloque derecho no contiene en realidad la representacioacuten ASCII de todos los caracteres (algunos ni siquiera tienen una representacioacuten imprimible) En realidad solo se muestran los caracteres imprimibles del primer bloque (US-ASCII) El resto estaacute 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 caraacutecter imprimible Esto no significa que dichas posiciones representen efectivamente tales valores para la aplicacioacuten que las utiliza Por ejemplo puede que en realidad las dos posiciones de memoria mencionadas (dos octetos o bytes) en vez de los caracteres ldquo5rdquo y ldquoardquo representen una palabra de 16 bits en formato Little Endian que a su vez representan una cantidad entera (un nuacutemero) Comandos Aunque su descripcioacuten completa llenariacutea todo un capiacutetulo a continuacioacuten comentamos algunas de las opciones maacutes interesantes relativas a inspeccioacuten del coacutedigo y de contenidos de memoria La opcioacuten D (Dump) permite obtener un volcado del contenido de la memoria (de DEBUG) La sintaxis acepta dos formas D [direccioacuten-inicial] [L posiciones-desde-direccioacuten-inicial ] D [direccioacuten-inicial][direccioacuten-final] Naturalmente para que exista algo en el buacutefer de memoria (al principio quizaacutes solo contiene basura) es preciso indicarle que lea algo Este algo puede ser un rango de direcciones de memoria RAM una direccioacuten absoluta de disco (sector) un archivo o el contenido de los registros del procesador Para empezar puede indicaacutersele que cargue un archivo xxxxyz que tenemos en el directorio actual o en el PATH cuyo contenido queremos ver Cgt DEBUG xxxxyz -D aquiacute se obtendriacutea una salida anaacuteloga a la comentada

Hemos visto un ejemplo al tratar de los servicios de interrupciones del PC aquiacute mostraremos otro Sabemos que el punto de inicio de la BIOS es la direccioacuten F000FFF0 y que desde eacutesta posicioacuten hasta el final de la memoria DOS hay 16 bytes Puede obtenerse un volcado de estas posiciones con el siguiente comando -D F000FFF0 La salida en un equipo puede ser F000FFF0 CD 19 E0 00 F0 30 36 2F-33 30 2F 39 37 00 FC 38 0630978 En este caso el comando solo muestra una liacutenea porque ha alcanzado el final de la memoria Puede verse que la fecha de la BIOS del sistema ocupa las uacuteltimas posiciones Si se ordena el volcado de una direccioacuten suficientemente alejada del final de la memoria sin indicar ninguacuten nuacutemero de posiciones por defecto se toma el valor 128 (8 filas de 16 posiciones) Si desea una cantidad distinta hay que antildeadir una L (Long) y el nuacutemero de posiciones hasta un maacuteximo de 64 KB (FFFF) Todos los nuacutemeros deben ser expresados en hexadecimal Por consiguiente los dos comandos que siguen son equivalentes (recuerde que 80 es el equivalente hexadecimal de 128) D FE000000 D FE000000 L 80 He aquiacute el resultado

Sabemos que esta zona corresponde al aacuterea de la BIOS del Sistema Otra opcioacuten muy interesante nos permite buscar determinados contenidos a traveacutes de la memoria utilizando el prefijo S (Search) Existen dos sintaxis alternativas S direccioacuten-de-inicio L longitud-a-explorar contenido-a-buscar S direccioacuten-de-inicio direccioacuten-final L contenido-a-buscar El contenido debe ser proporcionado en hexadecimal (tal como apareceriacutea en la columna central del ejemplo anterior) o entre comillas si es un texto ASCII Por ejemplo en un equipo IBM deseo ver algunas caracteriacutesticas de la BIOS Seacute que estos datos se alojan a partir de la posicioacuten F0000000 hasta el final de la memoria Es decir una longitud de 64 Kbytes (FFFF) a partir de la posicioacuten de inicio y que seguramente los datos buscados estaraacuten cerca de la identificacioacuten de la propia BIOS (la cadena IBM) Por lo que se utiliza la siguiente sintaxis [3] -s f0000000 L ffff IBM

y se obtiene la siguiente salida F000E00E F000E111 con las direcciones donde se ha encontrado la ocurrencia buscada A continuacioacuten puedo explorar las proximidades de cada posicioacuten Por ejemplo para la primera -D f000e000

Si lo que se busca estaacute en un archivo primero hay que cargarlo Lo que se puede hacer de dos formas en la propia invocacioacuten de DEBUG o mediante los comandos N y L Por ejemplo si queremos inspeccionar el contenido del archivo morecom podemos utilizar dos formas CWINDOWSgtDEBUG cwindowscommandmorecom CWINDOWSgtDEBUG - N cwindowscommandmorecom - L La sintaxis para el prefijo N es N [path-name]nombre-de-archivo En ambos casos el contenido del archivo seraacute cargado en memoria y podraacute ser utilizado Atencioacuten despueacutes de la orden L (Load) DEBUG le avisaraacute si no encuentra el archivo pero seguiraacute su funcionamiento En tal caso simplemente piensa que N sentildeala el nombre de un nuevo archivo que crearaacute con el contenido de la memoria -de DEBUG- cuando posteriormente seleccione la opcioacuten escribir W (Write)[4]

Nota Como ya habraacute deducido DEBUG permite leer un archivo realizar modificaciones en eacutel (con la opcioacuten E) y escribir el archivo modificado bajo otro nombre con NW

A continuacioacuten podemos comprobar el tamantildeo del archivo cargado Para ello usamos la opcioacuten 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 17A70100 E8CD0F CALL 10D0 -

Aquiacute nos interesa especialmente el contenido del registro CX cuyo valor 2917h (1519d) en este caso sentildeala el tamantildeo del archivo en bytes Tambieacuten podiacuteamos haber utilizado directamente el comando R CX que nos proporciona el valor de dicho registro -R CX CX 2917 -

Nota A continuacioacuten del valor correspondiente DEBUG muestra dos puntos () sentildealando que puede cambiar el valor del registro introduciendo un nuevo nuacutemero Pulse INTRO para dejar las cosas como estaacuten y volver al prompt (-) de DEBUG

Al llegar a este punto es importante sentildealar que a excepcioacuten de los archivos exe DEBUG carga los archivos a partir de la direccioacuten 100h (256d) de su memoria De forma que el primer octeto del archivo se carga en la direccioacuten 100 el segundo en 101 etc En nuestro caso el archivo se extenderaacute desde la posicioacuten 100h hasta 2A17h (100h + 2917h) A continuacioacuten para buscar la cadena Microsoft en el archivo utilizamos cualquiera de los siguientes comandos - S 100 L 2917 Microsoft - S 100 2a17 Microsoft El primer comando sentildeala el punto de inicio y el tamantildeo de la zona a buscar el segundo utiliza los puntos inicial y final de la exploracioacuten Con ambos se obtiene la misma respuesta 17A71083 17A710B2

Truco Debido a la forma especial en que se cargan los ejecutables exe si quiere inspeccionar la forma nativa de uno de estos archivos (como es su imagen en el disco) debe hacer una copia del archivo renombrarlo con cualquier otra terminacioacuten (o sin ella) y cargar esta copia En caso contrario DEBUG se prepararaacute para funcionar como un verdadero depurador de tiempo de ejecucioacuten (run-time) para lo que cargaraacute el archivo y lo acomodaraacute en memoria de forma que pueda ejecutarse [5]

Como ejercicio compruebe las distintas longitudes y aspecto (especialmente al principio) de un mismo archivo exe cargaacutendolo con DEBUG de las dos formas (busque en su sistema un exe lo maacutes pequentildeo posible) Ademaacutes de la capacidad de leer archivos antes mencionada quizaacutes una de las opciones maacutes interesantes (y peligrosas) de DEBUG es la posibilidad de leerescribir el contenido de disco a bajo nivel mediante los prefijos L (Load) y W (Write) Se utiliza la siguiente sintaxis L [Direccioacuten] [Unidad] [Primer_sector] [Nuacutemero] W [Direccioacuten] [Unidad] [Primer_sector] [Nuacutemero] El significado de los paraacutemetros es como sigue

Direccioacuten Posicioacuten de la memoria de DEBUG a partir de la cual se instalaraacuten los datos leiacutedos del disco o se tomaraacuten para el proceso de escritura (aquiacute se utiliza generalmente el valor 100h)

Unidad Valor numeacuterico que indica la loacutegica a utilizar 0 = A 1 = B 2 = C 3 = D etc [6]

Primer sector A partir del que se realizaraacute la lectura o se comenzaraacute a escribir

Nuacutemero Nuacutemero de sectores que se desea cargarescribir Como DEBUG no puede leerescribir maacutes de 64 Kbytes (2

16 = 65536) y los sectores de disco son de 512 bytes

el maacuteximo nuacutemero de sectores es 128 (80h) Asiacute pues el valor maacuteximo aquiacute es 80 Ejemplo Para obtener el contenido del sector de arranque (Master boot sector MBR) de un disquete en A utilizaremos el comando CWINDOWSgtDEBUG - L 100 0 0 1 - D 100 L 200 Como el resultado no cabe en una pantalla ingeniaremos un procedimiento para conservarlo en un archivo (maacutes adelante nos serviraacute para otro propoacutesito) Para ello creamos un archivo scripttxt con el siguiente contenido (dos INTRO despueacutes de la Q) L 100 0 0 1 D 100 L 200 Q A continuacioacuten invocamos DEBUG con el comando CWINDOWSgtDEBUG lt Dbuzonscripttxt gt Dbuzonresultadtxt Despueacutes de un breve parpadeo del disco y del disquete vuelve el prompt del DOS La operacioacuten ha concluido y en el directorio correspondiente de la unidad D tenemos el archivo resultadtxt con el volcado del sector de arranque del disquete ademaacutes de los ecos de los comandos introducidos (los hemos mantenido para orientacioacuten del lector) Otra forma de poder visualizar el contenido del Sector de Arranque del disco es utilizando el DEBUG Por ejemplo dentro del DEBUG tecleamos lo siguiente -L 100 0 0 1

-D 100 L 200

177C0100 EB 3E 90 2B 79 73 57 29-49 48 43 00 02 01 01 00 gt+ysW)IHC

177C0110 02 E0 00 40 0B F0 09 00-12 00 02 00 00 00 00 00

177C0120 00 00 00 00 00 00 29 5D-3B DD 10 4E 4F 20 4E 41 )]NO NA

177C0130 4D 45 20 20 20 20 46 41-54 31 32 20 20 20 F1 7D ME FAT12

177C0140 FA 33 C9 8E D1 BC FC 7B-16 07 BD 78 00 C5 76 00 3xv

177C0150 1E 56 16 55 BF 22 05 89-7E 00 89 4E 02 B1 0B FC VU~N

177C0160 F3 A4 06 1F BD 00 7C C6-45 FE 0F 8B 46 18 88 45 |EFE

177C0170 F9 FB 38 66 24 7C 04 CD-13 72 3C 8A 46 10 98 F7 8f$|rltF

177C0180 66 16 03 46 1C 13 56 1E-03 46 0E 13 D1 50 52 89 fFVFPR

177C0190 46 FC 89 56 FE B8 20 00-8B 76 11 F7 E6 8B 5E 0B FV v^

177C01A0 03 C3 48 F7 F3 01 46 FC-11 4E FE 5A 58 BB 00 07 HFNZX

177C01B0 8B FB B1 01 E8 94 00 72-47 38 2D 74 19 B1 0B 56 rG8-tV

177C01C0 8B 76 3E F3 A6 5E 74 4A-4E 74 0B 03 F9 83 C7 15 vgt^tJNt

177C01D0 3B FB 72 E5 EB D7 2B C9-B8 D8 7D 87 46 3E 3C D8 r+Fgtlt

177C01E0 75 99 BE 80 7D AC 98 03-F0 AC 84 C0 74 17 3C FF utlt

177C01F0 74 09 B4 0E BB 07 00 CD-10 EB EE BE 83 7D EB E5 t

177C0200 BE 81 7D EB E0 33 C0 CD-16 5E 1F 8F 04 8F 44 02 3^D

177C0210 CD 19 BE 82 7D 8B 7D 0F-83 FF 02 72 C8 8B C7 48 rH

177C0220 48 8A 4E 0D F7 E1 03 46-FC 13 56 FE BB 00 07 53 HNFVS

177C0230 B1 04 E8 16 00 5B 72 C8-81 3F 4D 5A 75 A7 81 BF [rMZu

177C0240 00 02 42 4A 75 9F EA 00-02 70 00 50 52 51 91 92 BJupPRQ

177C0250 33 D2 F7 76 18 91 F7 76-18 42 87 CA F7 76 1A 8A 3vvBv

177C0260 F2 8A 56 24 8A E8 D0 CC-D0 CC 0A CC B8 01 02 CD V$

177C0270 13 59 5A 58 72 09 40 75-01 42 03 5E 0B E2 CC C3 YZXruB^

177C0280 03 18 01 27 0D 0A 44 69-73 63 6F 20 69 6E 63 6F Disco inco

177C0290 72 72 65 63 74 6F 20 20-20 FF 0D 0A 45 72 72 6F rrecto Erro

177C02A0 72 20 45 2F 53 20 20 20-20 20 FF 0D 0A 43 61 6D r ES Cam

177C02B0 62 69 65 20 65 6C 20 64-69 73 63 6F 20 79 20 70 bie el disco y p

177C02C0 72 65 73 69 6F 6E 65 20-75 6E 61 20 74 65 63 6C resione una tecl

177C02D0 61 20 20 20 20 0D 0A 00-49 4F 20 20 20 20 20 20 a IO

177C02E0 53 59 53 4D 53 44 4F 53-20 20 20 53 59 53 80 01 SYSMSDOS SYS

177C02F0 00 57 49 4E 42 4F 4F 54-20 53 59 53 00 00 55 AA WINBOOT SYSU

-

-Q

FIN [1] En las primeras versiones de MS-DOS era un modesto programita DEBUGCOM de apenas 16 KB La versioacuten que acompantildea a Windows98 es ya un ejecutable en formato EXE de 21 KB [2] En realidad DEBUG es una utilidad de enorme potencia que requeririacutea todo un libro para ella sola Puede encontrarse una amplia descripcioacuten de esta herramienta en el libro de Paul Somerson PC Magazine DOS Powers Tools [3] Desgraciadamente no hay una convencioacuten estaacutendar sobre la colocacioacuten de los datos en la BIOS de forma que cada fabricante sigue sus propias reglas y es imposible por tanto utilizarla para cualquier tipo de identificacioacuten del sistema [4] En palabras del mencionado Paul Somerson Desgraciadamente debido a que DEBUG es un programa tan increiacuteblemente potente tambieacuten es increiacuteblemente peligroso Hay un dicho que afirma que El software no puede destruir el hardware Desgraciadamente esto no es cierto Ademaacutes de enviar mecanismos sensibles de la unidad de disco a tierra de nadie es posible hacer saltar monitores o transformadores Repito si sigue al pie de la letra las instrucciones y hace caso a todos los avisos todo iraacute bien [5] Recuerde que la imagen de un ejecutable exe cargado en memoria es distinta de su imagen en disco Solo en los ejecutables com la imagen en disco es una imagen exacta de su disposicioacuten en memoria [6] Es evidente que un pequentildeo error de nuacutemero en este paraacutemetro puede acarrear consecuencias nefastas Por ejemplo si cree que estaacute jugando con el disquete e inadvertidamente se dirige al disco duro (relea la nota [4])

Page 11: El Comando DEBUG

N NAME N ltnombre_archivogt Se asigna un nombre al programa que estaacute siendo creado o modificado Se puede indicar la trayectoria de directorios L LOAD L ltbuffergt ltnumdiscogt ltsectorinigt ltnumsectorgt ltbuffergt es la direccioacuten en donde se carga la informacioacuten ltnumdiscogt es el nuacutemero (opcional) del disco de donde se leeraacute la informacioacuten (0=A 1=B 2=C etc) ltsectorinigt es el sector de disco absoluto (en hexadecimal) a leer ltnumsectorgt es la cantidad de sectores a leer No se pueden leer maacutes de 80H (128) sectores Si no se suministra la combinacioacuten ltnumdiscogt ltsectorinigt ltnumsectorgt DEBUG presume que se desea leer un archivo En este caso ltbuffergt es opcional Debe usarse el comando N (ver maacutes adelante) para especificar el archivo a leer Eacuteste se carga en CS0100 Ejemplo Se va a leer el sector 0 del disco A y se vuelca a partir de la direccioacuten DS100 como se puede observar el disco contiene mucha informacioacuten ( ESTO NO QUIERE DECIR QUE TENGA QUE SALIR LO MISMO EN SU VOLCADO )

l 100 0 0 1 -d 100 300

W WRITE W ltdireccioacutengt Graba el contenido de una zona de memoria a disco Si no se indica la direccioacuten se graba desde CS100h hasta CS100h+nuacutemero_bytes el nuacutemero de bytes se indica en BXCX (no es una direccioacuten segmentada sino un valor de 32 bits) Si se trata de un EXE no se permitiraacute grabarlo (para modificarlos hay que renombrarles para cambiarles la extensioacuten aunque de esta manera no seraacuten montados al cargarlos) La sintaxis es W ltbuffergt ltnumdiscogt ltsectorinigt ltnumsectorgt ltbuffergt es la direccioacuten de donde se carga la informacioacuten ltnumdiscogt es el nuacutemero (opcional) del disco en donde se escribiraacute la informacioacuten (0=A 1=B 2=C etc) ltsectorinigt es el sector de disco absoluto (en hexadecimal) en donde empieza la escritura ltnumsectorgt es la cantidad de sectores a leer No se pueden escribir maacutes de 80H (128) sectores Si no se suministra la combinacioacuten ltnumdiscogt ltsectorinigt ltnumsectorgt DEBUG presume que el inicio de archivo es CS100 En este caso ltbuffergt es opcional Debe usarse el comando N (ver arriba) para especificar el archivo a escribir Antes de escribir BXCX debe ajustarse al nuacutemero de bytes que desean grabarse W no puede escribir a archivos con la extensioacuten EXE o HEX [5] Ejemplo

N ltnomarchivogt BXCX lt--- 2000 W

S SEARCH S ltrangogt ltlistagt Busca una cadena de bytes por la memoria Para buscar la cadena PEPE terminada por cero en un aacuterea de 512 bytes desde DS100 se hariacutea S 100 L 200 PEPE0 (por defecto se busca en DS) No se encontrariacutea sin embargo pepe (en minuacutesculas) C COMPARE C ltrangogt ltdireccioacutengt Compara dos zonas de memoria mostrando las diferencias Por ejemplo para comparar 5 bytes de DS100 y DS200 se hace C 100 L 5 200 M MOVE M ltrangogt ltdireccioacutengt Maacutes que mover copia una zona de memoria en otra de manera inteligente (controlando los posibles solapamientos de los bloques) I INPUT I ltpuertogt Visualiza la lectura del puerto de ES indicado

O OUTPUT O ltpuertogt ltvalorgt Enviacutea un valor a un puerto de ES H HEX H ltvalor1gt ltvalor2gt Muestra la suma y resta de valor1 y valor2 ambos operandos de un maacuteximo de 16 bits (si hay desbordamiento se trunca el resultado que tampoco excede los 16 bits) Resultado ltresultado_1gt Es la suma ( ltvalor1gt + ltvalor2gt) ltresultado_2gt es la resta (ltvalor1gt - ltvalor2gt ) Ejemplo -h 0003 0002 0005 0001 -h 0000 0001 0001 FFFF como se observa el resultado de la segunda operacioacuten es FFFF que es el equivalente en complemento a 2 de -1 G GO G =ltiniciogt ltquiebre1gt ltquiebre2gt ltquiebre10gt Este comando ejecuta el coacutedigo en memoria Si se estaacute depurando un programa permite ejecutar el coacutedigo cargado en memoria Tambieacuten permite establecer puntos de quiebre (breakpoints) que son direcciones en las que se detiene la ejecucioacuten del programa La sintaxis es G =ltiniciogt ltquiebre1gt ltquiebre2gt ltquiebre10gt ltiniciogt es la direccioacuten de inicio de ejecucioacuten ltquiebre1gt hasta ltquiebre10gt son direcciones opcionales de paro del programa Si no se especifica ltiniciogt Go inicia con la direccioacuten contenida en CSIP Para lograr los quiebres DEBUG reemplaza el coacutedigo en las direcciones de quiebre por el valor hexadecimal CC que es el coacutedigo de interrupcioacuten Si DEBUG llega a CC todos los puntos de quiebre son restituidos los registros se despliegan (como con el comando R [veacutease adelante]) y se para la ejecucioacuten U UNASSEMBLE U ltrangogt Este comando desensambla el contenido de la memoria a partir de la posicioacuten actual Registros y Banderas del DEBUG La mayoriacutea de los comandos de DEBUG ejecutan una accioacuten y vuelven al indicador del shell pero si es un comando largo como puede ser mostrar un trozo grande de coacutedigo puede detenerse pulsando CTRL-Pausa o interrumpirse con CTRL-C para volver al shell Por ejemplo al teclear lo siguiente

- r [Enter]

-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 17A70100 E8CD0F CALL 10D0 - Se desplegaran todos los contenidos de los registros internos del microprocesador una forma alternativa de mostrarlos es usar el comando r utilizando como paraacutemetro el nombre del registro cuyo valor se quiera visualizar Por ejemplo

- r bx Esta instruccioacuten desplegaraacute uacutenicamente el contenido del registro BX y cambia el indicador del DEBUG de - a Estando asiacute el prompt es posible cambiar el valor del registro que se visualizoacute tecleando el nuevo valor y a continuacioacuten [Enter] o se puede dejar el valor anterior presionando [Enter] sin teclear ninguacuten valor Es posible cambiar el valor del registro de banderas asiacute como utilizarlo como estructura de control en nuestros programas como se veraacute maacutes adelante Cada bit del registro tiene un nombre y significado especial la lista dada a continuacioacuten describe el valor de cada bit tanto apagado como prendido y su relacioacuten con las operaciones del microprocesador

Overflow (O) NV = no hay desbordamiento OV = si lo hay Direction (D) UP = hacia adelante DN = hacia atraacutes Interrupts (I) DI = desactivadas EI = activadas Sign (S) PL = positivo NG = negativo Zero (Z) NZ = no es cero ZR = s lo es Auxiliary Carry (A) NA = no hay acarreo auxiliar

AC = hay acarreo auxiliar Parity (P) PO = paridad non PE = paridad par Carry (C) NC = no hay acarreo CY = Si lo hay

La estructura del ensamblador En el lenguaje ensamblador las liacuteneas de coacutedigo constan de dos partes la primera es el nombre de la instruccioacuten que se va a ejecutar y la segunda son los paraacutemetros del comando u operandos Por ejemplo

add ahbh Aquiacute add es el comando a ejecutar (en este caso una adicioacuten) y tanto ah como bh son los paraacutemetros El nombre de las instrucciones en este lenguaje estaacute formado por dos tres o cuatro letras a estas instrucciones tambieacuten se les llama nombres mnemoacutenicos o coacutedigos de operacioacuten ya que representan alguna funcioacuten que habraacute de realizar el microprocesador Existen algunos comandos que no requieren paraacutemetros para su operacioacuten asiacute como otros que requieren solo un paraacutemetro Algunas veces se utilizaraacuten las instrucciones como sigue

add al[170] Los corchetes en el segundo paraacutemetro nos indican que vamos a trabajar con el contenido de la posicioacuten de memoria nuacutemero 170 y no con el valor 170 a esto se le conoce como direccionamiento directo Primer programa en ensamblador con el DEBUG Vamos a crear un programa que sirva para ilustrar lo que hemos estado viendo lo que haremos seraacute una suma de dos valores que introduciremos directamente en el programa El primer paso es iniciar el DEBUG este paso consiste uacutenicamente en teclear DEBUG [Enter] en el prompt del sistema operativo Para ensamblar un programa en el DEBUG se utiliza el comando a (assemble) cuando se utiliza este comando se le puede dar como paraacutemetro la direccioacuten donde se desea que se inicie el ensamblado Si se omite el paraacutemetro el ensamblado se iniciaraacute en la localidad especificada por CSIP usualmente 0100H que es la localidad donde deben iniciar los programas con extensioacuten COM y seraacute la localidad que utilizaremos debido a que DEBUG solo puede crear este tipo especiacutefico de programas

Aunque en este momento no es necesario darle un paraacutemetro al comando a es recomendable hacerlo para evitar problemas una vez que se haga uso de los registros CSIP por lo tanto tecleamos

- a 100 [Enter] Al hacer esto apareceraacute en la pantalla algo como 0C1B0100 y el cursor se posiciona a la derecha de estos nuacutemeros noacutetese que los primeros cuatro diacutegitos (en sistema hexadecimal) pueden ser diferentes pero los uacuteltimos cuatro deben ser 0100 ya que es la direccioacuten que indicamos como inicio Ahora podemos introducir las instrucciones

0C1B0100 mov ax0002 coloca el valor 0002 en el registro ax 0C1B0103 mov bx0004 coloca el valor 0004 en el registro bx 0C1B0106 add axbx le adiciona al contenido de ax el contenido de bx 0C1B0108 int 20 provoca la terminacioacuten del programa 0C1B010A

No es necesario escribir los comentarios que van despueacutes del Una vez escrito el uacuteltimo comando int 20 se le da [Enter] sin escribir nada maacutes para volver al prompt del DEBUG La uacuteltima liacutenea escrita no es propiamente una instruccioacuten de ensamblador es una llamada a una interrupcioacuten del sistema operativo estas interrupciones seraacuten tratadas maacutes a fondo en un capiacutetulo posterior por el momento solo es necesario saber que nos ahorran un gran nuacutemero de liacuteneas y son muy uacutetiles para accesar a funciones del sistema operativo Para ejecutar el programa que escribimos se utiliza el comando g al utilizarlo veremos que aparece un mensaje que dice Program terminated normally Naturalmente con un mensaje como eacuteste no podemos estar seguros que el programa haya hecho la suma pero existe una forma sencilla de verificarlo utilizando el comando r del DEBUG podemos ver los contenidos de todos los registros del microprocesador simplemente teclee

- r [Enter] Apareceraacute en pantalla cada registro con su respectivo valor actual -R AX=0006 BX=0004 CX=0000 DX=0000 SP=FFFE BP=0000 SI=0000 DI=0000 DS=0C1B ES=0C1B SS=0C1B CS=0C1B IP=010A NV UP EI PL NZ NA PO NC 17A70100 E8CD0F CALL 10D0 - Existe la posibilidad de que los registros contengan valores diferentes pero AX y BX deben ser los mismos ya que son los que acabamos de modificar Otra forma de ver los valores mientras se ejecuta el programa es utilizando como paraacutemetro para g la direccioacuten donde queremos que termine la ejecucioacuten y muestre los valores de los registros en este caso seraacute g108 esta instruccioacuten ejecuta el programa se detiene en la direccioacuten 108 y muestra los contenidos de los registros Tambieacuten se puede llevar un seguimiento de lo que pasa en los registros utilizando el comando t (trace) la funcioacuten de este comando es ejecutar liacutenea por liacutenea lo que se ensambloacute mostrando cada vez los contenidos de los registros Para salir del DEBUG se utiliza el comando q (quit)

Guardar y cargar los programas No seriacutea praacutectico tener que escribir todo un programa cada vez que se necesite para evitar eso es posible guardar un programa en el disco con la enorme ventaja de que ya ensamblado no seraacute necesario correr de nuevo DEBUG para ejecutarlo ya que cuando el DEBUG guardo nuestro programa en el disco eacuteste se guardo en binario (archivo con la extensioacuten com) Los pasos a seguir para guardar un programa ya almacenado en la memoria son

Obtener la longitud del programa restando la direccioacuten final de la direccioacuten inicial naturalmente en sistema hexadecimal

Darle un nombre al programa y una extensioacuten

Poner la longitud del programa en el registro CX

Ordenar a DEBUG que escriba el programa en el disco Utilizando como ejemplo el programa del ejemplo anterior tendremos una idea maacutes clara de coacutemo llevar estos pasos Al terminar de ensamblar el programa se veriacutea asiacute

0C1B0100 mov ax0002 0C1B0103 mov bx0004 0C1B0106 add axbx 0C1B0108 int 20 0C1B010A

Para almacenarlo en el disco hacemos lo siguiente - h 10a 100 020a 000a - n pruebacom - r cx CX 0000 000a -w Writing 000A bytes

Para obtener la longitud de un programa se utiliza el comando h el cual nos muestra la suma y resta de dos nuacutemeros en hexadecimal Para obtener la longitud del programa le proporcionamos como paraacutemetros el valor de la direccioacuten final de nuestro programa (10A) y el valor de la direccioacuten inicial (0100) El primer resultado que nos muestra el comando es la suma de los paraacutemetros y el segundo es la resta El comando n nos permite poner un nombre al programa El comando r cx nos permite cambiar el contenido del registro CX al valor que obtuvimos del tamantildeo del archivo con h en este caso 000a ya que nos interesa el resultado de la resta de la direccioacuten inicial a la direccioacuten final

Por uacuteltimo el comando w escribe nuestro programa en el disco indicaacutendonos cuantos bytes escribioacute

NOTA Si se trabaja en una ventana de DOS de Windows Vista o 7 es probable que al momento de guardar su programa el DEBUG escriba mas coacutedigo que el sentildealado por el registro CX por consiguiente seraacute necesario limpiar el registro BX esto es ponerlo a ceros y despueacutes utilizar el comando w Por ejemplo _r bx BX 000E 0000 w

Para cargar un archivo ya guardado son necesarios dos pasos

Proporcionar el nombre del archivo que se cargaraacute a memoria

Cargarlo utilizando el comando l (load) Para obtener el resultado correcto de los siguientes pasos es necesario que previamente se haya creado el programa anterior Dentro del DEBUG escribimos lo siguiente

- n pruebacom - l - u 100 109 0C3D0100 B80200 MOV AX0002 0C3D0103 BB0400 MOV BX0004 0C3D0106 01D8 ADD AXBX 0C3D0108 CD20 INT 20

El uacuteltimo comando u se utiliza para verificar que el programa se cargoacute en memoria lo que hace es desensamblar el coacutedigo y mostrarlo ya desensamblado Los paraacutemetros le indican a DEBUG desde donde y hasta donde desensamblar DEBUG siempre carga los programas en memoria en la direccioacuten 100H a menos que se le indique alguna otra Un programa que realiza un conteo en pantalla Con el DEBUG es posible escribir un programa que realice un conteo en pantalla por razones de comprensioacuten nuestro programa solo realizara un conteo de 9 a 0 (conteo descendente) 0B3B0100 B90A00 MOV CX000A CX=10 en decimal 0B3B0103 88CA MOV DLCL 0B3B0105 80C22F ADD DL2F sumamos 02Fh a DL 0B3B0108 B402 MOV AH02 funcioacuten 02 de INT 21 para imprimir un caracter 0B3B010A CD21 INT 21

0B3B010C E2F5 LOOP 0103 CX=0 Si no salta a 0103 0B3B010E CD20 INT 20 termina el programa En la liacutenea 0103 se puede observar que el valor del registro CX en su parte baja (en CL) se almacena en el registro DL Si se omitiera la liacutenea 0105 entonces cuando se ejecutara la liacutenea 010A solo se imprimiriacutea en pantalla el coacutedigo ASCII del valor que contenga DL (el coacutedigo ASCII de 0Ah que es 10 en decimal es un caraacutecter especial no imprimible) Para conseguir el ldquoefectordquo de que el programa realiza el conteo en decimal se hace un corrimiento de 02F (47 en decimal) Por ejemplo cuando se ejecuta la liacutenea 0105 DL tendriacutea el valor de 39h=57d (02Fh+0Ah=39h=57d) y el coacutedigo ASCII de 57d es el caraacutecter ldquo9rdquo El sentencia LOOP decrementa CX en 1 si CX es diferente a 0 salta a la liacutenea 0103 El proceso se repite y el programa imprime en pantalla 9876543210 Seriacutea interesante que el programa anterior fuera modificado para que la numeracioacuten se imprimiera de la siguiente manera 9 8 7 6 5 4 3 2 1 0

NOTA Como se dijo anteriormente cuando el DEBUG almacena un programa en el disco este archivo se graba en binario esto es en ejecutable Por lo tanto no es necesario cargar el DEBUG para volver a ejecutar nuestro programa sino que se hace de manera directa desde DOS El problema surge cuando al ejecutar nuestro programa el resultado no se puede observar porque el DOS borra la pantalla despueacutes de terminar de ejecutar el programa Para evitar el borrado automaacutetico seraacute necesario agregarle a nuestro programa antes de la INT 20h una instruccioacuten para la lectura de un caraacutecter desde el teclado Para tal efecto utilizaremos la funcioacuten 08 de la INT 21h (un buen truco para que el programa haga una pausa) asiacute el programa esperara hasta que el usuario presiona una tecla permitiendo observar el resultado Ejemplo mov ah08 Int 21 Int 20

Condiciones ciclos y bifurcaciones Estas estructuras o formas de control le dan a la maacutequina un cierto grado de decisioacuten basado en la informacioacuten que recibe La forma maacutes sencilla de comprender este tema es por medio de ejemplos Vamos a crear tres programas que hagan lo mismo desplegar un nuacutemero determinado de veces una cadena de caracteres en la pantalla

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV CX000F veces que se desplegara la cadena 0C1B0128 MOV DX0102 copia cadena al registro DX 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F LOOP 012D si CXgt0 salta a 012D 0C1B0131 INT 20 termina el programa

Por medio del comando e es posible introducir una cadena de caracteres en una determinada localidad de memoria dada como paraacutemetro la cadena se introduce entre comillas le sigue un espacio luego el valor hexadecimal del retorno de carro un espacio el valor de liacutenea nueva y por uacuteltimo el siacutembolo $ que el ensamblador interpreta como final de la cadena La interrupcioacuten 21 utiliza el valor almacenado en el registro AH para ejecutar una determinada funcioacuten en este caso mostrar la cadena en pantalla la cadena que muestra es la que estaacute almacenada en el registro DX La instruccioacuten LOOP decrementa automaacuteticamente el registro CX en uno y si no ha llegado el valor de este registro a cero salta a la posicioacuten de memoria indicada como paraacutemetro lo cual crea un ciclo que se repite el nuacutemero de veces especificado por el valor de CX La interrupcioacuten 20 termina la ejecucioacuten del programa Otra forma de realizar la misma funcioacuten pero sin utilizar el comando LOOP es la siguiente

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV BX000F veces que se desplegara la cadena 0C1B0128 MOV DX0102 copia cadena al registro DX 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F DEC BX decrementa en 1 a BX 0C1B0130 JNZ 012D si BX es diferente a 0 salta a 012D 0C1B0132 INT 20 termina el programa

En este caso se utiliza el registro BX como contador para el programa y por medio de la instruccioacuten DEC se disminuye su valor en 1 La instruccioacuten JNZ verifica si el valor de BX es diferente a 0 esto con base en la bandera NZ en caso afirmativo salta hacia la direccioacuten 012D En caso contrario continuacutea la ejecucioacuten normal del programa y por lo tanto se termina Una uacuteltima variante del programa es utilizando de nuevo a CX como contador pero en lugar de utilizar LOOP utilizaremos decrementos a CX y comparacioacuten de CX a 0

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV DX0102 copia cadena al registro DX 0C1B0128 MOV CX000F veces que se desplegara la cadena 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F DEC CX decrementa en 1 a CX 0C1B0130 JCXZ 0134 si CX es igual a 0 salta a 0134 0C1B0132 JMP 012D salta a la direccioacuten 012D 0C1B0134 INT 20 termina el programa

En este ejemplo se usoacute la instruccioacuten JCXZ para controlar la condicioacuten de salto el significado de tal funcioacuten es salta si CX=0 El tipo de control a utilizar dependeraacute de las necesidades de programacioacuten en determinado momento

Manipulacioacuten de Posiciones de Memoria Con el DEBUG es posible almacenar y recuperar datos numeacutericos en memoria por medio de un programa a traveacutes de los registros del microprocesador Por ejemplo el siguiente programa almacena previamente dos valores numeacutericos en la posicioacuten 0300h y 0400h respectivamente despueacutes el programa los recupera realiza la operacioacuten de suma con esos valores y el resultado lo almacena en la posicioacuten 0500h -a 100 0B1C0100 mov ax0002 ax=2 0B1C0103 mov [0300]ax almacenamos 2 en la direccioacuten 0300h 0B1C0106 mov ax0004 ax=4 0B1C0109 mov [0400]ax almacenamos 4 en la direccioacuten 0400h 0B1C010C mov ax[0300] recuperamos el dato1 en AX 0B1C010F mov bx[0400] recuperamos el dato2 en BX 0B1C0113 add axbx hacemos la operacioacuten de suma en AX 0B1C0115 mov [0500]ax almacenamos el 6 en la direccioacuten 0500h 0B1C0118 int 21 0B1C011A - Un nuacutemero entre corchetes [numero_hex] indica una posicioacuten de memoria y su manejo se hace a traveacutes de registros ya que no es posible almacenar valores numeacutericos de manera directa Ejecutamos el programa -g 118 AX=0006 BX=0004 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=0B1C ES=0B1C SS=0B1C CS=0B1C IP=0118 NV UP EI PL NZ NA PE NC 0B1C0118 CD21 INT 21 - Para ver si el resultado se almaceno en la direccioacuten correcta hacemos

Como se puede observar en la direccioacuten 0B1C0500 se encuentra el 06 y en 0B1C0501 se encuentra el 00 que es el resultado de la operacioacuten 2+4 Perohellip Porque aparece el 06 y despueacutes el 00 pareceriacutea que el resultado fue de 0600 pero no es asiacute lo que sucedes que los datos se almacenan en memoria de la siguiente manera

Como se hizo la operacioacuten AX=AX+BX entonces el resultado es de 16 bits (dos bytes) AX=6 entonces AX=0000 0000 0000 0110 (16 bits) por lo tanto los 8 bits de menor peso de AX son 0000 0110 y deben almacenarse en la direccioacuten 0500 y en la direccioacuten 0501 se almacena 0000 0000

0 0 0 0 0 1 1 0 0500

0 0 0 0 0 0 0 0 0501

x x x x x x x x 0502

x x x x x x x x 0503

x x x x x x x x 0504

x x x x x x x x 0505

Interrupciones Definicioacuten de interrupcioacuten

Una interrupcioacuten es una instruccioacuten que detiene la ejecucioacuten de un programa para permitir el uso del microprocesador en un proceso prioritario Una vez concluido este uacuteltimo proceso se devuelve el control a la aplicacioacuten anterior

Por ejemplo cuando estamos trabajando con un procesador de palabras y en ese momento llega un aviso de uno de los puertos de comunicaciones se detiene temporalmente la aplicacioacuten que estaacutebamos utilizando para permitir el uso del microprocesador al manejo de la informacioacuten que estaacute llegando en ese momento Una vez terminada la transferencia de informacioacuten se reanudan las funciones normales del procesador de palabras Las interrupciones ocurren muy seguido sencillamente la interrupcioacuten que actualiza la hora del diacutea ocurre aproximadamente 18 veces por segundo Para lograr administrar todas estas interrupciones la computadora cuenta con un espacio de memoria llamado memoria baja donde se almacenan las direcciones de cierta localidad de memoria donde se encuentran un juego de instrucciones que el microprocesador ejecutaraacute para despueacutes regresar a la aplicacioacuten que estaba en proceso En los programas anteriores hicimos uso de la interrupcioacuten nuacutemero 20H para terminar la ejecucioacuten de nuestros programas y en otros ejemplos utilizamos otra interrupcioacuten para mostrar informacioacuten en pantalla (INT 21h) Utilizando DEBUG tecleamos

- a100 2C1B0100 JMP 011D 2C1B0102 [ENTER] - E 102 Hola como estas 0D 0A $ - A011D 2C1B011D MOV DX0102 2C1B0120 MOV AH09 2C1B0122 INT 21 2C1B0123 INT 20

Orden

creciente

de la

memoria

En este programa la interrupcioacuten 21h manda al monitor la cadena localizada en la direccioacuten a la que apunta el registro DX El valor que se le da a AH determina cual de las opciones de la interrupcioacuten 21h seraacute utilizada ya que esta interrupcioacuten cuenta con varias opciones El manejo directo de interrupciones es una de las partes maacutes fuertes del lenguaje ensamblador ya que con ellas es posible controlar eficientemente todos los dispositivos internos y externos de una computadora gracias al completo control que se tiene sobre operaciones de entrada y salida Maacutes del DEBUG Una caracteriacutestica poco conocida es que DEBUG puede aceptar entradas desde un archivo Script que puede ser un simple archivo de texto ASCII en el que cada comando esteacute separado del anterior por un INTRO Despueacutes del uacuteltimo que debe ser una Q para salir de DEBUG es conveniente dejar una liacutenea en blanco pulsando INTRO dos veces Las liacuteneas pueden contener comentarios Cualquier cosa a partir del caracter punto y coma () hasta el final de la liacutenea seraacute ignorado esto es un comentario D aquiacute se mostraraacute algo Suponiendo que tengamos un archivo Script de nombre Ordenestxt puede ser utilizado como entrada para DEBUG mediante un comando de redireccioacuten en la siguiente forma DEBUG lt ordenestxt Tambieacuten puede conseguirse que el programa redireccione la salida hacia un archivo que puede ser inspeccionado maacutes 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 podriacutea obtenerse un archivo Resulttxt con el siguiente comando DEBUG lt ordenestxt gt Resulttxt Errores Cuando DEBUG no sabe interpretar un comando muestra un mensaje de error y un indicador ^ debajo del sitio del comando donde estaacute el error Entradas y Salidas DEBUG asume que los datos numeacutericos proporcionados son hexadecimales y cuando se trate de direcciones de memoria deben introducirse en forma segmentada A su vez los resultados son mostrados tambieacuten 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

Cada fila muestra 16 posiciones de memoria a partir de la posicioacuten sentildealada por las columnas de la izquierda que las muestran como segmentodesplazamiento El bloque central muestra el contenido hexadecimal de cada byte mientras que el bloque derecho contiene la representacioacuten ASCII Por ejemplo la 3ra fila muestra el contenido de las posiciones 0B770120 a 0B77012F (ambas inclusive) Sus tres uacuteltimos bytes contienen respectivamente los caracteres r 9 y 2 que corresponden a las cantidades 72h 39h y 32h del bloque central Que como sabemos equivalen a los decimales 114 57 y 50 que son precisamente los valores ASCII de los caracteres ldquorrdquo ldquo9rdquo y ldquo2rdquo anteriormente mencionados

Nota Por razoacuten de que eacuteste tipo de salida pueda ser listado a impresora el bloque derecho no contiene en realidad la representacioacuten ASCII de todos los caracteres (algunos ni siquiera tienen una representacioacuten imprimible) En realidad solo se muestran los caracteres imprimibles del primer bloque (US-ASCII) El resto estaacute 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 caraacutecter imprimible Esto no significa que dichas posiciones representen efectivamente tales valores para la aplicacioacuten que las utiliza Por ejemplo puede que en realidad las dos posiciones de memoria mencionadas (dos octetos o bytes) en vez de los caracteres ldquo5rdquo y ldquoardquo representen una palabra de 16 bits en formato Little Endian que a su vez representan una cantidad entera (un nuacutemero) Comandos Aunque su descripcioacuten completa llenariacutea todo un capiacutetulo a continuacioacuten comentamos algunas de las opciones maacutes interesantes relativas a inspeccioacuten del coacutedigo y de contenidos de memoria La opcioacuten D (Dump) permite obtener un volcado del contenido de la memoria (de DEBUG) La sintaxis acepta dos formas D [direccioacuten-inicial] [L posiciones-desde-direccioacuten-inicial ] D [direccioacuten-inicial][direccioacuten-final] Naturalmente para que exista algo en el buacutefer de memoria (al principio quizaacutes solo contiene basura) es preciso indicarle que lea algo Este algo puede ser un rango de direcciones de memoria RAM una direccioacuten absoluta de disco (sector) un archivo o el contenido de los registros del procesador Para empezar puede indicaacutersele que cargue un archivo xxxxyz que tenemos en el directorio actual o en el PATH cuyo contenido queremos ver Cgt DEBUG xxxxyz -D aquiacute se obtendriacutea una salida anaacuteloga a la comentada

Hemos visto un ejemplo al tratar de los servicios de interrupciones del PC aquiacute mostraremos otro Sabemos que el punto de inicio de la BIOS es la direccioacuten F000FFF0 y que desde eacutesta posicioacuten hasta el final de la memoria DOS hay 16 bytes Puede obtenerse un volcado de estas posiciones con el siguiente comando -D F000FFF0 La salida en un equipo puede ser F000FFF0 CD 19 E0 00 F0 30 36 2F-33 30 2F 39 37 00 FC 38 0630978 En este caso el comando solo muestra una liacutenea porque ha alcanzado el final de la memoria Puede verse que la fecha de la BIOS del sistema ocupa las uacuteltimas posiciones Si se ordena el volcado de una direccioacuten suficientemente alejada del final de la memoria sin indicar ninguacuten nuacutemero de posiciones por defecto se toma el valor 128 (8 filas de 16 posiciones) Si desea una cantidad distinta hay que antildeadir una L (Long) y el nuacutemero de posiciones hasta un maacuteximo de 64 KB (FFFF) Todos los nuacutemeros deben ser expresados en hexadecimal Por consiguiente los dos comandos que siguen son equivalentes (recuerde que 80 es el equivalente hexadecimal de 128) D FE000000 D FE000000 L 80 He aquiacute el resultado

Sabemos que esta zona corresponde al aacuterea de la BIOS del Sistema Otra opcioacuten muy interesante nos permite buscar determinados contenidos a traveacutes de la memoria utilizando el prefijo S (Search) Existen dos sintaxis alternativas S direccioacuten-de-inicio L longitud-a-explorar contenido-a-buscar S direccioacuten-de-inicio direccioacuten-final L contenido-a-buscar El contenido debe ser proporcionado en hexadecimal (tal como apareceriacutea en la columna central del ejemplo anterior) o entre comillas si es un texto ASCII Por ejemplo en un equipo IBM deseo ver algunas caracteriacutesticas de la BIOS Seacute que estos datos se alojan a partir de la posicioacuten F0000000 hasta el final de la memoria Es decir una longitud de 64 Kbytes (FFFF) a partir de la posicioacuten de inicio y que seguramente los datos buscados estaraacuten cerca de la identificacioacuten de la propia BIOS (la cadena IBM) Por lo que se utiliza la siguiente sintaxis [3] -s f0000000 L ffff IBM

y se obtiene la siguiente salida F000E00E F000E111 con las direcciones donde se ha encontrado la ocurrencia buscada A continuacioacuten puedo explorar las proximidades de cada posicioacuten Por ejemplo para la primera -D f000e000

Si lo que se busca estaacute en un archivo primero hay que cargarlo Lo que se puede hacer de dos formas en la propia invocacioacuten de DEBUG o mediante los comandos N y L Por ejemplo si queremos inspeccionar el contenido del archivo morecom podemos utilizar dos formas CWINDOWSgtDEBUG cwindowscommandmorecom CWINDOWSgtDEBUG - N cwindowscommandmorecom - L La sintaxis para el prefijo N es N [path-name]nombre-de-archivo En ambos casos el contenido del archivo seraacute cargado en memoria y podraacute ser utilizado Atencioacuten despueacutes de la orden L (Load) DEBUG le avisaraacute si no encuentra el archivo pero seguiraacute su funcionamiento En tal caso simplemente piensa que N sentildeala el nombre de un nuevo archivo que crearaacute con el contenido de la memoria -de DEBUG- cuando posteriormente seleccione la opcioacuten escribir W (Write)[4]

Nota Como ya habraacute deducido DEBUG permite leer un archivo realizar modificaciones en eacutel (con la opcioacuten E) y escribir el archivo modificado bajo otro nombre con NW

A continuacioacuten podemos comprobar el tamantildeo del archivo cargado Para ello usamos la opcioacuten 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 17A70100 E8CD0F CALL 10D0 -

Aquiacute nos interesa especialmente el contenido del registro CX cuyo valor 2917h (1519d) en este caso sentildeala el tamantildeo del archivo en bytes Tambieacuten podiacuteamos haber utilizado directamente el comando R CX que nos proporciona el valor de dicho registro -R CX CX 2917 -

Nota A continuacioacuten del valor correspondiente DEBUG muestra dos puntos () sentildealando que puede cambiar el valor del registro introduciendo un nuevo nuacutemero Pulse INTRO para dejar las cosas como estaacuten y volver al prompt (-) de DEBUG

Al llegar a este punto es importante sentildealar que a excepcioacuten de los archivos exe DEBUG carga los archivos a partir de la direccioacuten 100h (256d) de su memoria De forma que el primer octeto del archivo se carga en la direccioacuten 100 el segundo en 101 etc En nuestro caso el archivo se extenderaacute desde la posicioacuten 100h hasta 2A17h (100h + 2917h) A continuacioacuten para buscar la cadena Microsoft en el archivo utilizamos cualquiera de los siguientes comandos - S 100 L 2917 Microsoft - S 100 2a17 Microsoft El primer comando sentildeala el punto de inicio y el tamantildeo de la zona a buscar el segundo utiliza los puntos inicial y final de la exploracioacuten Con ambos se obtiene la misma respuesta 17A71083 17A710B2

Truco Debido a la forma especial en que se cargan los ejecutables exe si quiere inspeccionar la forma nativa de uno de estos archivos (como es su imagen en el disco) debe hacer una copia del archivo renombrarlo con cualquier otra terminacioacuten (o sin ella) y cargar esta copia En caso contrario DEBUG se prepararaacute para funcionar como un verdadero depurador de tiempo de ejecucioacuten (run-time) para lo que cargaraacute el archivo y lo acomodaraacute en memoria de forma que pueda ejecutarse [5]

Como ejercicio compruebe las distintas longitudes y aspecto (especialmente al principio) de un mismo archivo exe cargaacutendolo con DEBUG de las dos formas (busque en su sistema un exe lo maacutes pequentildeo posible) Ademaacutes de la capacidad de leer archivos antes mencionada quizaacutes una de las opciones maacutes interesantes (y peligrosas) de DEBUG es la posibilidad de leerescribir el contenido de disco a bajo nivel mediante los prefijos L (Load) y W (Write) Se utiliza la siguiente sintaxis L [Direccioacuten] [Unidad] [Primer_sector] [Nuacutemero] W [Direccioacuten] [Unidad] [Primer_sector] [Nuacutemero] El significado de los paraacutemetros es como sigue

Direccioacuten Posicioacuten de la memoria de DEBUG a partir de la cual se instalaraacuten los datos leiacutedos del disco o se tomaraacuten para el proceso de escritura (aquiacute se utiliza generalmente el valor 100h)

Unidad Valor numeacuterico que indica la loacutegica a utilizar 0 = A 1 = B 2 = C 3 = D etc [6]

Primer sector A partir del que se realizaraacute la lectura o se comenzaraacute a escribir

Nuacutemero Nuacutemero de sectores que se desea cargarescribir Como DEBUG no puede leerescribir maacutes de 64 Kbytes (2

16 = 65536) y los sectores de disco son de 512 bytes

el maacuteximo nuacutemero de sectores es 128 (80h) Asiacute pues el valor maacuteximo aquiacute es 80 Ejemplo Para obtener el contenido del sector de arranque (Master boot sector MBR) de un disquete en A utilizaremos el comando CWINDOWSgtDEBUG - L 100 0 0 1 - D 100 L 200 Como el resultado no cabe en una pantalla ingeniaremos un procedimiento para conservarlo en un archivo (maacutes adelante nos serviraacute para otro propoacutesito) Para ello creamos un archivo scripttxt con el siguiente contenido (dos INTRO despueacutes de la Q) L 100 0 0 1 D 100 L 200 Q A continuacioacuten invocamos DEBUG con el comando CWINDOWSgtDEBUG lt Dbuzonscripttxt gt Dbuzonresultadtxt Despueacutes de un breve parpadeo del disco y del disquete vuelve el prompt del DOS La operacioacuten ha concluido y en el directorio correspondiente de la unidad D tenemos el archivo resultadtxt con el volcado del sector de arranque del disquete ademaacutes de los ecos de los comandos introducidos (los hemos mantenido para orientacioacuten del lector) Otra forma de poder visualizar el contenido del Sector de Arranque del disco es utilizando el DEBUG Por ejemplo dentro del DEBUG tecleamos lo siguiente -L 100 0 0 1

-D 100 L 200

177C0100 EB 3E 90 2B 79 73 57 29-49 48 43 00 02 01 01 00 gt+ysW)IHC

177C0110 02 E0 00 40 0B F0 09 00-12 00 02 00 00 00 00 00

177C0120 00 00 00 00 00 00 29 5D-3B DD 10 4E 4F 20 4E 41 )]NO NA

177C0130 4D 45 20 20 20 20 46 41-54 31 32 20 20 20 F1 7D ME FAT12

177C0140 FA 33 C9 8E D1 BC FC 7B-16 07 BD 78 00 C5 76 00 3xv

177C0150 1E 56 16 55 BF 22 05 89-7E 00 89 4E 02 B1 0B FC VU~N

177C0160 F3 A4 06 1F BD 00 7C C6-45 FE 0F 8B 46 18 88 45 |EFE

177C0170 F9 FB 38 66 24 7C 04 CD-13 72 3C 8A 46 10 98 F7 8f$|rltF

177C0180 66 16 03 46 1C 13 56 1E-03 46 0E 13 D1 50 52 89 fFVFPR

177C0190 46 FC 89 56 FE B8 20 00-8B 76 11 F7 E6 8B 5E 0B FV v^

177C01A0 03 C3 48 F7 F3 01 46 FC-11 4E FE 5A 58 BB 00 07 HFNZX

177C01B0 8B FB B1 01 E8 94 00 72-47 38 2D 74 19 B1 0B 56 rG8-tV

177C01C0 8B 76 3E F3 A6 5E 74 4A-4E 74 0B 03 F9 83 C7 15 vgt^tJNt

177C01D0 3B FB 72 E5 EB D7 2B C9-B8 D8 7D 87 46 3E 3C D8 r+Fgtlt

177C01E0 75 99 BE 80 7D AC 98 03-F0 AC 84 C0 74 17 3C FF utlt

177C01F0 74 09 B4 0E BB 07 00 CD-10 EB EE BE 83 7D EB E5 t

177C0200 BE 81 7D EB E0 33 C0 CD-16 5E 1F 8F 04 8F 44 02 3^D

177C0210 CD 19 BE 82 7D 8B 7D 0F-83 FF 02 72 C8 8B C7 48 rH

177C0220 48 8A 4E 0D F7 E1 03 46-FC 13 56 FE BB 00 07 53 HNFVS

177C0230 B1 04 E8 16 00 5B 72 C8-81 3F 4D 5A 75 A7 81 BF [rMZu

177C0240 00 02 42 4A 75 9F EA 00-02 70 00 50 52 51 91 92 BJupPRQ

177C0250 33 D2 F7 76 18 91 F7 76-18 42 87 CA F7 76 1A 8A 3vvBv

177C0260 F2 8A 56 24 8A E8 D0 CC-D0 CC 0A CC B8 01 02 CD V$

177C0270 13 59 5A 58 72 09 40 75-01 42 03 5E 0B E2 CC C3 YZXruB^

177C0280 03 18 01 27 0D 0A 44 69-73 63 6F 20 69 6E 63 6F Disco inco

177C0290 72 72 65 63 74 6F 20 20-20 FF 0D 0A 45 72 72 6F rrecto Erro

177C02A0 72 20 45 2F 53 20 20 20-20 20 FF 0D 0A 43 61 6D r ES Cam

177C02B0 62 69 65 20 65 6C 20 64-69 73 63 6F 20 79 20 70 bie el disco y p

177C02C0 72 65 73 69 6F 6E 65 20-75 6E 61 20 74 65 63 6C resione una tecl

177C02D0 61 20 20 20 20 0D 0A 00-49 4F 20 20 20 20 20 20 a IO

177C02E0 53 59 53 4D 53 44 4F 53-20 20 20 53 59 53 80 01 SYSMSDOS SYS

177C02F0 00 57 49 4E 42 4F 4F 54-20 53 59 53 00 00 55 AA WINBOOT SYSU

-

-Q

FIN [1] En las primeras versiones de MS-DOS era un modesto programita DEBUGCOM de apenas 16 KB La versioacuten que acompantildea a Windows98 es ya un ejecutable en formato EXE de 21 KB [2] En realidad DEBUG es una utilidad de enorme potencia que requeririacutea todo un libro para ella sola Puede encontrarse una amplia descripcioacuten de esta herramienta en el libro de Paul Somerson PC Magazine DOS Powers Tools [3] Desgraciadamente no hay una convencioacuten estaacutendar sobre la colocacioacuten de los datos en la BIOS de forma que cada fabricante sigue sus propias reglas y es imposible por tanto utilizarla para cualquier tipo de identificacioacuten del sistema [4] En palabras del mencionado Paul Somerson Desgraciadamente debido a que DEBUG es un programa tan increiacuteblemente potente tambieacuten es increiacuteblemente peligroso Hay un dicho que afirma que El software no puede destruir el hardware Desgraciadamente esto no es cierto Ademaacutes de enviar mecanismos sensibles de la unidad de disco a tierra de nadie es posible hacer saltar monitores o transformadores Repito si sigue al pie de la letra las instrucciones y hace caso a todos los avisos todo iraacute bien [5] Recuerde que la imagen de un ejecutable exe cargado en memoria es distinta de su imagen en disco Solo en los ejecutables com la imagen en disco es una imagen exacta de su disposicioacuten en memoria [6] Es evidente que un pequentildeo error de nuacutemero en este paraacutemetro puede acarrear consecuencias nefastas Por ejemplo si cree que estaacute jugando con el disquete e inadvertidamente se dirige al disco duro (relea la nota [4])

Page 12: El Comando DEBUG

W WRITE W ltdireccioacutengt Graba el contenido de una zona de memoria a disco Si no se indica la direccioacuten se graba desde CS100h hasta CS100h+nuacutemero_bytes el nuacutemero de bytes se indica en BXCX (no es una direccioacuten segmentada sino un valor de 32 bits) Si se trata de un EXE no se permitiraacute grabarlo (para modificarlos hay que renombrarles para cambiarles la extensioacuten aunque de esta manera no seraacuten montados al cargarlos) La sintaxis es W ltbuffergt ltnumdiscogt ltsectorinigt ltnumsectorgt ltbuffergt es la direccioacuten de donde se carga la informacioacuten ltnumdiscogt es el nuacutemero (opcional) del disco en donde se escribiraacute la informacioacuten (0=A 1=B 2=C etc) ltsectorinigt es el sector de disco absoluto (en hexadecimal) en donde empieza la escritura ltnumsectorgt es la cantidad de sectores a leer No se pueden escribir maacutes de 80H (128) sectores Si no se suministra la combinacioacuten ltnumdiscogt ltsectorinigt ltnumsectorgt DEBUG presume que el inicio de archivo es CS100 En este caso ltbuffergt es opcional Debe usarse el comando N (ver arriba) para especificar el archivo a escribir Antes de escribir BXCX debe ajustarse al nuacutemero de bytes que desean grabarse W no puede escribir a archivos con la extensioacuten EXE o HEX [5] Ejemplo

N ltnomarchivogt BXCX lt--- 2000 W

S SEARCH S ltrangogt ltlistagt Busca una cadena de bytes por la memoria Para buscar la cadena PEPE terminada por cero en un aacuterea de 512 bytes desde DS100 se hariacutea S 100 L 200 PEPE0 (por defecto se busca en DS) No se encontrariacutea sin embargo pepe (en minuacutesculas) C COMPARE C ltrangogt ltdireccioacutengt Compara dos zonas de memoria mostrando las diferencias Por ejemplo para comparar 5 bytes de DS100 y DS200 se hace C 100 L 5 200 M MOVE M ltrangogt ltdireccioacutengt Maacutes que mover copia una zona de memoria en otra de manera inteligente (controlando los posibles solapamientos de los bloques) I INPUT I ltpuertogt Visualiza la lectura del puerto de ES indicado

O OUTPUT O ltpuertogt ltvalorgt Enviacutea un valor a un puerto de ES H HEX H ltvalor1gt ltvalor2gt Muestra la suma y resta de valor1 y valor2 ambos operandos de un maacuteximo de 16 bits (si hay desbordamiento se trunca el resultado que tampoco excede los 16 bits) Resultado ltresultado_1gt Es la suma ( ltvalor1gt + ltvalor2gt) ltresultado_2gt es la resta (ltvalor1gt - ltvalor2gt ) Ejemplo -h 0003 0002 0005 0001 -h 0000 0001 0001 FFFF como se observa el resultado de la segunda operacioacuten es FFFF que es el equivalente en complemento a 2 de -1 G GO G =ltiniciogt ltquiebre1gt ltquiebre2gt ltquiebre10gt Este comando ejecuta el coacutedigo en memoria Si se estaacute depurando un programa permite ejecutar el coacutedigo cargado en memoria Tambieacuten permite establecer puntos de quiebre (breakpoints) que son direcciones en las que se detiene la ejecucioacuten del programa La sintaxis es G =ltiniciogt ltquiebre1gt ltquiebre2gt ltquiebre10gt ltiniciogt es la direccioacuten de inicio de ejecucioacuten ltquiebre1gt hasta ltquiebre10gt son direcciones opcionales de paro del programa Si no se especifica ltiniciogt Go inicia con la direccioacuten contenida en CSIP Para lograr los quiebres DEBUG reemplaza el coacutedigo en las direcciones de quiebre por el valor hexadecimal CC que es el coacutedigo de interrupcioacuten Si DEBUG llega a CC todos los puntos de quiebre son restituidos los registros se despliegan (como con el comando R [veacutease adelante]) y se para la ejecucioacuten U UNASSEMBLE U ltrangogt Este comando desensambla el contenido de la memoria a partir de la posicioacuten actual Registros y Banderas del DEBUG La mayoriacutea de los comandos de DEBUG ejecutan una accioacuten y vuelven al indicador del shell pero si es un comando largo como puede ser mostrar un trozo grande de coacutedigo puede detenerse pulsando CTRL-Pausa o interrumpirse con CTRL-C para volver al shell Por ejemplo al teclear lo siguiente

- r [Enter]

-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 17A70100 E8CD0F CALL 10D0 - Se desplegaran todos los contenidos de los registros internos del microprocesador una forma alternativa de mostrarlos es usar el comando r utilizando como paraacutemetro el nombre del registro cuyo valor se quiera visualizar Por ejemplo

- r bx Esta instruccioacuten desplegaraacute uacutenicamente el contenido del registro BX y cambia el indicador del DEBUG de - a Estando asiacute el prompt es posible cambiar el valor del registro que se visualizoacute tecleando el nuevo valor y a continuacioacuten [Enter] o se puede dejar el valor anterior presionando [Enter] sin teclear ninguacuten valor Es posible cambiar el valor del registro de banderas asiacute como utilizarlo como estructura de control en nuestros programas como se veraacute maacutes adelante Cada bit del registro tiene un nombre y significado especial la lista dada a continuacioacuten describe el valor de cada bit tanto apagado como prendido y su relacioacuten con las operaciones del microprocesador

Overflow (O) NV = no hay desbordamiento OV = si lo hay Direction (D) UP = hacia adelante DN = hacia atraacutes Interrupts (I) DI = desactivadas EI = activadas Sign (S) PL = positivo NG = negativo Zero (Z) NZ = no es cero ZR = s lo es Auxiliary Carry (A) NA = no hay acarreo auxiliar

AC = hay acarreo auxiliar Parity (P) PO = paridad non PE = paridad par Carry (C) NC = no hay acarreo CY = Si lo hay

La estructura del ensamblador En el lenguaje ensamblador las liacuteneas de coacutedigo constan de dos partes la primera es el nombre de la instruccioacuten que se va a ejecutar y la segunda son los paraacutemetros del comando u operandos Por ejemplo

add ahbh Aquiacute add es el comando a ejecutar (en este caso una adicioacuten) y tanto ah como bh son los paraacutemetros El nombre de las instrucciones en este lenguaje estaacute formado por dos tres o cuatro letras a estas instrucciones tambieacuten se les llama nombres mnemoacutenicos o coacutedigos de operacioacuten ya que representan alguna funcioacuten que habraacute de realizar el microprocesador Existen algunos comandos que no requieren paraacutemetros para su operacioacuten asiacute como otros que requieren solo un paraacutemetro Algunas veces se utilizaraacuten las instrucciones como sigue

add al[170] Los corchetes en el segundo paraacutemetro nos indican que vamos a trabajar con el contenido de la posicioacuten de memoria nuacutemero 170 y no con el valor 170 a esto se le conoce como direccionamiento directo Primer programa en ensamblador con el DEBUG Vamos a crear un programa que sirva para ilustrar lo que hemos estado viendo lo que haremos seraacute una suma de dos valores que introduciremos directamente en el programa El primer paso es iniciar el DEBUG este paso consiste uacutenicamente en teclear DEBUG [Enter] en el prompt del sistema operativo Para ensamblar un programa en el DEBUG se utiliza el comando a (assemble) cuando se utiliza este comando se le puede dar como paraacutemetro la direccioacuten donde se desea que se inicie el ensamblado Si se omite el paraacutemetro el ensamblado se iniciaraacute en la localidad especificada por CSIP usualmente 0100H que es la localidad donde deben iniciar los programas con extensioacuten COM y seraacute la localidad que utilizaremos debido a que DEBUG solo puede crear este tipo especiacutefico de programas

Aunque en este momento no es necesario darle un paraacutemetro al comando a es recomendable hacerlo para evitar problemas una vez que se haga uso de los registros CSIP por lo tanto tecleamos

- a 100 [Enter] Al hacer esto apareceraacute en la pantalla algo como 0C1B0100 y el cursor se posiciona a la derecha de estos nuacutemeros noacutetese que los primeros cuatro diacutegitos (en sistema hexadecimal) pueden ser diferentes pero los uacuteltimos cuatro deben ser 0100 ya que es la direccioacuten que indicamos como inicio Ahora podemos introducir las instrucciones

0C1B0100 mov ax0002 coloca el valor 0002 en el registro ax 0C1B0103 mov bx0004 coloca el valor 0004 en el registro bx 0C1B0106 add axbx le adiciona al contenido de ax el contenido de bx 0C1B0108 int 20 provoca la terminacioacuten del programa 0C1B010A

No es necesario escribir los comentarios que van despueacutes del Una vez escrito el uacuteltimo comando int 20 se le da [Enter] sin escribir nada maacutes para volver al prompt del DEBUG La uacuteltima liacutenea escrita no es propiamente una instruccioacuten de ensamblador es una llamada a una interrupcioacuten del sistema operativo estas interrupciones seraacuten tratadas maacutes a fondo en un capiacutetulo posterior por el momento solo es necesario saber que nos ahorran un gran nuacutemero de liacuteneas y son muy uacutetiles para accesar a funciones del sistema operativo Para ejecutar el programa que escribimos se utiliza el comando g al utilizarlo veremos que aparece un mensaje que dice Program terminated normally Naturalmente con un mensaje como eacuteste no podemos estar seguros que el programa haya hecho la suma pero existe una forma sencilla de verificarlo utilizando el comando r del DEBUG podemos ver los contenidos de todos los registros del microprocesador simplemente teclee

- r [Enter] Apareceraacute en pantalla cada registro con su respectivo valor actual -R AX=0006 BX=0004 CX=0000 DX=0000 SP=FFFE BP=0000 SI=0000 DI=0000 DS=0C1B ES=0C1B SS=0C1B CS=0C1B IP=010A NV UP EI PL NZ NA PO NC 17A70100 E8CD0F CALL 10D0 - Existe la posibilidad de que los registros contengan valores diferentes pero AX y BX deben ser los mismos ya que son los que acabamos de modificar Otra forma de ver los valores mientras se ejecuta el programa es utilizando como paraacutemetro para g la direccioacuten donde queremos que termine la ejecucioacuten y muestre los valores de los registros en este caso seraacute g108 esta instruccioacuten ejecuta el programa se detiene en la direccioacuten 108 y muestra los contenidos de los registros Tambieacuten se puede llevar un seguimiento de lo que pasa en los registros utilizando el comando t (trace) la funcioacuten de este comando es ejecutar liacutenea por liacutenea lo que se ensambloacute mostrando cada vez los contenidos de los registros Para salir del DEBUG se utiliza el comando q (quit)

Guardar y cargar los programas No seriacutea praacutectico tener que escribir todo un programa cada vez que se necesite para evitar eso es posible guardar un programa en el disco con la enorme ventaja de que ya ensamblado no seraacute necesario correr de nuevo DEBUG para ejecutarlo ya que cuando el DEBUG guardo nuestro programa en el disco eacuteste se guardo en binario (archivo con la extensioacuten com) Los pasos a seguir para guardar un programa ya almacenado en la memoria son

Obtener la longitud del programa restando la direccioacuten final de la direccioacuten inicial naturalmente en sistema hexadecimal

Darle un nombre al programa y una extensioacuten

Poner la longitud del programa en el registro CX

Ordenar a DEBUG que escriba el programa en el disco Utilizando como ejemplo el programa del ejemplo anterior tendremos una idea maacutes clara de coacutemo llevar estos pasos Al terminar de ensamblar el programa se veriacutea asiacute

0C1B0100 mov ax0002 0C1B0103 mov bx0004 0C1B0106 add axbx 0C1B0108 int 20 0C1B010A

Para almacenarlo en el disco hacemos lo siguiente - h 10a 100 020a 000a - n pruebacom - r cx CX 0000 000a -w Writing 000A bytes

Para obtener la longitud de un programa se utiliza el comando h el cual nos muestra la suma y resta de dos nuacutemeros en hexadecimal Para obtener la longitud del programa le proporcionamos como paraacutemetros el valor de la direccioacuten final de nuestro programa (10A) y el valor de la direccioacuten inicial (0100) El primer resultado que nos muestra el comando es la suma de los paraacutemetros y el segundo es la resta El comando n nos permite poner un nombre al programa El comando r cx nos permite cambiar el contenido del registro CX al valor que obtuvimos del tamantildeo del archivo con h en este caso 000a ya que nos interesa el resultado de la resta de la direccioacuten inicial a la direccioacuten final

Por uacuteltimo el comando w escribe nuestro programa en el disco indicaacutendonos cuantos bytes escribioacute

NOTA Si se trabaja en una ventana de DOS de Windows Vista o 7 es probable que al momento de guardar su programa el DEBUG escriba mas coacutedigo que el sentildealado por el registro CX por consiguiente seraacute necesario limpiar el registro BX esto es ponerlo a ceros y despueacutes utilizar el comando w Por ejemplo _r bx BX 000E 0000 w

Para cargar un archivo ya guardado son necesarios dos pasos

Proporcionar el nombre del archivo que se cargaraacute a memoria

Cargarlo utilizando el comando l (load) Para obtener el resultado correcto de los siguientes pasos es necesario que previamente se haya creado el programa anterior Dentro del DEBUG escribimos lo siguiente

- n pruebacom - l - u 100 109 0C3D0100 B80200 MOV AX0002 0C3D0103 BB0400 MOV BX0004 0C3D0106 01D8 ADD AXBX 0C3D0108 CD20 INT 20

El uacuteltimo comando u se utiliza para verificar que el programa se cargoacute en memoria lo que hace es desensamblar el coacutedigo y mostrarlo ya desensamblado Los paraacutemetros le indican a DEBUG desde donde y hasta donde desensamblar DEBUG siempre carga los programas en memoria en la direccioacuten 100H a menos que se le indique alguna otra Un programa que realiza un conteo en pantalla Con el DEBUG es posible escribir un programa que realice un conteo en pantalla por razones de comprensioacuten nuestro programa solo realizara un conteo de 9 a 0 (conteo descendente) 0B3B0100 B90A00 MOV CX000A CX=10 en decimal 0B3B0103 88CA MOV DLCL 0B3B0105 80C22F ADD DL2F sumamos 02Fh a DL 0B3B0108 B402 MOV AH02 funcioacuten 02 de INT 21 para imprimir un caracter 0B3B010A CD21 INT 21

0B3B010C E2F5 LOOP 0103 CX=0 Si no salta a 0103 0B3B010E CD20 INT 20 termina el programa En la liacutenea 0103 se puede observar que el valor del registro CX en su parte baja (en CL) se almacena en el registro DL Si se omitiera la liacutenea 0105 entonces cuando se ejecutara la liacutenea 010A solo se imprimiriacutea en pantalla el coacutedigo ASCII del valor que contenga DL (el coacutedigo ASCII de 0Ah que es 10 en decimal es un caraacutecter especial no imprimible) Para conseguir el ldquoefectordquo de que el programa realiza el conteo en decimal se hace un corrimiento de 02F (47 en decimal) Por ejemplo cuando se ejecuta la liacutenea 0105 DL tendriacutea el valor de 39h=57d (02Fh+0Ah=39h=57d) y el coacutedigo ASCII de 57d es el caraacutecter ldquo9rdquo El sentencia LOOP decrementa CX en 1 si CX es diferente a 0 salta a la liacutenea 0103 El proceso se repite y el programa imprime en pantalla 9876543210 Seriacutea interesante que el programa anterior fuera modificado para que la numeracioacuten se imprimiera de la siguiente manera 9 8 7 6 5 4 3 2 1 0

NOTA Como se dijo anteriormente cuando el DEBUG almacena un programa en el disco este archivo se graba en binario esto es en ejecutable Por lo tanto no es necesario cargar el DEBUG para volver a ejecutar nuestro programa sino que se hace de manera directa desde DOS El problema surge cuando al ejecutar nuestro programa el resultado no se puede observar porque el DOS borra la pantalla despueacutes de terminar de ejecutar el programa Para evitar el borrado automaacutetico seraacute necesario agregarle a nuestro programa antes de la INT 20h una instruccioacuten para la lectura de un caraacutecter desde el teclado Para tal efecto utilizaremos la funcioacuten 08 de la INT 21h (un buen truco para que el programa haga una pausa) asiacute el programa esperara hasta que el usuario presiona una tecla permitiendo observar el resultado Ejemplo mov ah08 Int 21 Int 20

Condiciones ciclos y bifurcaciones Estas estructuras o formas de control le dan a la maacutequina un cierto grado de decisioacuten basado en la informacioacuten que recibe La forma maacutes sencilla de comprender este tema es por medio de ejemplos Vamos a crear tres programas que hagan lo mismo desplegar un nuacutemero determinado de veces una cadena de caracteres en la pantalla

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV CX000F veces que se desplegara la cadena 0C1B0128 MOV DX0102 copia cadena al registro DX 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F LOOP 012D si CXgt0 salta a 012D 0C1B0131 INT 20 termina el programa

Por medio del comando e es posible introducir una cadena de caracteres en una determinada localidad de memoria dada como paraacutemetro la cadena se introduce entre comillas le sigue un espacio luego el valor hexadecimal del retorno de carro un espacio el valor de liacutenea nueva y por uacuteltimo el siacutembolo $ que el ensamblador interpreta como final de la cadena La interrupcioacuten 21 utiliza el valor almacenado en el registro AH para ejecutar una determinada funcioacuten en este caso mostrar la cadena en pantalla la cadena que muestra es la que estaacute almacenada en el registro DX La instruccioacuten LOOP decrementa automaacuteticamente el registro CX en uno y si no ha llegado el valor de este registro a cero salta a la posicioacuten de memoria indicada como paraacutemetro lo cual crea un ciclo que se repite el nuacutemero de veces especificado por el valor de CX La interrupcioacuten 20 termina la ejecucioacuten del programa Otra forma de realizar la misma funcioacuten pero sin utilizar el comando LOOP es la siguiente

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV BX000F veces que se desplegara la cadena 0C1B0128 MOV DX0102 copia cadena al registro DX 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F DEC BX decrementa en 1 a BX 0C1B0130 JNZ 012D si BX es diferente a 0 salta a 012D 0C1B0132 INT 20 termina el programa

En este caso se utiliza el registro BX como contador para el programa y por medio de la instruccioacuten DEC se disminuye su valor en 1 La instruccioacuten JNZ verifica si el valor de BX es diferente a 0 esto con base en la bandera NZ en caso afirmativo salta hacia la direccioacuten 012D En caso contrario continuacutea la ejecucioacuten normal del programa y por lo tanto se termina Una uacuteltima variante del programa es utilizando de nuevo a CX como contador pero en lugar de utilizar LOOP utilizaremos decrementos a CX y comparacioacuten de CX a 0

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV DX0102 copia cadena al registro DX 0C1B0128 MOV CX000F veces que se desplegara la cadena 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F DEC CX decrementa en 1 a CX 0C1B0130 JCXZ 0134 si CX es igual a 0 salta a 0134 0C1B0132 JMP 012D salta a la direccioacuten 012D 0C1B0134 INT 20 termina el programa

En este ejemplo se usoacute la instruccioacuten JCXZ para controlar la condicioacuten de salto el significado de tal funcioacuten es salta si CX=0 El tipo de control a utilizar dependeraacute de las necesidades de programacioacuten en determinado momento

Manipulacioacuten de Posiciones de Memoria Con el DEBUG es posible almacenar y recuperar datos numeacutericos en memoria por medio de un programa a traveacutes de los registros del microprocesador Por ejemplo el siguiente programa almacena previamente dos valores numeacutericos en la posicioacuten 0300h y 0400h respectivamente despueacutes el programa los recupera realiza la operacioacuten de suma con esos valores y el resultado lo almacena en la posicioacuten 0500h -a 100 0B1C0100 mov ax0002 ax=2 0B1C0103 mov [0300]ax almacenamos 2 en la direccioacuten 0300h 0B1C0106 mov ax0004 ax=4 0B1C0109 mov [0400]ax almacenamos 4 en la direccioacuten 0400h 0B1C010C mov ax[0300] recuperamos el dato1 en AX 0B1C010F mov bx[0400] recuperamos el dato2 en BX 0B1C0113 add axbx hacemos la operacioacuten de suma en AX 0B1C0115 mov [0500]ax almacenamos el 6 en la direccioacuten 0500h 0B1C0118 int 21 0B1C011A - Un nuacutemero entre corchetes [numero_hex] indica una posicioacuten de memoria y su manejo se hace a traveacutes de registros ya que no es posible almacenar valores numeacutericos de manera directa Ejecutamos el programa -g 118 AX=0006 BX=0004 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=0B1C ES=0B1C SS=0B1C CS=0B1C IP=0118 NV UP EI PL NZ NA PE NC 0B1C0118 CD21 INT 21 - Para ver si el resultado se almaceno en la direccioacuten correcta hacemos

Como se puede observar en la direccioacuten 0B1C0500 se encuentra el 06 y en 0B1C0501 se encuentra el 00 que es el resultado de la operacioacuten 2+4 Perohellip Porque aparece el 06 y despueacutes el 00 pareceriacutea que el resultado fue de 0600 pero no es asiacute lo que sucedes que los datos se almacenan en memoria de la siguiente manera

Como se hizo la operacioacuten AX=AX+BX entonces el resultado es de 16 bits (dos bytes) AX=6 entonces AX=0000 0000 0000 0110 (16 bits) por lo tanto los 8 bits de menor peso de AX son 0000 0110 y deben almacenarse en la direccioacuten 0500 y en la direccioacuten 0501 se almacena 0000 0000

0 0 0 0 0 1 1 0 0500

0 0 0 0 0 0 0 0 0501

x x x x x x x x 0502

x x x x x x x x 0503

x x x x x x x x 0504

x x x x x x x x 0505

Interrupciones Definicioacuten de interrupcioacuten

Una interrupcioacuten es una instruccioacuten que detiene la ejecucioacuten de un programa para permitir el uso del microprocesador en un proceso prioritario Una vez concluido este uacuteltimo proceso se devuelve el control a la aplicacioacuten anterior

Por ejemplo cuando estamos trabajando con un procesador de palabras y en ese momento llega un aviso de uno de los puertos de comunicaciones se detiene temporalmente la aplicacioacuten que estaacutebamos utilizando para permitir el uso del microprocesador al manejo de la informacioacuten que estaacute llegando en ese momento Una vez terminada la transferencia de informacioacuten se reanudan las funciones normales del procesador de palabras Las interrupciones ocurren muy seguido sencillamente la interrupcioacuten que actualiza la hora del diacutea ocurre aproximadamente 18 veces por segundo Para lograr administrar todas estas interrupciones la computadora cuenta con un espacio de memoria llamado memoria baja donde se almacenan las direcciones de cierta localidad de memoria donde se encuentran un juego de instrucciones que el microprocesador ejecutaraacute para despueacutes regresar a la aplicacioacuten que estaba en proceso En los programas anteriores hicimos uso de la interrupcioacuten nuacutemero 20H para terminar la ejecucioacuten de nuestros programas y en otros ejemplos utilizamos otra interrupcioacuten para mostrar informacioacuten en pantalla (INT 21h) Utilizando DEBUG tecleamos

- a100 2C1B0100 JMP 011D 2C1B0102 [ENTER] - E 102 Hola como estas 0D 0A $ - A011D 2C1B011D MOV DX0102 2C1B0120 MOV AH09 2C1B0122 INT 21 2C1B0123 INT 20

Orden

creciente

de la

memoria

En este programa la interrupcioacuten 21h manda al monitor la cadena localizada en la direccioacuten a la que apunta el registro DX El valor que se le da a AH determina cual de las opciones de la interrupcioacuten 21h seraacute utilizada ya que esta interrupcioacuten cuenta con varias opciones El manejo directo de interrupciones es una de las partes maacutes fuertes del lenguaje ensamblador ya que con ellas es posible controlar eficientemente todos los dispositivos internos y externos de una computadora gracias al completo control que se tiene sobre operaciones de entrada y salida Maacutes del DEBUG Una caracteriacutestica poco conocida es que DEBUG puede aceptar entradas desde un archivo Script que puede ser un simple archivo de texto ASCII en el que cada comando esteacute separado del anterior por un INTRO Despueacutes del uacuteltimo que debe ser una Q para salir de DEBUG es conveniente dejar una liacutenea en blanco pulsando INTRO dos veces Las liacuteneas pueden contener comentarios Cualquier cosa a partir del caracter punto y coma () hasta el final de la liacutenea seraacute ignorado esto es un comentario D aquiacute se mostraraacute algo Suponiendo que tengamos un archivo Script de nombre Ordenestxt puede ser utilizado como entrada para DEBUG mediante un comando de redireccioacuten en la siguiente forma DEBUG lt ordenestxt Tambieacuten puede conseguirse que el programa redireccione la salida hacia un archivo que puede ser inspeccionado maacutes 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 podriacutea obtenerse un archivo Resulttxt con el siguiente comando DEBUG lt ordenestxt gt Resulttxt Errores Cuando DEBUG no sabe interpretar un comando muestra un mensaje de error y un indicador ^ debajo del sitio del comando donde estaacute el error Entradas y Salidas DEBUG asume que los datos numeacutericos proporcionados son hexadecimales y cuando se trate de direcciones de memoria deben introducirse en forma segmentada A su vez los resultados son mostrados tambieacuten 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

Cada fila muestra 16 posiciones de memoria a partir de la posicioacuten sentildealada por las columnas de la izquierda que las muestran como segmentodesplazamiento El bloque central muestra el contenido hexadecimal de cada byte mientras que el bloque derecho contiene la representacioacuten ASCII Por ejemplo la 3ra fila muestra el contenido de las posiciones 0B770120 a 0B77012F (ambas inclusive) Sus tres uacuteltimos bytes contienen respectivamente los caracteres r 9 y 2 que corresponden a las cantidades 72h 39h y 32h del bloque central Que como sabemos equivalen a los decimales 114 57 y 50 que son precisamente los valores ASCII de los caracteres ldquorrdquo ldquo9rdquo y ldquo2rdquo anteriormente mencionados

Nota Por razoacuten de que eacuteste tipo de salida pueda ser listado a impresora el bloque derecho no contiene en realidad la representacioacuten ASCII de todos los caracteres (algunos ni siquiera tienen una representacioacuten imprimible) En realidad solo se muestran los caracteres imprimibles del primer bloque (US-ASCII) El resto estaacute 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 caraacutecter imprimible Esto no significa que dichas posiciones representen efectivamente tales valores para la aplicacioacuten que las utiliza Por ejemplo puede que en realidad las dos posiciones de memoria mencionadas (dos octetos o bytes) en vez de los caracteres ldquo5rdquo y ldquoardquo representen una palabra de 16 bits en formato Little Endian que a su vez representan una cantidad entera (un nuacutemero) Comandos Aunque su descripcioacuten completa llenariacutea todo un capiacutetulo a continuacioacuten comentamos algunas de las opciones maacutes interesantes relativas a inspeccioacuten del coacutedigo y de contenidos de memoria La opcioacuten D (Dump) permite obtener un volcado del contenido de la memoria (de DEBUG) La sintaxis acepta dos formas D [direccioacuten-inicial] [L posiciones-desde-direccioacuten-inicial ] D [direccioacuten-inicial][direccioacuten-final] Naturalmente para que exista algo en el buacutefer de memoria (al principio quizaacutes solo contiene basura) es preciso indicarle que lea algo Este algo puede ser un rango de direcciones de memoria RAM una direccioacuten absoluta de disco (sector) un archivo o el contenido de los registros del procesador Para empezar puede indicaacutersele que cargue un archivo xxxxyz que tenemos en el directorio actual o en el PATH cuyo contenido queremos ver Cgt DEBUG xxxxyz -D aquiacute se obtendriacutea una salida anaacuteloga a la comentada

Hemos visto un ejemplo al tratar de los servicios de interrupciones del PC aquiacute mostraremos otro Sabemos que el punto de inicio de la BIOS es la direccioacuten F000FFF0 y que desde eacutesta posicioacuten hasta el final de la memoria DOS hay 16 bytes Puede obtenerse un volcado de estas posiciones con el siguiente comando -D F000FFF0 La salida en un equipo puede ser F000FFF0 CD 19 E0 00 F0 30 36 2F-33 30 2F 39 37 00 FC 38 0630978 En este caso el comando solo muestra una liacutenea porque ha alcanzado el final de la memoria Puede verse que la fecha de la BIOS del sistema ocupa las uacuteltimas posiciones Si se ordena el volcado de una direccioacuten suficientemente alejada del final de la memoria sin indicar ninguacuten nuacutemero de posiciones por defecto se toma el valor 128 (8 filas de 16 posiciones) Si desea una cantidad distinta hay que antildeadir una L (Long) y el nuacutemero de posiciones hasta un maacuteximo de 64 KB (FFFF) Todos los nuacutemeros deben ser expresados en hexadecimal Por consiguiente los dos comandos que siguen son equivalentes (recuerde que 80 es el equivalente hexadecimal de 128) D FE000000 D FE000000 L 80 He aquiacute el resultado

Sabemos que esta zona corresponde al aacuterea de la BIOS del Sistema Otra opcioacuten muy interesante nos permite buscar determinados contenidos a traveacutes de la memoria utilizando el prefijo S (Search) Existen dos sintaxis alternativas S direccioacuten-de-inicio L longitud-a-explorar contenido-a-buscar S direccioacuten-de-inicio direccioacuten-final L contenido-a-buscar El contenido debe ser proporcionado en hexadecimal (tal como apareceriacutea en la columna central del ejemplo anterior) o entre comillas si es un texto ASCII Por ejemplo en un equipo IBM deseo ver algunas caracteriacutesticas de la BIOS Seacute que estos datos se alojan a partir de la posicioacuten F0000000 hasta el final de la memoria Es decir una longitud de 64 Kbytes (FFFF) a partir de la posicioacuten de inicio y que seguramente los datos buscados estaraacuten cerca de la identificacioacuten de la propia BIOS (la cadena IBM) Por lo que se utiliza la siguiente sintaxis [3] -s f0000000 L ffff IBM

y se obtiene la siguiente salida F000E00E F000E111 con las direcciones donde se ha encontrado la ocurrencia buscada A continuacioacuten puedo explorar las proximidades de cada posicioacuten Por ejemplo para la primera -D f000e000

Si lo que se busca estaacute en un archivo primero hay que cargarlo Lo que se puede hacer de dos formas en la propia invocacioacuten de DEBUG o mediante los comandos N y L Por ejemplo si queremos inspeccionar el contenido del archivo morecom podemos utilizar dos formas CWINDOWSgtDEBUG cwindowscommandmorecom CWINDOWSgtDEBUG - N cwindowscommandmorecom - L La sintaxis para el prefijo N es N [path-name]nombre-de-archivo En ambos casos el contenido del archivo seraacute cargado en memoria y podraacute ser utilizado Atencioacuten despueacutes de la orden L (Load) DEBUG le avisaraacute si no encuentra el archivo pero seguiraacute su funcionamiento En tal caso simplemente piensa que N sentildeala el nombre de un nuevo archivo que crearaacute con el contenido de la memoria -de DEBUG- cuando posteriormente seleccione la opcioacuten escribir W (Write)[4]

Nota Como ya habraacute deducido DEBUG permite leer un archivo realizar modificaciones en eacutel (con la opcioacuten E) y escribir el archivo modificado bajo otro nombre con NW

A continuacioacuten podemos comprobar el tamantildeo del archivo cargado Para ello usamos la opcioacuten 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 17A70100 E8CD0F CALL 10D0 -

Aquiacute nos interesa especialmente el contenido del registro CX cuyo valor 2917h (1519d) en este caso sentildeala el tamantildeo del archivo en bytes Tambieacuten podiacuteamos haber utilizado directamente el comando R CX que nos proporciona el valor de dicho registro -R CX CX 2917 -

Nota A continuacioacuten del valor correspondiente DEBUG muestra dos puntos () sentildealando que puede cambiar el valor del registro introduciendo un nuevo nuacutemero Pulse INTRO para dejar las cosas como estaacuten y volver al prompt (-) de DEBUG

Al llegar a este punto es importante sentildealar que a excepcioacuten de los archivos exe DEBUG carga los archivos a partir de la direccioacuten 100h (256d) de su memoria De forma que el primer octeto del archivo se carga en la direccioacuten 100 el segundo en 101 etc En nuestro caso el archivo se extenderaacute desde la posicioacuten 100h hasta 2A17h (100h + 2917h) A continuacioacuten para buscar la cadena Microsoft en el archivo utilizamos cualquiera de los siguientes comandos - S 100 L 2917 Microsoft - S 100 2a17 Microsoft El primer comando sentildeala el punto de inicio y el tamantildeo de la zona a buscar el segundo utiliza los puntos inicial y final de la exploracioacuten Con ambos se obtiene la misma respuesta 17A71083 17A710B2

Truco Debido a la forma especial en que se cargan los ejecutables exe si quiere inspeccionar la forma nativa de uno de estos archivos (como es su imagen en el disco) debe hacer una copia del archivo renombrarlo con cualquier otra terminacioacuten (o sin ella) y cargar esta copia En caso contrario DEBUG se prepararaacute para funcionar como un verdadero depurador de tiempo de ejecucioacuten (run-time) para lo que cargaraacute el archivo y lo acomodaraacute en memoria de forma que pueda ejecutarse [5]

Como ejercicio compruebe las distintas longitudes y aspecto (especialmente al principio) de un mismo archivo exe cargaacutendolo con DEBUG de las dos formas (busque en su sistema un exe lo maacutes pequentildeo posible) Ademaacutes de la capacidad de leer archivos antes mencionada quizaacutes una de las opciones maacutes interesantes (y peligrosas) de DEBUG es la posibilidad de leerescribir el contenido de disco a bajo nivel mediante los prefijos L (Load) y W (Write) Se utiliza la siguiente sintaxis L [Direccioacuten] [Unidad] [Primer_sector] [Nuacutemero] W [Direccioacuten] [Unidad] [Primer_sector] [Nuacutemero] El significado de los paraacutemetros es como sigue

Direccioacuten Posicioacuten de la memoria de DEBUG a partir de la cual se instalaraacuten los datos leiacutedos del disco o se tomaraacuten para el proceso de escritura (aquiacute se utiliza generalmente el valor 100h)

Unidad Valor numeacuterico que indica la loacutegica a utilizar 0 = A 1 = B 2 = C 3 = D etc [6]

Primer sector A partir del que se realizaraacute la lectura o se comenzaraacute a escribir

Nuacutemero Nuacutemero de sectores que se desea cargarescribir Como DEBUG no puede leerescribir maacutes de 64 Kbytes (2

16 = 65536) y los sectores de disco son de 512 bytes

el maacuteximo nuacutemero de sectores es 128 (80h) Asiacute pues el valor maacuteximo aquiacute es 80 Ejemplo Para obtener el contenido del sector de arranque (Master boot sector MBR) de un disquete en A utilizaremos el comando CWINDOWSgtDEBUG - L 100 0 0 1 - D 100 L 200 Como el resultado no cabe en una pantalla ingeniaremos un procedimiento para conservarlo en un archivo (maacutes adelante nos serviraacute para otro propoacutesito) Para ello creamos un archivo scripttxt con el siguiente contenido (dos INTRO despueacutes de la Q) L 100 0 0 1 D 100 L 200 Q A continuacioacuten invocamos DEBUG con el comando CWINDOWSgtDEBUG lt Dbuzonscripttxt gt Dbuzonresultadtxt Despueacutes de un breve parpadeo del disco y del disquete vuelve el prompt del DOS La operacioacuten ha concluido y en el directorio correspondiente de la unidad D tenemos el archivo resultadtxt con el volcado del sector de arranque del disquete ademaacutes de los ecos de los comandos introducidos (los hemos mantenido para orientacioacuten del lector) Otra forma de poder visualizar el contenido del Sector de Arranque del disco es utilizando el DEBUG Por ejemplo dentro del DEBUG tecleamos lo siguiente -L 100 0 0 1

-D 100 L 200

177C0100 EB 3E 90 2B 79 73 57 29-49 48 43 00 02 01 01 00 gt+ysW)IHC

177C0110 02 E0 00 40 0B F0 09 00-12 00 02 00 00 00 00 00

177C0120 00 00 00 00 00 00 29 5D-3B DD 10 4E 4F 20 4E 41 )]NO NA

177C0130 4D 45 20 20 20 20 46 41-54 31 32 20 20 20 F1 7D ME FAT12

177C0140 FA 33 C9 8E D1 BC FC 7B-16 07 BD 78 00 C5 76 00 3xv

177C0150 1E 56 16 55 BF 22 05 89-7E 00 89 4E 02 B1 0B FC VU~N

177C0160 F3 A4 06 1F BD 00 7C C6-45 FE 0F 8B 46 18 88 45 |EFE

177C0170 F9 FB 38 66 24 7C 04 CD-13 72 3C 8A 46 10 98 F7 8f$|rltF

177C0180 66 16 03 46 1C 13 56 1E-03 46 0E 13 D1 50 52 89 fFVFPR

177C0190 46 FC 89 56 FE B8 20 00-8B 76 11 F7 E6 8B 5E 0B FV v^

177C01A0 03 C3 48 F7 F3 01 46 FC-11 4E FE 5A 58 BB 00 07 HFNZX

177C01B0 8B FB B1 01 E8 94 00 72-47 38 2D 74 19 B1 0B 56 rG8-tV

177C01C0 8B 76 3E F3 A6 5E 74 4A-4E 74 0B 03 F9 83 C7 15 vgt^tJNt

177C01D0 3B FB 72 E5 EB D7 2B C9-B8 D8 7D 87 46 3E 3C D8 r+Fgtlt

177C01E0 75 99 BE 80 7D AC 98 03-F0 AC 84 C0 74 17 3C FF utlt

177C01F0 74 09 B4 0E BB 07 00 CD-10 EB EE BE 83 7D EB E5 t

177C0200 BE 81 7D EB E0 33 C0 CD-16 5E 1F 8F 04 8F 44 02 3^D

177C0210 CD 19 BE 82 7D 8B 7D 0F-83 FF 02 72 C8 8B C7 48 rH

177C0220 48 8A 4E 0D F7 E1 03 46-FC 13 56 FE BB 00 07 53 HNFVS

177C0230 B1 04 E8 16 00 5B 72 C8-81 3F 4D 5A 75 A7 81 BF [rMZu

177C0240 00 02 42 4A 75 9F EA 00-02 70 00 50 52 51 91 92 BJupPRQ

177C0250 33 D2 F7 76 18 91 F7 76-18 42 87 CA F7 76 1A 8A 3vvBv

177C0260 F2 8A 56 24 8A E8 D0 CC-D0 CC 0A CC B8 01 02 CD V$

177C0270 13 59 5A 58 72 09 40 75-01 42 03 5E 0B E2 CC C3 YZXruB^

177C0280 03 18 01 27 0D 0A 44 69-73 63 6F 20 69 6E 63 6F Disco inco

177C0290 72 72 65 63 74 6F 20 20-20 FF 0D 0A 45 72 72 6F rrecto Erro

177C02A0 72 20 45 2F 53 20 20 20-20 20 FF 0D 0A 43 61 6D r ES Cam

177C02B0 62 69 65 20 65 6C 20 64-69 73 63 6F 20 79 20 70 bie el disco y p

177C02C0 72 65 73 69 6F 6E 65 20-75 6E 61 20 74 65 63 6C resione una tecl

177C02D0 61 20 20 20 20 0D 0A 00-49 4F 20 20 20 20 20 20 a IO

177C02E0 53 59 53 4D 53 44 4F 53-20 20 20 53 59 53 80 01 SYSMSDOS SYS

177C02F0 00 57 49 4E 42 4F 4F 54-20 53 59 53 00 00 55 AA WINBOOT SYSU

-

-Q

FIN [1] En las primeras versiones de MS-DOS era un modesto programita DEBUGCOM de apenas 16 KB La versioacuten que acompantildea a Windows98 es ya un ejecutable en formato EXE de 21 KB [2] En realidad DEBUG es una utilidad de enorme potencia que requeririacutea todo un libro para ella sola Puede encontrarse una amplia descripcioacuten de esta herramienta en el libro de Paul Somerson PC Magazine DOS Powers Tools [3] Desgraciadamente no hay una convencioacuten estaacutendar sobre la colocacioacuten de los datos en la BIOS de forma que cada fabricante sigue sus propias reglas y es imposible por tanto utilizarla para cualquier tipo de identificacioacuten del sistema [4] En palabras del mencionado Paul Somerson Desgraciadamente debido a que DEBUG es un programa tan increiacuteblemente potente tambieacuten es increiacuteblemente peligroso Hay un dicho que afirma que El software no puede destruir el hardware Desgraciadamente esto no es cierto Ademaacutes de enviar mecanismos sensibles de la unidad de disco a tierra de nadie es posible hacer saltar monitores o transformadores Repito si sigue al pie de la letra las instrucciones y hace caso a todos los avisos todo iraacute bien [5] Recuerde que la imagen de un ejecutable exe cargado en memoria es distinta de su imagen en disco Solo en los ejecutables com la imagen en disco es una imagen exacta de su disposicioacuten en memoria [6] Es evidente que un pequentildeo error de nuacutemero en este paraacutemetro puede acarrear consecuencias nefastas Por ejemplo si cree que estaacute jugando con el disquete e inadvertidamente se dirige al disco duro (relea la nota [4])

Page 13: El Comando DEBUG

O OUTPUT O ltpuertogt ltvalorgt Enviacutea un valor a un puerto de ES H HEX H ltvalor1gt ltvalor2gt Muestra la suma y resta de valor1 y valor2 ambos operandos de un maacuteximo de 16 bits (si hay desbordamiento se trunca el resultado que tampoco excede los 16 bits) Resultado ltresultado_1gt Es la suma ( ltvalor1gt + ltvalor2gt) ltresultado_2gt es la resta (ltvalor1gt - ltvalor2gt ) Ejemplo -h 0003 0002 0005 0001 -h 0000 0001 0001 FFFF como se observa el resultado de la segunda operacioacuten es FFFF que es el equivalente en complemento a 2 de -1 G GO G =ltiniciogt ltquiebre1gt ltquiebre2gt ltquiebre10gt Este comando ejecuta el coacutedigo en memoria Si se estaacute depurando un programa permite ejecutar el coacutedigo cargado en memoria Tambieacuten permite establecer puntos de quiebre (breakpoints) que son direcciones en las que se detiene la ejecucioacuten del programa La sintaxis es G =ltiniciogt ltquiebre1gt ltquiebre2gt ltquiebre10gt ltiniciogt es la direccioacuten de inicio de ejecucioacuten ltquiebre1gt hasta ltquiebre10gt son direcciones opcionales de paro del programa Si no se especifica ltiniciogt Go inicia con la direccioacuten contenida en CSIP Para lograr los quiebres DEBUG reemplaza el coacutedigo en las direcciones de quiebre por el valor hexadecimal CC que es el coacutedigo de interrupcioacuten Si DEBUG llega a CC todos los puntos de quiebre son restituidos los registros se despliegan (como con el comando R [veacutease adelante]) y se para la ejecucioacuten U UNASSEMBLE U ltrangogt Este comando desensambla el contenido de la memoria a partir de la posicioacuten actual Registros y Banderas del DEBUG La mayoriacutea de los comandos de DEBUG ejecutan una accioacuten y vuelven al indicador del shell pero si es un comando largo como puede ser mostrar un trozo grande de coacutedigo puede detenerse pulsando CTRL-Pausa o interrumpirse con CTRL-C para volver al shell Por ejemplo al teclear lo siguiente

- r [Enter]

-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 17A70100 E8CD0F CALL 10D0 - Se desplegaran todos los contenidos de los registros internos del microprocesador una forma alternativa de mostrarlos es usar el comando r utilizando como paraacutemetro el nombre del registro cuyo valor se quiera visualizar Por ejemplo

- r bx Esta instruccioacuten desplegaraacute uacutenicamente el contenido del registro BX y cambia el indicador del DEBUG de - a Estando asiacute el prompt es posible cambiar el valor del registro que se visualizoacute tecleando el nuevo valor y a continuacioacuten [Enter] o se puede dejar el valor anterior presionando [Enter] sin teclear ninguacuten valor Es posible cambiar el valor del registro de banderas asiacute como utilizarlo como estructura de control en nuestros programas como se veraacute maacutes adelante Cada bit del registro tiene un nombre y significado especial la lista dada a continuacioacuten describe el valor de cada bit tanto apagado como prendido y su relacioacuten con las operaciones del microprocesador

Overflow (O) NV = no hay desbordamiento OV = si lo hay Direction (D) UP = hacia adelante DN = hacia atraacutes Interrupts (I) DI = desactivadas EI = activadas Sign (S) PL = positivo NG = negativo Zero (Z) NZ = no es cero ZR = s lo es Auxiliary Carry (A) NA = no hay acarreo auxiliar

AC = hay acarreo auxiliar Parity (P) PO = paridad non PE = paridad par Carry (C) NC = no hay acarreo CY = Si lo hay

La estructura del ensamblador En el lenguaje ensamblador las liacuteneas de coacutedigo constan de dos partes la primera es el nombre de la instruccioacuten que se va a ejecutar y la segunda son los paraacutemetros del comando u operandos Por ejemplo

add ahbh Aquiacute add es el comando a ejecutar (en este caso una adicioacuten) y tanto ah como bh son los paraacutemetros El nombre de las instrucciones en este lenguaje estaacute formado por dos tres o cuatro letras a estas instrucciones tambieacuten se les llama nombres mnemoacutenicos o coacutedigos de operacioacuten ya que representan alguna funcioacuten que habraacute de realizar el microprocesador Existen algunos comandos que no requieren paraacutemetros para su operacioacuten asiacute como otros que requieren solo un paraacutemetro Algunas veces se utilizaraacuten las instrucciones como sigue

add al[170] Los corchetes en el segundo paraacutemetro nos indican que vamos a trabajar con el contenido de la posicioacuten de memoria nuacutemero 170 y no con el valor 170 a esto se le conoce como direccionamiento directo Primer programa en ensamblador con el DEBUG Vamos a crear un programa que sirva para ilustrar lo que hemos estado viendo lo que haremos seraacute una suma de dos valores que introduciremos directamente en el programa El primer paso es iniciar el DEBUG este paso consiste uacutenicamente en teclear DEBUG [Enter] en el prompt del sistema operativo Para ensamblar un programa en el DEBUG se utiliza el comando a (assemble) cuando se utiliza este comando se le puede dar como paraacutemetro la direccioacuten donde se desea que se inicie el ensamblado Si se omite el paraacutemetro el ensamblado se iniciaraacute en la localidad especificada por CSIP usualmente 0100H que es la localidad donde deben iniciar los programas con extensioacuten COM y seraacute la localidad que utilizaremos debido a que DEBUG solo puede crear este tipo especiacutefico de programas

Aunque en este momento no es necesario darle un paraacutemetro al comando a es recomendable hacerlo para evitar problemas una vez que se haga uso de los registros CSIP por lo tanto tecleamos

- a 100 [Enter] Al hacer esto apareceraacute en la pantalla algo como 0C1B0100 y el cursor se posiciona a la derecha de estos nuacutemeros noacutetese que los primeros cuatro diacutegitos (en sistema hexadecimal) pueden ser diferentes pero los uacuteltimos cuatro deben ser 0100 ya que es la direccioacuten que indicamos como inicio Ahora podemos introducir las instrucciones

0C1B0100 mov ax0002 coloca el valor 0002 en el registro ax 0C1B0103 mov bx0004 coloca el valor 0004 en el registro bx 0C1B0106 add axbx le adiciona al contenido de ax el contenido de bx 0C1B0108 int 20 provoca la terminacioacuten del programa 0C1B010A

No es necesario escribir los comentarios que van despueacutes del Una vez escrito el uacuteltimo comando int 20 se le da [Enter] sin escribir nada maacutes para volver al prompt del DEBUG La uacuteltima liacutenea escrita no es propiamente una instruccioacuten de ensamblador es una llamada a una interrupcioacuten del sistema operativo estas interrupciones seraacuten tratadas maacutes a fondo en un capiacutetulo posterior por el momento solo es necesario saber que nos ahorran un gran nuacutemero de liacuteneas y son muy uacutetiles para accesar a funciones del sistema operativo Para ejecutar el programa que escribimos se utiliza el comando g al utilizarlo veremos que aparece un mensaje que dice Program terminated normally Naturalmente con un mensaje como eacuteste no podemos estar seguros que el programa haya hecho la suma pero existe una forma sencilla de verificarlo utilizando el comando r del DEBUG podemos ver los contenidos de todos los registros del microprocesador simplemente teclee

- r [Enter] Apareceraacute en pantalla cada registro con su respectivo valor actual -R AX=0006 BX=0004 CX=0000 DX=0000 SP=FFFE BP=0000 SI=0000 DI=0000 DS=0C1B ES=0C1B SS=0C1B CS=0C1B IP=010A NV UP EI PL NZ NA PO NC 17A70100 E8CD0F CALL 10D0 - Existe la posibilidad de que los registros contengan valores diferentes pero AX y BX deben ser los mismos ya que son los que acabamos de modificar Otra forma de ver los valores mientras se ejecuta el programa es utilizando como paraacutemetro para g la direccioacuten donde queremos que termine la ejecucioacuten y muestre los valores de los registros en este caso seraacute g108 esta instruccioacuten ejecuta el programa se detiene en la direccioacuten 108 y muestra los contenidos de los registros Tambieacuten se puede llevar un seguimiento de lo que pasa en los registros utilizando el comando t (trace) la funcioacuten de este comando es ejecutar liacutenea por liacutenea lo que se ensambloacute mostrando cada vez los contenidos de los registros Para salir del DEBUG se utiliza el comando q (quit)

Guardar y cargar los programas No seriacutea praacutectico tener que escribir todo un programa cada vez que se necesite para evitar eso es posible guardar un programa en el disco con la enorme ventaja de que ya ensamblado no seraacute necesario correr de nuevo DEBUG para ejecutarlo ya que cuando el DEBUG guardo nuestro programa en el disco eacuteste se guardo en binario (archivo con la extensioacuten com) Los pasos a seguir para guardar un programa ya almacenado en la memoria son

Obtener la longitud del programa restando la direccioacuten final de la direccioacuten inicial naturalmente en sistema hexadecimal

Darle un nombre al programa y una extensioacuten

Poner la longitud del programa en el registro CX

Ordenar a DEBUG que escriba el programa en el disco Utilizando como ejemplo el programa del ejemplo anterior tendremos una idea maacutes clara de coacutemo llevar estos pasos Al terminar de ensamblar el programa se veriacutea asiacute

0C1B0100 mov ax0002 0C1B0103 mov bx0004 0C1B0106 add axbx 0C1B0108 int 20 0C1B010A

Para almacenarlo en el disco hacemos lo siguiente - h 10a 100 020a 000a - n pruebacom - r cx CX 0000 000a -w Writing 000A bytes

Para obtener la longitud de un programa se utiliza el comando h el cual nos muestra la suma y resta de dos nuacutemeros en hexadecimal Para obtener la longitud del programa le proporcionamos como paraacutemetros el valor de la direccioacuten final de nuestro programa (10A) y el valor de la direccioacuten inicial (0100) El primer resultado que nos muestra el comando es la suma de los paraacutemetros y el segundo es la resta El comando n nos permite poner un nombre al programa El comando r cx nos permite cambiar el contenido del registro CX al valor que obtuvimos del tamantildeo del archivo con h en este caso 000a ya que nos interesa el resultado de la resta de la direccioacuten inicial a la direccioacuten final

Por uacuteltimo el comando w escribe nuestro programa en el disco indicaacutendonos cuantos bytes escribioacute

NOTA Si se trabaja en una ventana de DOS de Windows Vista o 7 es probable que al momento de guardar su programa el DEBUG escriba mas coacutedigo que el sentildealado por el registro CX por consiguiente seraacute necesario limpiar el registro BX esto es ponerlo a ceros y despueacutes utilizar el comando w Por ejemplo _r bx BX 000E 0000 w

Para cargar un archivo ya guardado son necesarios dos pasos

Proporcionar el nombre del archivo que se cargaraacute a memoria

Cargarlo utilizando el comando l (load) Para obtener el resultado correcto de los siguientes pasos es necesario que previamente se haya creado el programa anterior Dentro del DEBUG escribimos lo siguiente

- n pruebacom - l - u 100 109 0C3D0100 B80200 MOV AX0002 0C3D0103 BB0400 MOV BX0004 0C3D0106 01D8 ADD AXBX 0C3D0108 CD20 INT 20

El uacuteltimo comando u se utiliza para verificar que el programa se cargoacute en memoria lo que hace es desensamblar el coacutedigo y mostrarlo ya desensamblado Los paraacutemetros le indican a DEBUG desde donde y hasta donde desensamblar DEBUG siempre carga los programas en memoria en la direccioacuten 100H a menos que se le indique alguna otra Un programa que realiza un conteo en pantalla Con el DEBUG es posible escribir un programa que realice un conteo en pantalla por razones de comprensioacuten nuestro programa solo realizara un conteo de 9 a 0 (conteo descendente) 0B3B0100 B90A00 MOV CX000A CX=10 en decimal 0B3B0103 88CA MOV DLCL 0B3B0105 80C22F ADD DL2F sumamos 02Fh a DL 0B3B0108 B402 MOV AH02 funcioacuten 02 de INT 21 para imprimir un caracter 0B3B010A CD21 INT 21

0B3B010C E2F5 LOOP 0103 CX=0 Si no salta a 0103 0B3B010E CD20 INT 20 termina el programa En la liacutenea 0103 se puede observar que el valor del registro CX en su parte baja (en CL) se almacena en el registro DL Si se omitiera la liacutenea 0105 entonces cuando se ejecutara la liacutenea 010A solo se imprimiriacutea en pantalla el coacutedigo ASCII del valor que contenga DL (el coacutedigo ASCII de 0Ah que es 10 en decimal es un caraacutecter especial no imprimible) Para conseguir el ldquoefectordquo de que el programa realiza el conteo en decimal se hace un corrimiento de 02F (47 en decimal) Por ejemplo cuando se ejecuta la liacutenea 0105 DL tendriacutea el valor de 39h=57d (02Fh+0Ah=39h=57d) y el coacutedigo ASCII de 57d es el caraacutecter ldquo9rdquo El sentencia LOOP decrementa CX en 1 si CX es diferente a 0 salta a la liacutenea 0103 El proceso se repite y el programa imprime en pantalla 9876543210 Seriacutea interesante que el programa anterior fuera modificado para que la numeracioacuten se imprimiera de la siguiente manera 9 8 7 6 5 4 3 2 1 0

NOTA Como se dijo anteriormente cuando el DEBUG almacena un programa en el disco este archivo se graba en binario esto es en ejecutable Por lo tanto no es necesario cargar el DEBUG para volver a ejecutar nuestro programa sino que se hace de manera directa desde DOS El problema surge cuando al ejecutar nuestro programa el resultado no se puede observar porque el DOS borra la pantalla despueacutes de terminar de ejecutar el programa Para evitar el borrado automaacutetico seraacute necesario agregarle a nuestro programa antes de la INT 20h una instruccioacuten para la lectura de un caraacutecter desde el teclado Para tal efecto utilizaremos la funcioacuten 08 de la INT 21h (un buen truco para que el programa haga una pausa) asiacute el programa esperara hasta que el usuario presiona una tecla permitiendo observar el resultado Ejemplo mov ah08 Int 21 Int 20

Condiciones ciclos y bifurcaciones Estas estructuras o formas de control le dan a la maacutequina un cierto grado de decisioacuten basado en la informacioacuten que recibe La forma maacutes sencilla de comprender este tema es por medio de ejemplos Vamos a crear tres programas que hagan lo mismo desplegar un nuacutemero determinado de veces una cadena de caracteres en la pantalla

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV CX000F veces que se desplegara la cadena 0C1B0128 MOV DX0102 copia cadena al registro DX 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F LOOP 012D si CXgt0 salta a 012D 0C1B0131 INT 20 termina el programa

Por medio del comando e es posible introducir una cadena de caracteres en una determinada localidad de memoria dada como paraacutemetro la cadena se introduce entre comillas le sigue un espacio luego el valor hexadecimal del retorno de carro un espacio el valor de liacutenea nueva y por uacuteltimo el siacutembolo $ que el ensamblador interpreta como final de la cadena La interrupcioacuten 21 utiliza el valor almacenado en el registro AH para ejecutar una determinada funcioacuten en este caso mostrar la cadena en pantalla la cadena que muestra es la que estaacute almacenada en el registro DX La instruccioacuten LOOP decrementa automaacuteticamente el registro CX en uno y si no ha llegado el valor de este registro a cero salta a la posicioacuten de memoria indicada como paraacutemetro lo cual crea un ciclo que se repite el nuacutemero de veces especificado por el valor de CX La interrupcioacuten 20 termina la ejecucioacuten del programa Otra forma de realizar la misma funcioacuten pero sin utilizar el comando LOOP es la siguiente

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV BX000F veces que se desplegara la cadena 0C1B0128 MOV DX0102 copia cadena al registro DX 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F DEC BX decrementa en 1 a BX 0C1B0130 JNZ 012D si BX es diferente a 0 salta a 012D 0C1B0132 INT 20 termina el programa

En este caso se utiliza el registro BX como contador para el programa y por medio de la instruccioacuten DEC se disminuye su valor en 1 La instruccioacuten JNZ verifica si el valor de BX es diferente a 0 esto con base en la bandera NZ en caso afirmativo salta hacia la direccioacuten 012D En caso contrario continuacutea la ejecucioacuten normal del programa y por lo tanto se termina Una uacuteltima variante del programa es utilizando de nuevo a CX como contador pero en lugar de utilizar LOOP utilizaremos decrementos a CX y comparacioacuten de CX a 0

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV DX0102 copia cadena al registro DX 0C1B0128 MOV CX000F veces que se desplegara la cadena 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F DEC CX decrementa en 1 a CX 0C1B0130 JCXZ 0134 si CX es igual a 0 salta a 0134 0C1B0132 JMP 012D salta a la direccioacuten 012D 0C1B0134 INT 20 termina el programa

En este ejemplo se usoacute la instruccioacuten JCXZ para controlar la condicioacuten de salto el significado de tal funcioacuten es salta si CX=0 El tipo de control a utilizar dependeraacute de las necesidades de programacioacuten en determinado momento

Manipulacioacuten de Posiciones de Memoria Con el DEBUG es posible almacenar y recuperar datos numeacutericos en memoria por medio de un programa a traveacutes de los registros del microprocesador Por ejemplo el siguiente programa almacena previamente dos valores numeacutericos en la posicioacuten 0300h y 0400h respectivamente despueacutes el programa los recupera realiza la operacioacuten de suma con esos valores y el resultado lo almacena en la posicioacuten 0500h -a 100 0B1C0100 mov ax0002 ax=2 0B1C0103 mov [0300]ax almacenamos 2 en la direccioacuten 0300h 0B1C0106 mov ax0004 ax=4 0B1C0109 mov [0400]ax almacenamos 4 en la direccioacuten 0400h 0B1C010C mov ax[0300] recuperamos el dato1 en AX 0B1C010F mov bx[0400] recuperamos el dato2 en BX 0B1C0113 add axbx hacemos la operacioacuten de suma en AX 0B1C0115 mov [0500]ax almacenamos el 6 en la direccioacuten 0500h 0B1C0118 int 21 0B1C011A - Un nuacutemero entre corchetes [numero_hex] indica una posicioacuten de memoria y su manejo se hace a traveacutes de registros ya que no es posible almacenar valores numeacutericos de manera directa Ejecutamos el programa -g 118 AX=0006 BX=0004 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=0B1C ES=0B1C SS=0B1C CS=0B1C IP=0118 NV UP EI PL NZ NA PE NC 0B1C0118 CD21 INT 21 - Para ver si el resultado se almaceno en la direccioacuten correcta hacemos

Como se puede observar en la direccioacuten 0B1C0500 se encuentra el 06 y en 0B1C0501 se encuentra el 00 que es el resultado de la operacioacuten 2+4 Perohellip Porque aparece el 06 y despueacutes el 00 pareceriacutea que el resultado fue de 0600 pero no es asiacute lo que sucedes que los datos se almacenan en memoria de la siguiente manera

Como se hizo la operacioacuten AX=AX+BX entonces el resultado es de 16 bits (dos bytes) AX=6 entonces AX=0000 0000 0000 0110 (16 bits) por lo tanto los 8 bits de menor peso de AX son 0000 0110 y deben almacenarse en la direccioacuten 0500 y en la direccioacuten 0501 se almacena 0000 0000

0 0 0 0 0 1 1 0 0500

0 0 0 0 0 0 0 0 0501

x x x x x x x x 0502

x x x x x x x x 0503

x x x x x x x x 0504

x x x x x x x x 0505

Interrupciones Definicioacuten de interrupcioacuten

Una interrupcioacuten es una instruccioacuten que detiene la ejecucioacuten de un programa para permitir el uso del microprocesador en un proceso prioritario Una vez concluido este uacuteltimo proceso se devuelve el control a la aplicacioacuten anterior

Por ejemplo cuando estamos trabajando con un procesador de palabras y en ese momento llega un aviso de uno de los puertos de comunicaciones se detiene temporalmente la aplicacioacuten que estaacutebamos utilizando para permitir el uso del microprocesador al manejo de la informacioacuten que estaacute llegando en ese momento Una vez terminada la transferencia de informacioacuten se reanudan las funciones normales del procesador de palabras Las interrupciones ocurren muy seguido sencillamente la interrupcioacuten que actualiza la hora del diacutea ocurre aproximadamente 18 veces por segundo Para lograr administrar todas estas interrupciones la computadora cuenta con un espacio de memoria llamado memoria baja donde se almacenan las direcciones de cierta localidad de memoria donde se encuentran un juego de instrucciones que el microprocesador ejecutaraacute para despueacutes regresar a la aplicacioacuten que estaba en proceso En los programas anteriores hicimos uso de la interrupcioacuten nuacutemero 20H para terminar la ejecucioacuten de nuestros programas y en otros ejemplos utilizamos otra interrupcioacuten para mostrar informacioacuten en pantalla (INT 21h) Utilizando DEBUG tecleamos

- a100 2C1B0100 JMP 011D 2C1B0102 [ENTER] - E 102 Hola como estas 0D 0A $ - A011D 2C1B011D MOV DX0102 2C1B0120 MOV AH09 2C1B0122 INT 21 2C1B0123 INT 20

Orden

creciente

de la

memoria

En este programa la interrupcioacuten 21h manda al monitor la cadena localizada en la direccioacuten a la que apunta el registro DX El valor que se le da a AH determina cual de las opciones de la interrupcioacuten 21h seraacute utilizada ya que esta interrupcioacuten cuenta con varias opciones El manejo directo de interrupciones es una de las partes maacutes fuertes del lenguaje ensamblador ya que con ellas es posible controlar eficientemente todos los dispositivos internos y externos de una computadora gracias al completo control que se tiene sobre operaciones de entrada y salida Maacutes del DEBUG Una caracteriacutestica poco conocida es que DEBUG puede aceptar entradas desde un archivo Script que puede ser un simple archivo de texto ASCII en el que cada comando esteacute separado del anterior por un INTRO Despueacutes del uacuteltimo que debe ser una Q para salir de DEBUG es conveniente dejar una liacutenea en blanco pulsando INTRO dos veces Las liacuteneas pueden contener comentarios Cualquier cosa a partir del caracter punto y coma () hasta el final de la liacutenea seraacute ignorado esto es un comentario D aquiacute se mostraraacute algo Suponiendo que tengamos un archivo Script de nombre Ordenestxt puede ser utilizado como entrada para DEBUG mediante un comando de redireccioacuten en la siguiente forma DEBUG lt ordenestxt Tambieacuten puede conseguirse que el programa redireccione la salida hacia un archivo que puede ser inspeccionado maacutes 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 podriacutea obtenerse un archivo Resulttxt con el siguiente comando DEBUG lt ordenestxt gt Resulttxt Errores Cuando DEBUG no sabe interpretar un comando muestra un mensaje de error y un indicador ^ debajo del sitio del comando donde estaacute el error Entradas y Salidas DEBUG asume que los datos numeacutericos proporcionados son hexadecimales y cuando se trate de direcciones de memoria deben introducirse en forma segmentada A su vez los resultados son mostrados tambieacuten 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

Cada fila muestra 16 posiciones de memoria a partir de la posicioacuten sentildealada por las columnas de la izquierda que las muestran como segmentodesplazamiento El bloque central muestra el contenido hexadecimal de cada byte mientras que el bloque derecho contiene la representacioacuten ASCII Por ejemplo la 3ra fila muestra el contenido de las posiciones 0B770120 a 0B77012F (ambas inclusive) Sus tres uacuteltimos bytes contienen respectivamente los caracteres r 9 y 2 que corresponden a las cantidades 72h 39h y 32h del bloque central Que como sabemos equivalen a los decimales 114 57 y 50 que son precisamente los valores ASCII de los caracteres ldquorrdquo ldquo9rdquo y ldquo2rdquo anteriormente mencionados

Nota Por razoacuten de que eacuteste tipo de salida pueda ser listado a impresora el bloque derecho no contiene en realidad la representacioacuten ASCII de todos los caracteres (algunos ni siquiera tienen una representacioacuten imprimible) En realidad solo se muestran los caracteres imprimibles del primer bloque (US-ASCII) El resto estaacute 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 caraacutecter imprimible Esto no significa que dichas posiciones representen efectivamente tales valores para la aplicacioacuten que las utiliza Por ejemplo puede que en realidad las dos posiciones de memoria mencionadas (dos octetos o bytes) en vez de los caracteres ldquo5rdquo y ldquoardquo representen una palabra de 16 bits en formato Little Endian que a su vez representan una cantidad entera (un nuacutemero) Comandos Aunque su descripcioacuten completa llenariacutea todo un capiacutetulo a continuacioacuten comentamos algunas de las opciones maacutes interesantes relativas a inspeccioacuten del coacutedigo y de contenidos de memoria La opcioacuten D (Dump) permite obtener un volcado del contenido de la memoria (de DEBUG) La sintaxis acepta dos formas D [direccioacuten-inicial] [L posiciones-desde-direccioacuten-inicial ] D [direccioacuten-inicial][direccioacuten-final] Naturalmente para que exista algo en el buacutefer de memoria (al principio quizaacutes solo contiene basura) es preciso indicarle que lea algo Este algo puede ser un rango de direcciones de memoria RAM una direccioacuten absoluta de disco (sector) un archivo o el contenido de los registros del procesador Para empezar puede indicaacutersele que cargue un archivo xxxxyz que tenemos en el directorio actual o en el PATH cuyo contenido queremos ver Cgt DEBUG xxxxyz -D aquiacute se obtendriacutea una salida anaacuteloga a la comentada

Hemos visto un ejemplo al tratar de los servicios de interrupciones del PC aquiacute mostraremos otro Sabemos que el punto de inicio de la BIOS es la direccioacuten F000FFF0 y que desde eacutesta posicioacuten hasta el final de la memoria DOS hay 16 bytes Puede obtenerse un volcado de estas posiciones con el siguiente comando -D F000FFF0 La salida en un equipo puede ser F000FFF0 CD 19 E0 00 F0 30 36 2F-33 30 2F 39 37 00 FC 38 0630978 En este caso el comando solo muestra una liacutenea porque ha alcanzado el final de la memoria Puede verse que la fecha de la BIOS del sistema ocupa las uacuteltimas posiciones Si se ordena el volcado de una direccioacuten suficientemente alejada del final de la memoria sin indicar ninguacuten nuacutemero de posiciones por defecto se toma el valor 128 (8 filas de 16 posiciones) Si desea una cantidad distinta hay que antildeadir una L (Long) y el nuacutemero de posiciones hasta un maacuteximo de 64 KB (FFFF) Todos los nuacutemeros deben ser expresados en hexadecimal Por consiguiente los dos comandos que siguen son equivalentes (recuerde que 80 es el equivalente hexadecimal de 128) D FE000000 D FE000000 L 80 He aquiacute el resultado

Sabemos que esta zona corresponde al aacuterea de la BIOS del Sistema Otra opcioacuten muy interesante nos permite buscar determinados contenidos a traveacutes de la memoria utilizando el prefijo S (Search) Existen dos sintaxis alternativas S direccioacuten-de-inicio L longitud-a-explorar contenido-a-buscar S direccioacuten-de-inicio direccioacuten-final L contenido-a-buscar El contenido debe ser proporcionado en hexadecimal (tal como apareceriacutea en la columna central del ejemplo anterior) o entre comillas si es un texto ASCII Por ejemplo en un equipo IBM deseo ver algunas caracteriacutesticas de la BIOS Seacute que estos datos se alojan a partir de la posicioacuten F0000000 hasta el final de la memoria Es decir una longitud de 64 Kbytes (FFFF) a partir de la posicioacuten de inicio y que seguramente los datos buscados estaraacuten cerca de la identificacioacuten de la propia BIOS (la cadena IBM) Por lo que se utiliza la siguiente sintaxis [3] -s f0000000 L ffff IBM

y se obtiene la siguiente salida F000E00E F000E111 con las direcciones donde se ha encontrado la ocurrencia buscada A continuacioacuten puedo explorar las proximidades de cada posicioacuten Por ejemplo para la primera -D f000e000

Si lo que se busca estaacute en un archivo primero hay que cargarlo Lo que se puede hacer de dos formas en la propia invocacioacuten de DEBUG o mediante los comandos N y L Por ejemplo si queremos inspeccionar el contenido del archivo morecom podemos utilizar dos formas CWINDOWSgtDEBUG cwindowscommandmorecom CWINDOWSgtDEBUG - N cwindowscommandmorecom - L La sintaxis para el prefijo N es N [path-name]nombre-de-archivo En ambos casos el contenido del archivo seraacute cargado en memoria y podraacute ser utilizado Atencioacuten despueacutes de la orden L (Load) DEBUG le avisaraacute si no encuentra el archivo pero seguiraacute su funcionamiento En tal caso simplemente piensa que N sentildeala el nombre de un nuevo archivo que crearaacute con el contenido de la memoria -de DEBUG- cuando posteriormente seleccione la opcioacuten escribir W (Write)[4]

Nota Como ya habraacute deducido DEBUG permite leer un archivo realizar modificaciones en eacutel (con la opcioacuten E) y escribir el archivo modificado bajo otro nombre con NW

A continuacioacuten podemos comprobar el tamantildeo del archivo cargado Para ello usamos la opcioacuten 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 17A70100 E8CD0F CALL 10D0 -

Aquiacute nos interesa especialmente el contenido del registro CX cuyo valor 2917h (1519d) en este caso sentildeala el tamantildeo del archivo en bytes Tambieacuten podiacuteamos haber utilizado directamente el comando R CX que nos proporciona el valor de dicho registro -R CX CX 2917 -

Nota A continuacioacuten del valor correspondiente DEBUG muestra dos puntos () sentildealando que puede cambiar el valor del registro introduciendo un nuevo nuacutemero Pulse INTRO para dejar las cosas como estaacuten y volver al prompt (-) de DEBUG

Al llegar a este punto es importante sentildealar que a excepcioacuten de los archivos exe DEBUG carga los archivos a partir de la direccioacuten 100h (256d) de su memoria De forma que el primer octeto del archivo se carga en la direccioacuten 100 el segundo en 101 etc En nuestro caso el archivo se extenderaacute desde la posicioacuten 100h hasta 2A17h (100h + 2917h) A continuacioacuten para buscar la cadena Microsoft en el archivo utilizamos cualquiera de los siguientes comandos - S 100 L 2917 Microsoft - S 100 2a17 Microsoft El primer comando sentildeala el punto de inicio y el tamantildeo de la zona a buscar el segundo utiliza los puntos inicial y final de la exploracioacuten Con ambos se obtiene la misma respuesta 17A71083 17A710B2

Truco Debido a la forma especial en que se cargan los ejecutables exe si quiere inspeccionar la forma nativa de uno de estos archivos (como es su imagen en el disco) debe hacer una copia del archivo renombrarlo con cualquier otra terminacioacuten (o sin ella) y cargar esta copia En caso contrario DEBUG se prepararaacute para funcionar como un verdadero depurador de tiempo de ejecucioacuten (run-time) para lo que cargaraacute el archivo y lo acomodaraacute en memoria de forma que pueda ejecutarse [5]

Como ejercicio compruebe las distintas longitudes y aspecto (especialmente al principio) de un mismo archivo exe cargaacutendolo con DEBUG de las dos formas (busque en su sistema un exe lo maacutes pequentildeo posible) Ademaacutes de la capacidad de leer archivos antes mencionada quizaacutes una de las opciones maacutes interesantes (y peligrosas) de DEBUG es la posibilidad de leerescribir el contenido de disco a bajo nivel mediante los prefijos L (Load) y W (Write) Se utiliza la siguiente sintaxis L [Direccioacuten] [Unidad] [Primer_sector] [Nuacutemero] W [Direccioacuten] [Unidad] [Primer_sector] [Nuacutemero] El significado de los paraacutemetros es como sigue

Direccioacuten Posicioacuten de la memoria de DEBUG a partir de la cual se instalaraacuten los datos leiacutedos del disco o se tomaraacuten para el proceso de escritura (aquiacute se utiliza generalmente el valor 100h)

Unidad Valor numeacuterico que indica la loacutegica a utilizar 0 = A 1 = B 2 = C 3 = D etc [6]

Primer sector A partir del que se realizaraacute la lectura o se comenzaraacute a escribir

Nuacutemero Nuacutemero de sectores que se desea cargarescribir Como DEBUG no puede leerescribir maacutes de 64 Kbytes (2

16 = 65536) y los sectores de disco son de 512 bytes

el maacuteximo nuacutemero de sectores es 128 (80h) Asiacute pues el valor maacuteximo aquiacute es 80 Ejemplo Para obtener el contenido del sector de arranque (Master boot sector MBR) de un disquete en A utilizaremos el comando CWINDOWSgtDEBUG - L 100 0 0 1 - D 100 L 200 Como el resultado no cabe en una pantalla ingeniaremos un procedimiento para conservarlo en un archivo (maacutes adelante nos serviraacute para otro propoacutesito) Para ello creamos un archivo scripttxt con el siguiente contenido (dos INTRO despueacutes de la Q) L 100 0 0 1 D 100 L 200 Q A continuacioacuten invocamos DEBUG con el comando CWINDOWSgtDEBUG lt Dbuzonscripttxt gt Dbuzonresultadtxt Despueacutes de un breve parpadeo del disco y del disquete vuelve el prompt del DOS La operacioacuten ha concluido y en el directorio correspondiente de la unidad D tenemos el archivo resultadtxt con el volcado del sector de arranque del disquete ademaacutes de los ecos de los comandos introducidos (los hemos mantenido para orientacioacuten del lector) Otra forma de poder visualizar el contenido del Sector de Arranque del disco es utilizando el DEBUG Por ejemplo dentro del DEBUG tecleamos lo siguiente -L 100 0 0 1

-D 100 L 200

177C0100 EB 3E 90 2B 79 73 57 29-49 48 43 00 02 01 01 00 gt+ysW)IHC

177C0110 02 E0 00 40 0B F0 09 00-12 00 02 00 00 00 00 00

177C0120 00 00 00 00 00 00 29 5D-3B DD 10 4E 4F 20 4E 41 )]NO NA

177C0130 4D 45 20 20 20 20 46 41-54 31 32 20 20 20 F1 7D ME FAT12

177C0140 FA 33 C9 8E D1 BC FC 7B-16 07 BD 78 00 C5 76 00 3xv

177C0150 1E 56 16 55 BF 22 05 89-7E 00 89 4E 02 B1 0B FC VU~N

177C0160 F3 A4 06 1F BD 00 7C C6-45 FE 0F 8B 46 18 88 45 |EFE

177C0170 F9 FB 38 66 24 7C 04 CD-13 72 3C 8A 46 10 98 F7 8f$|rltF

177C0180 66 16 03 46 1C 13 56 1E-03 46 0E 13 D1 50 52 89 fFVFPR

177C0190 46 FC 89 56 FE B8 20 00-8B 76 11 F7 E6 8B 5E 0B FV v^

177C01A0 03 C3 48 F7 F3 01 46 FC-11 4E FE 5A 58 BB 00 07 HFNZX

177C01B0 8B FB B1 01 E8 94 00 72-47 38 2D 74 19 B1 0B 56 rG8-tV

177C01C0 8B 76 3E F3 A6 5E 74 4A-4E 74 0B 03 F9 83 C7 15 vgt^tJNt

177C01D0 3B FB 72 E5 EB D7 2B C9-B8 D8 7D 87 46 3E 3C D8 r+Fgtlt

177C01E0 75 99 BE 80 7D AC 98 03-F0 AC 84 C0 74 17 3C FF utlt

177C01F0 74 09 B4 0E BB 07 00 CD-10 EB EE BE 83 7D EB E5 t

177C0200 BE 81 7D EB E0 33 C0 CD-16 5E 1F 8F 04 8F 44 02 3^D

177C0210 CD 19 BE 82 7D 8B 7D 0F-83 FF 02 72 C8 8B C7 48 rH

177C0220 48 8A 4E 0D F7 E1 03 46-FC 13 56 FE BB 00 07 53 HNFVS

177C0230 B1 04 E8 16 00 5B 72 C8-81 3F 4D 5A 75 A7 81 BF [rMZu

177C0240 00 02 42 4A 75 9F EA 00-02 70 00 50 52 51 91 92 BJupPRQ

177C0250 33 D2 F7 76 18 91 F7 76-18 42 87 CA F7 76 1A 8A 3vvBv

177C0260 F2 8A 56 24 8A E8 D0 CC-D0 CC 0A CC B8 01 02 CD V$

177C0270 13 59 5A 58 72 09 40 75-01 42 03 5E 0B E2 CC C3 YZXruB^

177C0280 03 18 01 27 0D 0A 44 69-73 63 6F 20 69 6E 63 6F Disco inco

177C0290 72 72 65 63 74 6F 20 20-20 FF 0D 0A 45 72 72 6F rrecto Erro

177C02A0 72 20 45 2F 53 20 20 20-20 20 FF 0D 0A 43 61 6D r ES Cam

177C02B0 62 69 65 20 65 6C 20 64-69 73 63 6F 20 79 20 70 bie el disco y p

177C02C0 72 65 73 69 6F 6E 65 20-75 6E 61 20 74 65 63 6C resione una tecl

177C02D0 61 20 20 20 20 0D 0A 00-49 4F 20 20 20 20 20 20 a IO

177C02E0 53 59 53 4D 53 44 4F 53-20 20 20 53 59 53 80 01 SYSMSDOS SYS

177C02F0 00 57 49 4E 42 4F 4F 54-20 53 59 53 00 00 55 AA WINBOOT SYSU

-

-Q

FIN [1] En las primeras versiones de MS-DOS era un modesto programita DEBUGCOM de apenas 16 KB La versioacuten que acompantildea a Windows98 es ya un ejecutable en formato EXE de 21 KB [2] En realidad DEBUG es una utilidad de enorme potencia que requeririacutea todo un libro para ella sola Puede encontrarse una amplia descripcioacuten de esta herramienta en el libro de Paul Somerson PC Magazine DOS Powers Tools [3] Desgraciadamente no hay una convencioacuten estaacutendar sobre la colocacioacuten de los datos en la BIOS de forma que cada fabricante sigue sus propias reglas y es imposible por tanto utilizarla para cualquier tipo de identificacioacuten del sistema [4] En palabras del mencionado Paul Somerson Desgraciadamente debido a que DEBUG es un programa tan increiacuteblemente potente tambieacuten es increiacuteblemente peligroso Hay un dicho que afirma que El software no puede destruir el hardware Desgraciadamente esto no es cierto Ademaacutes de enviar mecanismos sensibles de la unidad de disco a tierra de nadie es posible hacer saltar monitores o transformadores Repito si sigue al pie de la letra las instrucciones y hace caso a todos los avisos todo iraacute bien [5] Recuerde que la imagen de un ejecutable exe cargado en memoria es distinta de su imagen en disco Solo en los ejecutables com la imagen en disco es una imagen exacta de su disposicioacuten en memoria [6] Es evidente que un pequentildeo error de nuacutemero en este paraacutemetro puede acarrear consecuencias nefastas Por ejemplo si cree que estaacute jugando con el disquete e inadvertidamente se dirige al disco duro (relea la nota [4])

Page 14: El Comando DEBUG

-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 17A70100 E8CD0F CALL 10D0 - Se desplegaran todos los contenidos de los registros internos del microprocesador una forma alternativa de mostrarlos es usar el comando r utilizando como paraacutemetro el nombre del registro cuyo valor se quiera visualizar Por ejemplo

- r bx Esta instruccioacuten desplegaraacute uacutenicamente el contenido del registro BX y cambia el indicador del DEBUG de - a Estando asiacute el prompt es posible cambiar el valor del registro que se visualizoacute tecleando el nuevo valor y a continuacioacuten [Enter] o se puede dejar el valor anterior presionando [Enter] sin teclear ninguacuten valor Es posible cambiar el valor del registro de banderas asiacute como utilizarlo como estructura de control en nuestros programas como se veraacute maacutes adelante Cada bit del registro tiene un nombre y significado especial la lista dada a continuacioacuten describe el valor de cada bit tanto apagado como prendido y su relacioacuten con las operaciones del microprocesador

Overflow (O) NV = no hay desbordamiento OV = si lo hay Direction (D) UP = hacia adelante DN = hacia atraacutes Interrupts (I) DI = desactivadas EI = activadas Sign (S) PL = positivo NG = negativo Zero (Z) NZ = no es cero ZR = s lo es Auxiliary Carry (A) NA = no hay acarreo auxiliar

AC = hay acarreo auxiliar Parity (P) PO = paridad non PE = paridad par Carry (C) NC = no hay acarreo CY = Si lo hay

La estructura del ensamblador En el lenguaje ensamblador las liacuteneas de coacutedigo constan de dos partes la primera es el nombre de la instruccioacuten que se va a ejecutar y la segunda son los paraacutemetros del comando u operandos Por ejemplo

add ahbh Aquiacute add es el comando a ejecutar (en este caso una adicioacuten) y tanto ah como bh son los paraacutemetros El nombre de las instrucciones en este lenguaje estaacute formado por dos tres o cuatro letras a estas instrucciones tambieacuten se les llama nombres mnemoacutenicos o coacutedigos de operacioacuten ya que representan alguna funcioacuten que habraacute de realizar el microprocesador Existen algunos comandos que no requieren paraacutemetros para su operacioacuten asiacute como otros que requieren solo un paraacutemetro Algunas veces se utilizaraacuten las instrucciones como sigue

add al[170] Los corchetes en el segundo paraacutemetro nos indican que vamos a trabajar con el contenido de la posicioacuten de memoria nuacutemero 170 y no con el valor 170 a esto se le conoce como direccionamiento directo Primer programa en ensamblador con el DEBUG Vamos a crear un programa que sirva para ilustrar lo que hemos estado viendo lo que haremos seraacute una suma de dos valores que introduciremos directamente en el programa El primer paso es iniciar el DEBUG este paso consiste uacutenicamente en teclear DEBUG [Enter] en el prompt del sistema operativo Para ensamblar un programa en el DEBUG se utiliza el comando a (assemble) cuando se utiliza este comando se le puede dar como paraacutemetro la direccioacuten donde se desea que se inicie el ensamblado Si se omite el paraacutemetro el ensamblado se iniciaraacute en la localidad especificada por CSIP usualmente 0100H que es la localidad donde deben iniciar los programas con extensioacuten COM y seraacute la localidad que utilizaremos debido a que DEBUG solo puede crear este tipo especiacutefico de programas

Aunque en este momento no es necesario darle un paraacutemetro al comando a es recomendable hacerlo para evitar problemas una vez que se haga uso de los registros CSIP por lo tanto tecleamos

- a 100 [Enter] Al hacer esto apareceraacute en la pantalla algo como 0C1B0100 y el cursor se posiciona a la derecha de estos nuacutemeros noacutetese que los primeros cuatro diacutegitos (en sistema hexadecimal) pueden ser diferentes pero los uacuteltimos cuatro deben ser 0100 ya que es la direccioacuten que indicamos como inicio Ahora podemos introducir las instrucciones

0C1B0100 mov ax0002 coloca el valor 0002 en el registro ax 0C1B0103 mov bx0004 coloca el valor 0004 en el registro bx 0C1B0106 add axbx le adiciona al contenido de ax el contenido de bx 0C1B0108 int 20 provoca la terminacioacuten del programa 0C1B010A

No es necesario escribir los comentarios que van despueacutes del Una vez escrito el uacuteltimo comando int 20 se le da [Enter] sin escribir nada maacutes para volver al prompt del DEBUG La uacuteltima liacutenea escrita no es propiamente una instruccioacuten de ensamblador es una llamada a una interrupcioacuten del sistema operativo estas interrupciones seraacuten tratadas maacutes a fondo en un capiacutetulo posterior por el momento solo es necesario saber que nos ahorran un gran nuacutemero de liacuteneas y son muy uacutetiles para accesar a funciones del sistema operativo Para ejecutar el programa que escribimos se utiliza el comando g al utilizarlo veremos que aparece un mensaje que dice Program terminated normally Naturalmente con un mensaje como eacuteste no podemos estar seguros que el programa haya hecho la suma pero existe una forma sencilla de verificarlo utilizando el comando r del DEBUG podemos ver los contenidos de todos los registros del microprocesador simplemente teclee

- r [Enter] Apareceraacute en pantalla cada registro con su respectivo valor actual -R AX=0006 BX=0004 CX=0000 DX=0000 SP=FFFE BP=0000 SI=0000 DI=0000 DS=0C1B ES=0C1B SS=0C1B CS=0C1B IP=010A NV UP EI PL NZ NA PO NC 17A70100 E8CD0F CALL 10D0 - Existe la posibilidad de que los registros contengan valores diferentes pero AX y BX deben ser los mismos ya que son los que acabamos de modificar Otra forma de ver los valores mientras se ejecuta el programa es utilizando como paraacutemetro para g la direccioacuten donde queremos que termine la ejecucioacuten y muestre los valores de los registros en este caso seraacute g108 esta instruccioacuten ejecuta el programa se detiene en la direccioacuten 108 y muestra los contenidos de los registros Tambieacuten se puede llevar un seguimiento de lo que pasa en los registros utilizando el comando t (trace) la funcioacuten de este comando es ejecutar liacutenea por liacutenea lo que se ensambloacute mostrando cada vez los contenidos de los registros Para salir del DEBUG se utiliza el comando q (quit)

Guardar y cargar los programas No seriacutea praacutectico tener que escribir todo un programa cada vez que se necesite para evitar eso es posible guardar un programa en el disco con la enorme ventaja de que ya ensamblado no seraacute necesario correr de nuevo DEBUG para ejecutarlo ya que cuando el DEBUG guardo nuestro programa en el disco eacuteste se guardo en binario (archivo con la extensioacuten com) Los pasos a seguir para guardar un programa ya almacenado en la memoria son

Obtener la longitud del programa restando la direccioacuten final de la direccioacuten inicial naturalmente en sistema hexadecimal

Darle un nombre al programa y una extensioacuten

Poner la longitud del programa en el registro CX

Ordenar a DEBUG que escriba el programa en el disco Utilizando como ejemplo el programa del ejemplo anterior tendremos una idea maacutes clara de coacutemo llevar estos pasos Al terminar de ensamblar el programa se veriacutea asiacute

0C1B0100 mov ax0002 0C1B0103 mov bx0004 0C1B0106 add axbx 0C1B0108 int 20 0C1B010A

Para almacenarlo en el disco hacemos lo siguiente - h 10a 100 020a 000a - n pruebacom - r cx CX 0000 000a -w Writing 000A bytes

Para obtener la longitud de un programa se utiliza el comando h el cual nos muestra la suma y resta de dos nuacutemeros en hexadecimal Para obtener la longitud del programa le proporcionamos como paraacutemetros el valor de la direccioacuten final de nuestro programa (10A) y el valor de la direccioacuten inicial (0100) El primer resultado que nos muestra el comando es la suma de los paraacutemetros y el segundo es la resta El comando n nos permite poner un nombre al programa El comando r cx nos permite cambiar el contenido del registro CX al valor que obtuvimos del tamantildeo del archivo con h en este caso 000a ya que nos interesa el resultado de la resta de la direccioacuten inicial a la direccioacuten final

Por uacuteltimo el comando w escribe nuestro programa en el disco indicaacutendonos cuantos bytes escribioacute

NOTA Si se trabaja en una ventana de DOS de Windows Vista o 7 es probable que al momento de guardar su programa el DEBUG escriba mas coacutedigo que el sentildealado por el registro CX por consiguiente seraacute necesario limpiar el registro BX esto es ponerlo a ceros y despueacutes utilizar el comando w Por ejemplo _r bx BX 000E 0000 w

Para cargar un archivo ya guardado son necesarios dos pasos

Proporcionar el nombre del archivo que se cargaraacute a memoria

Cargarlo utilizando el comando l (load) Para obtener el resultado correcto de los siguientes pasos es necesario que previamente se haya creado el programa anterior Dentro del DEBUG escribimos lo siguiente

- n pruebacom - l - u 100 109 0C3D0100 B80200 MOV AX0002 0C3D0103 BB0400 MOV BX0004 0C3D0106 01D8 ADD AXBX 0C3D0108 CD20 INT 20

El uacuteltimo comando u se utiliza para verificar que el programa se cargoacute en memoria lo que hace es desensamblar el coacutedigo y mostrarlo ya desensamblado Los paraacutemetros le indican a DEBUG desde donde y hasta donde desensamblar DEBUG siempre carga los programas en memoria en la direccioacuten 100H a menos que se le indique alguna otra Un programa que realiza un conteo en pantalla Con el DEBUG es posible escribir un programa que realice un conteo en pantalla por razones de comprensioacuten nuestro programa solo realizara un conteo de 9 a 0 (conteo descendente) 0B3B0100 B90A00 MOV CX000A CX=10 en decimal 0B3B0103 88CA MOV DLCL 0B3B0105 80C22F ADD DL2F sumamos 02Fh a DL 0B3B0108 B402 MOV AH02 funcioacuten 02 de INT 21 para imprimir un caracter 0B3B010A CD21 INT 21

0B3B010C E2F5 LOOP 0103 CX=0 Si no salta a 0103 0B3B010E CD20 INT 20 termina el programa En la liacutenea 0103 se puede observar que el valor del registro CX en su parte baja (en CL) se almacena en el registro DL Si se omitiera la liacutenea 0105 entonces cuando se ejecutara la liacutenea 010A solo se imprimiriacutea en pantalla el coacutedigo ASCII del valor que contenga DL (el coacutedigo ASCII de 0Ah que es 10 en decimal es un caraacutecter especial no imprimible) Para conseguir el ldquoefectordquo de que el programa realiza el conteo en decimal se hace un corrimiento de 02F (47 en decimal) Por ejemplo cuando se ejecuta la liacutenea 0105 DL tendriacutea el valor de 39h=57d (02Fh+0Ah=39h=57d) y el coacutedigo ASCII de 57d es el caraacutecter ldquo9rdquo El sentencia LOOP decrementa CX en 1 si CX es diferente a 0 salta a la liacutenea 0103 El proceso se repite y el programa imprime en pantalla 9876543210 Seriacutea interesante que el programa anterior fuera modificado para que la numeracioacuten se imprimiera de la siguiente manera 9 8 7 6 5 4 3 2 1 0

NOTA Como se dijo anteriormente cuando el DEBUG almacena un programa en el disco este archivo se graba en binario esto es en ejecutable Por lo tanto no es necesario cargar el DEBUG para volver a ejecutar nuestro programa sino que se hace de manera directa desde DOS El problema surge cuando al ejecutar nuestro programa el resultado no se puede observar porque el DOS borra la pantalla despueacutes de terminar de ejecutar el programa Para evitar el borrado automaacutetico seraacute necesario agregarle a nuestro programa antes de la INT 20h una instruccioacuten para la lectura de un caraacutecter desde el teclado Para tal efecto utilizaremos la funcioacuten 08 de la INT 21h (un buen truco para que el programa haga una pausa) asiacute el programa esperara hasta que el usuario presiona una tecla permitiendo observar el resultado Ejemplo mov ah08 Int 21 Int 20

Condiciones ciclos y bifurcaciones Estas estructuras o formas de control le dan a la maacutequina un cierto grado de decisioacuten basado en la informacioacuten que recibe La forma maacutes sencilla de comprender este tema es por medio de ejemplos Vamos a crear tres programas que hagan lo mismo desplegar un nuacutemero determinado de veces una cadena de caracteres en la pantalla

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV CX000F veces que se desplegara la cadena 0C1B0128 MOV DX0102 copia cadena al registro DX 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F LOOP 012D si CXgt0 salta a 012D 0C1B0131 INT 20 termina el programa

Por medio del comando e es posible introducir una cadena de caracteres en una determinada localidad de memoria dada como paraacutemetro la cadena se introduce entre comillas le sigue un espacio luego el valor hexadecimal del retorno de carro un espacio el valor de liacutenea nueva y por uacuteltimo el siacutembolo $ que el ensamblador interpreta como final de la cadena La interrupcioacuten 21 utiliza el valor almacenado en el registro AH para ejecutar una determinada funcioacuten en este caso mostrar la cadena en pantalla la cadena que muestra es la que estaacute almacenada en el registro DX La instruccioacuten LOOP decrementa automaacuteticamente el registro CX en uno y si no ha llegado el valor de este registro a cero salta a la posicioacuten de memoria indicada como paraacutemetro lo cual crea un ciclo que se repite el nuacutemero de veces especificado por el valor de CX La interrupcioacuten 20 termina la ejecucioacuten del programa Otra forma de realizar la misma funcioacuten pero sin utilizar el comando LOOP es la siguiente

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV BX000F veces que se desplegara la cadena 0C1B0128 MOV DX0102 copia cadena al registro DX 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F DEC BX decrementa en 1 a BX 0C1B0130 JNZ 012D si BX es diferente a 0 salta a 012D 0C1B0132 INT 20 termina el programa

En este caso se utiliza el registro BX como contador para el programa y por medio de la instruccioacuten DEC se disminuye su valor en 1 La instruccioacuten JNZ verifica si el valor de BX es diferente a 0 esto con base en la bandera NZ en caso afirmativo salta hacia la direccioacuten 012D En caso contrario continuacutea la ejecucioacuten normal del programa y por lo tanto se termina Una uacuteltima variante del programa es utilizando de nuevo a CX como contador pero en lugar de utilizar LOOP utilizaremos decrementos a CX y comparacioacuten de CX a 0

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV DX0102 copia cadena al registro DX 0C1B0128 MOV CX000F veces que se desplegara la cadena 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F DEC CX decrementa en 1 a CX 0C1B0130 JCXZ 0134 si CX es igual a 0 salta a 0134 0C1B0132 JMP 012D salta a la direccioacuten 012D 0C1B0134 INT 20 termina el programa

En este ejemplo se usoacute la instruccioacuten JCXZ para controlar la condicioacuten de salto el significado de tal funcioacuten es salta si CX=0 El tipo de control a utilizar dependeraacute de las necesidades de programacioacuten en determinado momento

Manipulacioacuten de Posiciones de Memoria Con el DEBUG es posible almacenar y recuperar datos numeacutericos en memoria por medio de un programa a traveacutes de los registros del microprocesador Por ejemplo el siguiente programa almacena previamente dos valores numeacutericos en la posicioacuten 0300h y 0400h respectivamente despueacutes el programa los recupera realiza la operacioacuten de suma con esos valores y el resultado lo almacena en la posicioacuten 0500h -a 100 0B1C0100 mov ax0002 ax=2 0B1C0103 mov [0300]ax almacenamos 2 en la direccioacuten 0300h 0B1C0106 mov ax0004 ax=4 0B1C0109 mov [0400]ax almacenamos 4 en la direccioacuten 0400h 0B1C010C mov ax[0300] recuperamos el dato1 en AX 0B1C010F mov bx[0400] recuperamos el dato2 en BX 0B1C0113 add axbx hacemos la operacioacuten de suma en AX 0B1C0115 mov [0500]ax almacenamos el 6 en la direccioacuten 0500h 0B1C0118 int 21 0B1C011A - Un nuacutemero entre corchetes [numero_hex] indica una posicioacuten de memoria y su manejo se hace a traveacutes de registros ya que no es posible almacenar valores numeacutericos de manera directa Ejecutamos el programa -g 118 AX=0006 BX=0004 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=0B1C ES=0B1C SS=0B1C CS=0B1C IP=0118 NV UP EI PL NZ NA PE NC 0B1C0118 CD21 INT 21 - Para ver si el resultado se almaceno en la direccioacuten correcta hacemos

Como se puede observar en la direccioacuten 0B1C0500 se encuentra el 06 y en 0B1C0501 se encuentra el 00 que es el resultado de la operacioacuten 2+4 Perohellip Porque aparece el 06 y despueacutes el 00 pareceriacutea que el resultado fue de 0600 pero no es asiacute lo que sucedes que los datos se almacenan en memoria de la siguiente manera

Como se hizo la operacioacuten AX=AX+BX entonces el resultado es de 16 bits (dos bytes) AX=6 entonces AX=0000 0000 0000 0110 (16 bits) por lo tanto los 8 bits de menor peso de AX son 0000 0110 y deben almacenarse en la direccioacuten 0500 y en la direccioacuten 0501 se almacena 0000 0000

0 0 0 0 0 1 1 0 0500

0 0 0 0 0 0 0 0 0501

x x x x x x x x 0502

x x x x x x x x 0503

x x x x x x x x 0504

x x x x x x x x 0505

Interrupciones Definicioacuten de interrupcioacuten

Una interrupcioacuten es una instruccioacuten que detiene la ejecucioacuten de un programa para permitir el uso del microprocesador en un proceso prioritario Una vez concluido este uacuteltimo proceso se devuelve el control a la aplicacioacuten anterior

Por ejemplo cuando estamos trabajando con un procesador de palabras y en ese momento llega un aviso de uno de los puertos de comunicaciones se detiene temporalmente la aplicacioacuten que estaacutebamos utilizando para permitir el uso del microprocesador al manejo de la informacioacuten que estaacute llegando en ese momento Una vez terminada la transferencia de informacioacuten se reanudan las funciones normales del procesador de palabras Las interrupciones ocurren muy seguido sencillamente la interrupcioacuten que actualiza la hora del diacutea ocurre aproximadamente 18 veces por segundo Para lograr administrar todas estas interrupciones la computadora cuenta con un espacio de memoria llamado memoria baja donde se almacenan las direcciones de cierta localidad de memoria donde se encuentran un juego de instrucciones que el microprocesador ejecutaraacute para despueacutes regresar a la aplicacioacuten que estaba en proceso En los programas anteriores hicimos uso de la interrupcioacuten nuacutemero 20H para terminar la ejecucioacuten de nuestros programas y en otros ejemplos utilizamos otra interrupcioacuten para mostrar informacioacuten en pantalla (INT 21h) Utilizando DEBUG tecleamos

- a100 2C1B0100 JMP 011D 2C1B0102 [ENTER] - E 102 Hola como estas 0D 0A $ - A011D 2C1B011D MOV DX0102 2C1B0120 MOV AH09 2C1B0122 INT 21 2C1B0123 INT 20

Orden

creciente

de la

memoria

En este programa la interrupcioacuten 21h manda al monitor la cadena localizada en la direccioacuten a la que apunta el registro DX El valor que se le da a AH determina cual de las opciones de la interrupcioacuten 21h seraacute utilizada ya que esta interrupcioacuten cuenta con varias opciones El manejo directo de interrupciones es una de las partes maacutes fuertes del lenguaje ensamblador ya que con ellas es posible controlar eficientemente todos los dispositivos internos y externos de una computadora gracias al completo control que se tiene sobre operaciones de entrada y salida Maacutes del DEBUG Una caracteriacutestica poco conocida es que DEBUG puede aceptar entradas desde un archivo Script que puede ser un simple archivo de texto ASCII en el que cada comando esteacute separado del anterior por un INTRO Despueacutes del uacuteltimo que debe ser una Q para salir de DEBUG es conveniente dejar una liacutenea en blanco pulsando INTRO dos veces Las liacuteneas pueden contener comentarios Cualquier cosa a partir del caracter punto y coma () hasta el final de la liacutenea seraacute ignorado esto es un comentario D aquiacute se mostraraacute algo Suponiendo que tengamos un archivo Script de nombre Ordenestxt puede ser utilizado como entrada para DEBUG mediante un comando de redireccioacuten en la siguiente forma DEBUG lt ordenestxt Tambieacuten puede conseguirse que el programa redireccione la salida hacia un archivo que puede ser inspeccionado maacutes 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 podriacutea obtenerse un archivo Resulttxt con el siguiente comando DEBUG lt ordenestxt gt Resulttxt Errores Cuando DEBUG no sabe interpretar un comando muestra un mensaje de error y un indicador ^ debajo del sitio del comando donde estaacute el error Entradas y Salidas DEBUG asume que los datos numeacutericos proporcionados son hexadecimales y cuando se trate de direcciones de memoria deben introducirse en forma segmentada A su vez los resultados son mostrados tambieacuten 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

Cada fila muestra 16 posiciones de memoria a partir de la posicioacuten sentildealada por las columnas de la izquierda que las muestran como segmentodesplazamiento El bloque central muestra el contenido hexadecimal de cada byte mientras que el bloque derecho contiene la representacioacuten ASCII Por ejemplo la 3ra fila muestra el contenido de las posiciones 0B770120 a 0B77012F (ambas inclusive) Sus tres uacuteltimos bytes contienen respectivamente los caracteres r 9 y 2 que corresponden a las cantidades 72h 39h y 32h del bloque central Que como sabemos equivalen a los decimales 114 57 y 50 que son precisamente los valores ASCII de los caracteres ldquorrdquo ldquo9rdquo y ldquo2rdquo anteriormente mencionados

Nota Por razoacuten de que eacuteste tipo de salida pueda ser listado a impresora el bloque derecho no contiene en realidad la representacioacuten ASCII de todos los caracteres (algunos ni siquiera tienen una representacioacuten imprimible) En realidad solo se muestran los caracteres imprimibles del primer bloque (US-ASCII) El resto estaacute 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 caraacutecter imprimible Esto no significa que dichas posiciones representen efectivamente tales valores para la aplicacioacuten que las utiliza Por ejemplo puede que en realidad las dos posiciones de memoria mencionadas (dos octetos o bytes) en vez de los caracteres ldquo5rdquo y ldquoardquo representen una palabra de 16 bits en formato Little Endian que a su vez representan una cantidad entera (un nuacutemero) Comandos Aunque su descripcioacuten completa llenariacutea todo un capiacutetulo a continuacioacuten comentamos algunas de las opciones maacutes interesantes relativas a inspeccioacuten del coacutedigo y de contenidos de memoria La opcioacuten D (Dump) permite obtener un volcado del contenido de la memoria (de DEBUG) La sintaxis acepta dos formas D [direccioacuten-inicial] [L posiciones-desde-direccioacuten-inicial ] D [direccioacuten-inicial][direccioacuten-final] Naturalmente para que exista algo en el buacutefer de memoria (al principio quizaacutes solo contiene basura) es preciso indicarle que lea algo Este algo puede ser un rango de direcciones de memoria RAM una direccioacuten absoluta de disco (sector) un archivo o el contenido de los registros del procesador Para empezar puede indicaacutersele que cargue un archivo xxxxyz que tenemos en el directorio actual o en el PATH cuyo contenido queremos ver Cgt DEBUG xxxxyz -D aquiacute se obtendriacutea una salida anaacuteloga a la comentada

Hemos visto un ejemplo al tratar de los servicios de interrupciones del PC aquiacute mostraremos otro Sabemos que el punto de inicio de la BIOS es la direccioacuten F000FFF0 y que desde eacutesta posicioacuten hasta el final de la memoria DOS hay 16 bytes Puede obtenerse un volcado de estas posiciones con el siguiente comando -D F000FFF0 La salida en un equipo puede ser F000FFF0 CD 19 E0 00 F0 30 36 2F-33 30 2F 39 37 00 FC 38 0630978 En este caso el comando solo muestra una liacutenea porque ha alcanzado el final de la memoria Puede verse que la fecha de la BIOS del sistema ocupa las uacuteltimas posiciones Si se ordena el volcado de una direccioacuten suficientemente alejada del final de la memoria sin indicar ninguacuten nuacutemero de posiciones por defecto se toma el valor 128 (8 filas de 16 posiciones) Si desea una cantidad distinta hay que antildeadir una L (Long) y el nuacutemero de posiciones hasta un maacuteximo de 64 KB (FFFF) Todos los nuacutemeros deben ser expresados en hexadecimal Por consiguiente los dos comandos que siguen son equivalentes (recuerde que 80 es el equivalente hexadecimal de 128) D FE000000 D FE000000 L 80 He aquiacute el resultado

Sabemos que esta zona corresponde al aacuterea de la BIOS del Sistema Otra opcioacuten muy interesante nos permite buscar determinados contenidos a traveacutes de la memoria utilizando el prefijo S (Search) Existen dos sintaxis alternativas S direccioacuten-de-inicio L longitud-a-explorar contenido-a-buscar S direccioacuten-de-inicio direccioacuten-final L contenido-a-buscar El contenido debe ser proporcionado en hexadecimal (tal como apareceriacutea en la columna central del ejemplo anterior) o entre comillas si es un texto ASCII Por ejemplo en un equipo IBM deseo ver algunas caracteriacutesticas de la BIOS Seacute que estos datos se alojan a partir de la posicioacuten F0000000 hasta el final de la memoria Es decir una longitud de 64 Kbytes (FFFF) a partir de la posicioacuten de inicio y que seguramente los datos buscados estaraacuten cerca de la identificacioacuten de la propia BIOS (la cadena IBM) Por lo que se utiliza la siguiente sintaxis [3] -s f0000000 L ffff IBM

y se obtiene la siguiente salida F000E00E F000E111 con las direcciones donde se ha encontrado la ocurrencia buscada A continuacioacuten puedo explorar las proximidades de cada posicioacuten Por ejemplo para la primera -D f000e000

Si lo que se busca estaacute en un archivo primero hay que cargarlo Lo que se puede hacer de dos formas en la propia invocacioacuten de DEBUG o mediante los comandos N y L Por ejemplo si queremos inspeccionar el contenido del archivo morecom podemos utilizar dos formas CWINDOWSgtDEBUG cwindowscommandmorecom CWINDOWSgtDEBUG - N cwindowscommandmorecom - L La sintaxis para el prefijo N es N [path-name]nombre-de-archivo En ambos casos el contenido del archivo seraacute cargado en memoria y podraacute ser utilizado Atencioacuten despueacutes de la orden L (Load) DEBUG le avisaraacute si no encuentra el archivo pero seguiraacute su funcionamiento En tal caso simplemente piensa que N sentildeala el nombre de un nuevo archivo que crearaacute con el contenido de la memoria -de DEBUG- cuando posteriormente seleccione la opcioacuten escribir W (Write)[4]

Nota Como ya habraacute deducido DEBUG permite leer un archivo realizar modificaciones en eacutel (con la opcioacuten E) y escribir el archivo modificado bajo otro nombre con NW

A continuacioacuten podemos comprobar el tamantildeo del archivo cargado Para ello usamos la opcioacuten 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 17A70100 E8CD0F CALL 10D0 -

Aquiacute nos interesa especialmente el contenido del registro CX cuyo valor 2917h (1519d) en este caso sentildeala el tamantildeo del archivo en bytes Tambieacuten podiacuteamos haber utilizado directamente el comando R CX que nos proporciona el valor de dicho registro -R CX CX 2917 -

Nota A continuacioacuten del valor correspondiente DEBUG muestra dos puntos () sentildealando que puede cambiar el valor del registro introduciendo un nuevo nuacutemero Pulse INTRO para dejar las cosas como estaacuten y volver al prompt (-) de DEBUG

Al llegar a este punto es importante sentildealar que a excepcioacuten de los archivos exe DEBUG carga los archivos a partir de la direccioacuten 100h (256d) de su memoria De forma que el primer octeto del archivo se carga en la direccioacuten 100 el segundo en 101 etc En nuestro caso el archivo se extenderaacute desde la posicioacuten 100h hasta 2A17h (100h + 2917h) A continuacioacuten para buscar la cadena Microsoft en el archivo utilizamos cualquiera de los siguientes comandos - S 100 L 2917 Microsoft - S 100 2a17 Microsoft El primer comando sentildeala el punto de inicio y el tamantildeo de la zona a buscar el segundo utiliza los puntos inicial y final de la exploracioacuten Con ambos se obtiene la misma respuesta 17A71083 17A710B2

Truco Debido a la forma especial en que se cargan los ejecutables exe si quiere inspeccionar la forma nativa de uno de estos archivos (como es su imagen en el disco) debe hacer una copia del archivo renombrarlo con cualquier otra terminacioacuten (o sin ella) y cargar esta copia En caso contrario DEBUG se prepararaacute para funcionar como un verdadero depurador de tiempo de ejecucioacuten (run-time) para lo que cargaraacute el archivo y lo acomodaraacute en memoria de forma que pueda ejecutarse [5]

Como ejercicio compruebe las distintas longitudes y aspecto (especialmente al principio) de un mismo archivo exe cargaacutendolo con DEBUG de las dos formas (busque en su sistema un exe lo maacutes pequentildeo posible) Ademaacutes de la capacidad de leer archivos antes mencionada quizaacutes una de las opciones maacutes interesantes (y peligrosas) de DEBUG es la posibilidad de leerescribir el contenido de disco a bajo nivel mediante los prefijos L (Load) y W (Write) Se utiliza la siguiente sintaxis L [Direccioacuten] [Unidad] [Primer_sector] [Nuacutemero] W [Direccioacuten] [Unidad] [Primer_sector] [Nuacutemero] El significado de los paraacutemetros es como sigue

Direccioacuten Posicioacuten de la memoria de DEBUG a partir de la cual se instalaraacuten los datos leiacutedos del disco o se tomaraacuten para el proceso de escritura (aquiacute se utiliza generalmente el valor 100h)

Unidad Valor numeacuterico que indica la loacutegica a utilizar 0 = A 1 = B 2 = C 3 = D etc [6]

Primer sector A partir del que se realizaraacute la lectura o se comenzaraacute a escribir

Nuacutemero Nuacutemero de sectores que se desea cargarescribir Como DEBUG no puede leerescribir maacutes de 64 Kbytes (2

16 = 65536) y los sectores de disco son de 512 bytes

el maacuteximo nuacutemero de sectores es 128 (80h) Asiacute pues el valor maacuteximo aquiacute es 80 Ejemplo Para obtener el contenido del sector de arranque (Master boot sector MBR) de un disquete en A utilizaremos el comando CWINDOWSgtDEBUG - L 100 0 0 1 - D 100 L 200 Como el resultado no cabe en una pantalla ingeniaremos un procedimiento para conservarlo en un archivo (maacutes adelante nos serviraacute para otro propoacutesito) Para ello creamos un archivo scripttxt con el siguiente contenido (dos INTRO despueacutes de la Q) L 100 0 0 1 D 100 L 200 Q A continuacioacuten invocamos DEBUG con el comando CWINDOWSgtDEBUG lt Dbuzonscripttxt gt Dbuzonresultadtxt Despueacutes de un breve parpadeo del disco y del disquete vuelve el prompt del DOS La operacioacuten ha concluido y en el directorio correspondiente de la unidad D tenemos el archivo resultadtxt con el volcado del sector de arranque del disquete ademaacutes de los ecos de los comandos introducidos (los hemos mantenido para orientacioacuten del lector) Otra forma de poder visualizar el contenido del Sector de Arranque del disco es utilizando el DEBUG Por ejemplo dentro del DEBUG tecleamos lo siguiente -L 100 0 0 1

-D 100 L 200

177C0100 EB 3E 90 2B 79 73 57 29-49 48 43 00 02 01 01 00 gt+ysW)IHC

177C0110 02 E0 00 40 0B F0 09 00-12 00 02 00 00 00 00 00

177C0120 00 00 00 00 00 00 29 5D-3B DD 10 4E 4F 20 4E 41 )]NO NA

177C0130 4D 45 20 20 20 20 46 41-54 31 32 20 20 20 F1 7D ME FAT12

177C0140 FA 33 C9 8E D1 BC FC 7B-16 07 BD 78 00 C5 76 00 3xv

177C0150 1E 56 16 55 BF 22 05 89-7E 00 89 4E 02 B1 0B FC VU~N

177C0160 F3 A4 06 1F BD 00 7C C6-45 FE 0F 8B 46 18 88 45 |EFE

177C0170 F9 FB 38 66 24 7C 04 CD-13 72 3C 8A 46 10 98 F7 8f$|rltF

177C0180 66 16 03 46 1C 13 56 1E-03 46 0E 13 D1 50 52 89 fFVFPR

177C0190 46 FC 89 56 FE B8 20 00-8B 76 11 F7 E6 8B 5E 0B FV v^

177C01A0 03 C3 48 F7 F3 01 46 FC-11 4E FE 5A 58 BB 00 07 HFNZX

177C01B0 8B FB B1 01 E8 94 00 72-47 38 2D 74 19 B1 0B 56 rG8-tV

177C01C0 8B 76 3E F3 A6 5E 74 4A-4E 74 0B 03 F9 83 C7 15 vgt^tJNt

177C01D0 3B FB 72 E5 EB D7 2B C9-B8 D8 7D 87 46 3E 3C D8 r+Fgtlt

177C01E0 75 99 BE 80 7D AC 98 03-F0 AC 84 C0 74 17 3C FF utlt

177C01F0 74 09 B4 0E BB 07 00 CD-10 EB EE BE 83 7D EB E5 t

177C0200 BE 81 7D EB E0 33 C0 CD-16 5E 1F 8F 04 8F 44 02 3^D

177C0210 CD 19 BE 82 7D 8B 7D 0F-83 FF 02 72 C8 8B C7 48 rH

177C0220 48 8A 4E 0D F7 E1 03 46-FC 13 56 FE BB 00 07 53 HNFVS

177C0230 B1 04 E8 16 00 5B 72 C8-81 3F 4D 5A 75 A7 81 BF [rMZu

177C0240 00 02 42 4A 75 9F EA 00-02 70 00 50 52 51 91 92 BJupPRQ

177C0250 33 D2 F7 76 18 91 F7 76-18 42 87 CA F7 76 1A 8A 3vvBv

177C0260 F2 8A 56 24 8A E8 D0 CC-D0 CC 0A CC B8 01 02 CD V$

177C0270 13 59 5A 58 72 09 40 75-01 42 03 5E 0B E2 CC C3 YZXruB^

177C0280 03 18 01 27 0D 0A 44 69-73 63 6F 20 69 6E 63 6F Disco inco

177C0290 72 72 65 63 74 6F 20 20-20 FF 0D 0A 45 72 72 6F rrecto Erro

177C02A0 72 20 45 2F 53 20 20 20-20 20 FF 0D 0A 43 61 6D r ES Cam

177C02B0 62 69 65 20 65 6C 20 64-69 73 63 6F 20 79 20 70 bie el disco y p

177C02C0 72 65 73 69 6F 6E 65 20-75 6E 61 20 74 65 63 6C resione una tecl

177C02D0 61 20 20 20 20 0D 0A 00-49 4F 20 20 20 20 20 20 a IO

177C02E0 53 59 53 4D 53 44 4F 53-20 20 20 53 59 53 80 01 SYSMSDOS SYS

177C02F0 00 57 49 4E 42 4F 4F 54-20 53 59 53 00 00 55 AA WINBOOT SYSU

-

-Q

FIN [1] En las primeras versiones de MS-DOS era un modesto programita DEBUGCOM de apenas 16 KB La versioacuten que acompantildea a Windows98 es ya un ejecutable en formato EXE de 21 KB [2] En realidad DEBUG es una utilidad de enorme potencia que requeririacutea todo un libro para ella sola Puede encontrarse una amplia descripcioacuten de esta herramienta en el libro de Paul Somerson PC Magazine DOS Powers Tools [3] Desgraciadamente no hay una convencioacuten estaacutendar sobre la colocacioacuten de los datos en la BIOS de forma que cada fabricante sigue sus propias reglas y es imposible por tanto utilizarla para cualquier tipo de identificacioacuten del sistema [4] En palabras del mencionado Paul Somerson Desgraciadamente debido a que DEBUG es un programa tan increiacuteblemente potente tambieacuten es increiacuteblemente peligroso Hay un dicho que afirma que El software no puede destruir el hardware Desgraciadamente esto no es cierto Ademaacutes de enviar mecanismos sensibles de la unidad de disco a tierra de nadie es posible hacer saltar monitores o transformadores Repito si sigue al pie de la letra las instrucciones y hace caso a todos los avisos todo iraacute bien [5] Recuerde que la imagen de un ejecutable exe cargado en memoria es distinta de su imagen en disco Solo en los ejecutables com la imagen en disco es una imagen exacta de su disposicioacuten en memoria [6] Es evidente que un pequentildeo error de nuacutemero en este paraacutemetro puede acarrear consecuencias nefastas Por ejemplo si cree que estaacute jugando con el disquete e inadvertidamente se dirige al disco duro (relea la nota [4])

Page 15: El Comando DEBUG

AC = hay acarreo auxiliar Parity (P) PO = paridad non PE = paridad par Carry (C) NC = no hay acarreo CY = Si lo hay

La estructura del ensamblador En el lenguaje ensamblador las liacuteneas de coacutedigo constan de dos partes la primera es el nombre de la instruccioacuten que se va a ejecutar y la segunda son los paraacutemetros del comando u operandos Por ejemplo

add ahbh Aquiacute add es el comando a ejecutar (en este caso una adicioacuten) y tanto ah como bh son los paraacutemetros El nombre de las instrucciones en este lenguaje estaacute formado por dos tres o cuatro letras a estas instrucciones tambieacuten se les llama nombres mnemoacutenicos o coacutedigos de operacioacuten ya que representan alguna funcioacuten que habraacute de realizar el microprocesador Existen algunos comandos que no requieren paraacutemetros para su operacioacuten asiacute como otros que requieren solo un paraacutemetro Algunas veces se utilizaraacuten las instrucciones como sigue

add al[170] Los corchetes en el segundo paraacutemetro nos indican que vamos a trabajar con el contenido de la posicioacuten de memoria nuacutemero 170 y no con el valor 170 a esto se le conoce como direccionamiento directo Primer programa en ensamblador con el DEBUG Vamos a crear un programa que sirva para ilustrar lo que hemos estado viendo lo que haremos seraacute una suma de dos valores que introduciremos directamente en el programa El primer paso es iniciar el DEBUG este paso consiste uacutenicamente en teclear DEBUG [Enter] en el prompt del sistema operativo Para ensamblar un programa en el DEBUG se utiliza el comando a (assemble) cuando se utiliza este comando se le puede dar como paraacutemetro la direccioacuten donde se desea que se inicie el ensamblado Si se omite el paraacutemetro el ensamblado se iniciaraacute en la localidad especificada por CSIP usualmente 0100H que es la localidad donde deben iniciar los programas con extensioacuten COM y seraacute la localidad que utilizaremos debido a que DEBUG solo puede crear este tipo especiacutefico de programas

Aunque en este momento no es necesario darle un paraacutemetro al comando a es recomendable hacerlo para evitar problemas una vez que se haga uso de los registros CSIP por lo tanto tecleamos

- a 100 [Enter] Al hacer esto apareceraacute en la pantalla algo como 0C1B0100 y el cursor se posiciona a la derecha de estos nuacutemeros noacutetese que los primeros cuatro diacutegitos (en sistema hexadecimal) pueden ser diferentes pero los uacuteltimos cuatro deben ser 0100 ya que es la direccioacuten que indicamos como inicio Ahora podemos introducir las instrucciones

0C1B0100 mov ax0002 coloca el valor 0002 en el registro ax 0C1B0103 mov bx0004 coloca el valor 0004 en el registro bx 0C1B0106 add axbx le adiciona al contenido de ax el contenido de bx 0C1B0108 int 20 provoca la terminacioacuten del programa 0C1B010A

No es necesario escribir los comentarios que van despueacutes del Una vez escrito el uacuteltimo comando int 20 se le da [Enter] sin escribir nada maacutes para volver al prompt del DEBUG La uacuteltima liacutenea escrita no es propiamente una instruccioacuten de ensamblador es una llamada a una interrupcioacuten del sistema operativo estas interrupciones seraacuten tratadas maacutes a fondo en un capiacutetulo posterior por el momento solo es necesario saber que nos ahorran un gran nuacutemero de liacuteneas y son muy uacutetiles para accesar a funciones del sistema operativo Para ejecutar el programa que escribimos se utiliza el comando g al utilizarlo veremos que aparece un mensaje que dice Program terminated normally Naturalmente con un mensaje como eacuteste no podemos estar seguros que el programa haya hecho la suma pero existe una forma sencilla de verificarlo utilizando el comando r del DEBUG podemos ver los contenidos de todos los registros del microprocesador simplemente teclee

- r [Enter] Apareceraacute en pantalla cada registro con su respectivo valor actual -R AX=0006 BX=0004 CX=0000 DX=0000 SP=FFFE BP=0000 SI=0000 DI=0000 DS=0C1B ES=0C1B SS=0C1B CS=0C1B IP=010A NV UP EI PL NZ NA PO NC 17A70100 E8CD0F CALL 10D0 - Existe la posibilidad de que los registros contengan valores diferentes pero AX y BX deben ser los mismos ya que son los que acabamos de modificar Otra forma de ver los valores mientras se ejecuta el programa es utilizando como paraacutemetro para g la direccioacuten donde queremos que termine la ejecucioacuten y muestre los valores de los registros en este caso seraacute g108 esta instruccioacuten ejecuta el programa se detiene en la direccioacuten 108 y muestra los contenidos de los registros Tambieacuten se puede llevar un seguimiento de lo que pasa en los registros utilizando el comando t (trace) la funcioacuten de este comando es ejecutar liacutenea por liacutenea lo que se ensambloacute mostrando cada vez los contenidos de los registros Para salir del DEBUG se utiliza el comando q (quit)

Guardar y cargar los programas No seriacutea praacutectico tener que escribir todo un programa cada vez que se necesite para evitar eso es posible guardar un programa en el disco con la enorme ventaja de que ya ensamblado no seraacute necesario correr de nuevo DEBUG para ejecutarlo ya que cuando el DEBUG guardo nuestro programa en el disco eacuteste se guardo en binario (archivo con la extensioacuten com) Los pasos a seguir para guardar un programa ya almacenado en la memoria son

Obtener la longitud del programa restando la direccioacuten final de la direccioacuten inicial naturalmente en sistema hexadecimal

Darle un nombre al programa y una extensioacuten

Poner la longitud del programa en el registro CX

Ordenar a DEBUG que escriba el programa en el disco Utilizando como ejemplo el programa del ejemplo anterior tendremos una idea maacutes clara de coacutemo llevar estos pasos Al terminar de ensamblar el programa se veriacutea asiacute

0C1B0100 mov ax0002 0C1B0103 mov bx0004 0C1B0106 add axbx 0C1B0108 int 20 0C1B010A

Para almacenarlo en el disco hacemos lo siguiente - h 10a 100 020a 000a - n pruebacom - r cx CX 0000 000a -w Writing 000A bytes

Para obtener la longitud de un programa se utiliza el comando h el cual nos muestra la suma y resta de dos nuacutemeros en hexadecimal Para obtener la longitud del programa le proporcionamos como paraacutemetros el valor de la direccioacuten final de nuestro programa (10A) y el valor de la direccioacuten inicial (0100) El primer resultado que nos muestra el comando es la suma de los paraacutemetros y el segundo es la resta El comando n nos permite poner un nombre al programa El comando r cx nos permite cambiar el contenido del registro CX al valor que obtuvimos del tamantildeo del archivo con h en este caso 000a ya que nos interesa el resultado de la resta de la direccioacuten inicial a la direccioacuten final

Por uacuteltimo el comando w escribe nuestro programa en el disco indicaacutendonos cuantos bytes escribioacute

NOTA Si se trabaja en una ventana de DOS de Windows Vista o 7 es probable que al momento de guardar su programa el DEBUG escriba mas coacutedigo que el sentildealado por el registro CX por consiguiente seraacute necesario limpiar el registro BX esto es ponerlo a ceros y despueacutes utilizar el comando w Por ejemplo _r bx BX 000E 0000 w

Para cargar un archivo ya guardado son necesarios dos pasos

Proporcionar el nombre del archivo que se cargaraacute a memoria

Cargarlo utilizando el comando l (load) Para obtener el resultado correcto de los siguientes pasos es necesario que previamente se haya creado el programa anterior Dentro del DEBUG escribimos lo siguiente

- n pruebacom - l - u 100 109 0C3D0100 B80200 MOV AX0002 0C3D0103 BB0400 MOV BX0004 0C3D0106 01D8 ADD AXBX 0C3D0108 CD20 INT 20

El uacuteltimo comando u se utiliza para verificar que el programa se cargoacute en memoria lo que hace es desensamblar el coacutedigo y mostrarlo ya desensamblado Los paraacutemetros le indican a DEBUG desde donde y hasta donde desensamblar DEBUG siempre carga los programas en memoria en la direccioacuten 100H a menos que se le indique alguna otra Un programa que realiza un conteo en pantalla Con el DEBUG es posible escribir un programa que realice un conteo en pantalla por razones de comprensioacuten nuestro programa solo realizara un conteo de 9 a 0 (conteo descendente) 0B3B0100 B90A00 MOV CX000A CX=10 en decimal 0B3B0103 88CA MOV DLCL 0B3B0105 80C22F ADD DL2F sumamos 02Fh a DL 0B3B0108 B402 MOV AH02 funcioacuten 02 de INT 21 para imprimir un caracter 0B3B010A CD21 INT 21

0B3B010C E2F5 LOOP 0103 CX=0 Si no salta a 0103 0B3B010E CD20 INT 20 termina el programa En la liacutenea 0103 se puede observar que el valor del registro CX en su parte baja (en CL) se almacena en el registro DL Si se omitiera la liacutenea 0105 entonces cuando se ejecutara la liacutenea 010A solo se imprimiriacutea en pantalla el coacutedigo ASCII del valor que contenga DL (el coacutedigo ASCII de 0Ah que es 10 en decimal es un caraacutecter especial no imprimible) Para conseguir el ldquoefectordquo de que el programa realiza el conteo en decimal se hace un corrimiento de 02F (47 en decimal) Por ejemplo cuando se ejecuta la liacutenea 0105 DL tendriacutea el valor de 39h=57d (02Fh+0Ah=39h=57d) y el coacutedigo ASCII de 57d es el caraacutecter ldquo9rdquo El sentencia LOOP decrementa CX en 1 si CX es diferente a 0 salta a la liacutenea 0103 El proceso se repite y el programa imprime en pantalla 9876543210 Seriacutea interesante que el programa anterior fuera modificado para que la numeracioacuten se imprimiera de la siguiente manera 9 8 7 6 5 4 3 2 1 0

NOTA Como se dijo anteriormente cuando el DEBUG almacena un programa en el disco este archivo se graba en binario esto es en ejecutable Por lo tanto no es necesario cargar el DEBUG para volver a ejecutar nuestro programa sino que se hace de manera directa desde DOS El problema surge cuando al ejecutar nuestro programa el resultado no se puede observar porque el DOS borra la pantalla despueacutes de terminar de ejecutar el programa Para evitar el borrado automaacutetico seraacute necesario agregarle a nuestro programa antes de la INT 20h una instruccioacuten para la lectura de un caraacutecter desde el teclado Para tal efecto utilizaremos la funcioacuten 08 de la INT 21h (un buen truco para que el programa haga una pausa) asiacute el programa esperara hasta que el usuario presiona una tecla permitiendo observar el resultado Ejemplo mov ah08 Int 21 Int 20

Condiciones ciclos y bifurcaciones Estas estructuras o formas de control le dan a la maacutequina un cierto grado de decisioacuten basado en la informacioacuten que recibe La forma maacutes sencilla de comprender este tema es por medio de ejemplos Vamos a crear tres programas que hagan lo mismo desplegar un nuacutemero determinado de veces una cadena de caracteres en la pantalla

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV CX000F veces que se desplegara la cadena 0C1B0128 MOV DX0102 copia cadena al registro DX 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F LOOP 012D si CXgt0 salta a 012D 0C1B0131 INT 20 termina el programa

Por medio del comando e es posible introducir una cadena de caracteres en una determinada localidad de memoria dada como paraacutemetro la cadena se introduce entre comillas le sigue un espacio luego el valor hexadecimal del retorno de carro un espacio el valor de liacutenea nueva y por uacuteltimo el siacutembolo $ que el ensamblador interpreta como final de la cadena La interrupcioacuten 21 utiliza el valor almacenado en el registro AH para ejecutar una determinada funcioacuten en este caso mostrar la cadena en pantalla la cadena que muestra es la que estaacute almacenada en el registro DX La instruccioacuten LOOP decrementa automaacuteticamente el registro CX en uno y si no ha llegado el valor de este registro a cero salta a la posicioacuten de memoria indicada como paraacutemetro lo cual crea un ciclo que se repite el nuacutemero de veces especificado por el valor de CX La interrupcioacuten 20 termina la ejecucioacuten del programa Otra forma de realizar la misma funcioacuten pero sin utilizar el comando LOOP es la siguiente

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV BX000F veces que se desplegara la cadena 0C1B0128 MOV DX0102 copia cadena al registro DX 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F DEC BX decrementa en 1 a BX 0C1B0130 JNZ 012D si BX es diferente a 0 salta a 012D 0C1B0132 INT 20 termina el programa

En este caso se utiliza el registro BX como contador para el programa y por medio de la instruccioacuten DEC se disminuye su valor en 1 La instruccioacuten JNZ verifica si el valor de BX es diferente a 0 esto con base en la bandera NZ en caso afirmativo salta hacia la direccioacuten 012D En caso contrario continuacutea la ejecucioacuten normal del programa y por lo tanto se termina Una uacuteltima variante del programa es utilizando de nuevo a CX como contador pero en lugar de utilizar LOOP utilizaremos decrementos a CX y comparacioacuten de CX a 0

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV DX0102 copia cadena al registro DX 0C1B0128 MOV CX000F veces que se desplegara la cadena 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F DEC CX decrementa en 1 a CX 0C1B0130 JCXZ 0134 si CX es igual a 0 salta a 0134 0C1B0132 JMP 012D salta a la direccioacuten 012D 0C1B0134 INT 20 termina el programa

En este ejemplo se usoacute la instruccioacuten JCXZ para controlar la condicioacuten de salto el significado de tal funcioacuten es salta si CX=0 El tipo de control a utilizar dependeraacute de las necesidades de programacioacuten en determinado momento

Manipulacioacuten de Posiciones de Memoria Con el DEBUG es posible almacenar y recuperar datos numeacutericos en memoria por medio de un programa a traveacutes de los registros del microprocesador Por ejemplo el siguiente programa almacena previamente dos valores numeacutericos en la posicioacuten 0300h y 0400h respectivamente despueacutes el programa los recupera realiza la operacioacuten de suma con esos valores y el resultado lo almacena en la posicioacuten 0500h -a 100 0B1C0100 mov ax0002 ax=2 0B1C0103 mov [0300]ax almacenamos 2 en la direccioacuten 0300h 0B1C0106 mov ax0004 ax=4 0B1C0109 mov [0400]ax almacenamos 4 en la direccioacuten 0400h 0B1C010C mov ax[0300] recuperamos el dato1 en AX 0B1C010F mov bx[0400] recuperamos el dato2 en BX 0B1C0113 add axbx hacemos la operacioacuten de suma en AX 0B1C0115 mov [0500]ax almacenamos el 6 en la direccioacuten 0500h 0B1C0118 int 21 0B1C011A - Un nuacutemero entre corchetes [numero_hex] indica una posicioacuten de memoria y su manejo se hace a traveacutes de registros ya que no es posible almacenar valores numeacutericos de manera directa Ejecutamos el programa -g 118 AX=0006 BX=0004 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=0B1C ES=0B1C SS=0B1C CS=0B1C IP=0118 NV UP EI PL NZ NA PE NC 0B1C0118 CD21 INT 21 - Para ver si el resultado se almaceno en la direccioacuten correcta hacemos

Como se puede observar en la direccioacuten 0B1C0500 se encuentra el 06 y en 0B1C0501 se encuentra el 00 que es el resultado de la operacioacuten 2+4 Perohellip Porque aparece el 06 y despueacutes el 00 pareceriacutea que el resultado fue de 0600 pero no es asiacute lo que sucedes que los datos se almacenan en memoria de la siguiente manera

Como se hizo la operacioacuten AX=AX+BX entonces el resultado es de 16 bits (dos bytes) AX=6 entonces AX=0000 0000 0000 0110 (16 bits) por lo tanto los 8 bits de menor peso de AX son 0000 0110 y deben almacenarse en la direccioacuten 0500 y en la direccioacuten 0501 se almacena 0000 0000

0 0 0 0 0 1 1 0 0500

0 0 0 0 0 0 0 0 0501

x x x x x x x x 0502

x x x x x x x x 0503

x x x x x x x x 0504

x x x x x x x x 0505

Interrupciones Definicioacuten de interrupcioacuten

Una interrupcioacuten es una instruccioacuten que detiene la ejecucioacuten de un programa para permitir el uso del microprocesador en un proceso prioritario Una vez concluido este uacuteltimo proceso se devuelve el control a la aplicacioacuten anterior

Por ejemplo cuando estamos trabajando con un procesador de palabras y en ese momento llega un aviso de uno de los puertos de comunicaciones se detiene temporalmente la aplicacioacuten que estaacutebamos utilizando para permitir el uso del microprocesador al manejo de la informacioacuten que estaacute llegando en ese momento Una vez terminada la transferencia de informacioacuten se reanudan las funciones normales del procesador de palabras Las interrupciones ocurren muy seguido sencillamente la interrupcioacuten que actualiza la hora del diacutea ocurre aproximadamente 18 veces por segundo Para lograr administrar todas estas interrupciones la computadora cuenta con un espacio de memoria llamado memoria baja donde se almacenan las direcciones de cierta localidad de memoria donde se encuentran un juego de instrucciones que el microprocesador ejecutaraacute para despueacutes regresar a la aplicacioacuten que estaba en proceso En los programas anteriores hicimos uso de la interrupcioacuten nuacutemero 20H para terminar la ejecucioacuten de nuestros programas y en otros ejemplos utilizamos otra interrupcioacuten para mostrar informacioacuten en pantalla (INT 21h) Utilizando DEBUG tecleamos

- a100 2C1B0100 JMP 011D 2C1B0102 [ENTER] - E 102 Hola como estas 0D 0A $ - A011D 2C1B011D MOV DX0102 2C1B0120 MOV AH09 2C1B0122 INT 21 2C1B0123 INT 20

Orden

creciente

de la

memoria

En este programa la interrupcioacuten 21h manda al monitor la cadena localizada en la direccioacuten a la que apunta el registro DX El valor que se le da a AH determina cual de las opciones de la interrupcioacuten 21h seraacute utilizada ya que esta interrupcioacuten cuenta con varias opciones El manejo directo de interrupciones es una de las partes maacutes fuertes del lenguaje ensamblador ya que con ellas es posible controlar eficientemente todos los dispositivos internos y externos de una computadora gracias al completo control que se tiene sobre operaciones de entrada y salida Maacutes del DEBUG Una caracteriacutestica poco conocida es que DEBUG puede aceptar entradas desde un archivo Script que puede ser un simple archivo de texto ASCII en el que cada comando esteacute separado del anterior por un INTRO Despueacutes del uacuteltimo que debe ser una Q para salir de DEBUG es conveniente dejar una liacutenea en blanco pulsando INTRO dos veces Las liacuteneas pueden contener comentarios Cualquier cosa a partir del caracter punto y coma () hasta el final de la liacutenea seraacute ignorado esto es un comentario D aquiacute se mostraraacute algo Suponiendo que tengamos un archivo Script de nombre Ordenestxt puede ser utilizado como entrada para DEBUG mediante un comando de redireccioacuten en la siguiente forma DEBUG lt ordenestxt Tambieacuten puede conseguirse que el programa redireccione la salida hacia un archivo que puede ser inspeccionado maacutes 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 podriacutea obtenerse un archivo Resulttxt con el siguiente comando DEBUG lt ordenestxt gt Resulttxt Errores Cuando DEBUG no sabe interpretar un comando muestra un mensaje de error y un indicador ^ debajo del sitio del comando donde estaacute el error Entradas y Salidas DEBUG asume que los datos numeacutericos proporcionados son hexadecimales y cuando se trate de direcciones de memoria deben introducirse en forma segmentada A su vez los resultados son mostrados tambieacuten 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

Cada fila muestra 16 posiciones de memoria a partir de la posicioacuten sentildealada por las columnas de la izquierda que las muestran como segmentodesplazamiento El bloque central muestra el contenido hexadecimal de cada byte mientras que el bloque derecho contiene la representacioacuten ASCII Por ejemplo la 3ra fila muestra el contenido de las posiciones 0B770120 a 0B77012F (ambas inclusive) Sus tres uacuteltimos bytes contienen respectivamente los caracteres r 9 y 2 que corresponden a las cantidades 72h 39h y 32h del bloque central Que como sabemos equivalen a los decimales 114 57 y 50 que son precisamente los valores ASCII de los caracteres ldquorrdquo ldquo9rdquo y ldquo2rdquo anteriormente mencionados

Nota Por razoacuten de que eacuteste tipo de salida pueda ser listado a impresora el bloque derecho no contiene en realidad la representacioacuten ASCII de todos los caracteres (algunos ni siquiera tienen una representacioacuten imprimible) En realidad solo se muestran los caracteres imprimibles del primer bloque (US-ASCII) El resto estaacute 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 caraacutecter imprimible Esto no significa que dichas posiciones representen efectivamente tales valores para la aplicacioacuten que las utiliza Por ejemplo puede que en realidad las dos posiciones de memoria mencionadas (dos octetos o bytes) en vez de los caracteres ldquo5rdquo y ldquoardquo representen una palabra de 16 bits en formato Little Endian que a su vez representan una cantidad entera (un nuacutemero) Comandos Aunque su descripcioacuten completa llenariacutea todo un capiacutetulo a continuacioacuten comentamos algunas de las opciones maacutes interesantes relativas a inspeccioacuten del coacutedigo y de contenidos de memoria La opcioacuten D (Dump) permite obtener un volcado del contenido de la memoria (de DEBUG) La sintaxis acepta dos formas D [direccioacuten-inicial] [L posiciones-desde-direccioacuten-inicial ] D [direccioacuten-inicial][direccioacuten-final] Naturalmente para que exista algo en el buacutefer de memoria (al principio quizaacutes solo contiene basura) es preciso indicarle que lea algo Este algo puede ser un rango de direcciones de memoria RAM una direccioacuten absoluta de disco (sector) un archivo o el contenido de los registros del procesador Para empezar puede indicaacutersele que cargue un archivo xxxxyz que tenemos en el directorio actual o en el PATH cuyo contenido queremos ver Cgt DEBUG xxxxyz -D aquiacute se obtendriacutea una salida anaacuteloga a la comentada

Hemos visto un ejemplo al tratar de los servicios de interrupciones del PC aquiacute mostraremos otro Sabemos que el punto de inicio de la BIOS es la direccioacuten F000FFF0 y que desde eacutesta posicioacuten hasta el final de la memoria DOS hay 16 bytes Puede obtenerse un volcado de estas posiciones con el siguiente comando -D F000FFF0 La salida en un equipo puede ser F000FFF0 CD 19 E0 00 F0 30 36 2F-33 30 2F 39 37 00 FC 38 0630978 En este caso el comando solo muestra una liacutenea porque ha alcanzado el final de la memoria Puede verse que la fecha de la BIOS del sistema ocupa las uacuteltimas posiciones Si se ordena el volcado de una direccioacuten suficientemente alejada del final de la memoria sin indicar ninguacuten nuacutemero de posiciones por defecto se toma el valor 128 (8 filas de 16 posiciones) Si desea una cantidad distinta hay que antildeadir una L (Long) y el nuacutemero de posiciones hasta un maacuteximo de 64 KB (FFFF) Todos los nuacutemeros deben ser expresados en hexadecimal Por consiguiente los dos comandos que siguen son equivalentes (recuerde que 80 es el equivalente hexadecimal de 128) D FE000000 D FE000000 L 80 He aquiacute el resultado

Sabemos que esta zona corresponde al aacuterea de la BIOS del Sistema Otra opcioacuten muy interesante nos permite buscar determinados contenidos a traveacutes de la memoria utilizando el prefijo S (Search) Existen dos sintaxis alternativas S direccioacuten-de-inicio L longitud-a-explorar contenido-a-buscar S direccioacuten-de-inicio direccioacuten-final L contenido-a-buscar El contenido debe ser proporcionado en hexadecimal (tal como apareceriacutea en la columna central del ejemplo anterior) o entre comillas si es un texto ASCII Por ejemplo en un equipo IBM deseo ver algunas caracteriacutesticas de la BIOS Seacute que estos datos se alojan a partir de la posicioacuten F0000000 hasta el final de la memoria Es decir una longitud de 64 Kbytes (FFFF) a partir de la posicioacuten de inicio y que seguramente los datos buscados estaraacuten cerca de la identificacioacuten de la propia BIOS (la cadena IBM) Por lo que se utiliza la siguiente sintaxis [3] -s f0000000 L ffff IBM

y se obtiene la siguiente salida F000E00E F000E111 con las direcciones donde se ha encontrado la ocurrencia buscada A continuacioacuten puedo explorar las proximidades de cada posicioacuten Por ejemplo para la primera -D f000e000

Si lo que se busca estaacute en un archivo primero hay que cargarlo Lo que se puede hacer de dos formas en la propia invocacioacuten de DEBUG o mediante los comandos N y L Por ejemplo si queremos inspeccionar el contenido del archivo morecom podemos utilizar dos formas CWINDOWSgtDEBUG cwindowscommandmorecom CWINDOWSgtDEBUG - N cwindowscommandmorecom - L La sintaxis para el prefijo N es N [path-name]nombre-de-archivo En ambos casos el contenido del archivo seraacute cargado en memoria y podraacute ser utilizado Atencioacuten despueacutes de la orden L (Load) DEBUG le avisaraacute si no encuentra el archivo pero seguiraacute su funcionamiento En tal caso simplemente piensa que N sentildeala el nombre de un nuevo archivo que crearaacute con el contenido de la memoria -de DEBUG- cuando posteriormente seleccione la opcioacuten escribir W (Write)[4]

Nota Como ya habraacute deducido DEBUG permite leer un archivo realizar modificaciones en eacutel (con la opcioacuten E) y escribir el archivo modificado bajo otro nombre con NW

A continuacioacuten podemos comprobar el tamantildeo del archivo cargado Para ello usamos la opcioacuten 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 17A70100 E8CD0F CALL 10D0 -

Aquiacute nos interesa especialmente el contenido del registro CX cuyo valor 2917h (1519d) en este caso sentildeala el tamantildeo del archivo en bytes Tambieacuten podiacuteamos haber utilizado directamente el comando R CX que nos proporciona el valor de dicho registro -R CX CX 2917 -

Nota A continuacioacuten del valor correspondiente DEBUG muestra dos puntos () sentildealando que puede cambiar el valor del registro introduciendo un nuevo nuacutemero Pulse INTRO para dejar las cosas como estaacuten y volver al prompt (-) de DEBUG

Al llegar a este punto es importante sentildealar que a excepcioacuten de los archivos exe DEBUG carga los archivos a partir de la direccioacuten 100h (256d) de su memoria De forma que el primer octeto del archivo se carga en la direccioacuten 100 el segundo en 101 etc En nuestro caso el archivo se extenderaacute desde la posicioacuten 100h hasta 2A17h (100h + 2917h) A continuacioacuten para buscar la cadena Microsoft en el archivo utilizamos cualquiera de los siguientes comandos - S 100 L 2917 Microsoft - S 100 2a17 Microsoft El primer comando sentildeala el punto de inicio y el tamantildeo de la zona a buscar el segundo utiliza los puntos inicial y final de la exploracioacuten Con ambos se obtiene la misma respuesta 17A71083 17A710B2

Truco Debido a la forma especial en que se cargan los ejecutables exe si quiere inspeccionar la forma nativa de uno de estos archivos (como es su imagen en el disco) debe hacer una copia del archivo renombrarlo con cualquier otra terminacioacuten (o sin ella) y cargar esta copia En caso contrario DEBUG se prepararaacute para funcionar como un verdadero depurador de tiempo de ejecucioacuten (run-time) para lo que cargaraacute el archivo y lo acomodaraacute en memoria de forma que pueda ejecutarse [5]

Como ejercicio compruebe las distintas longitudes y aspecto (especialmente al principio) de un mismo archivo exe cargaacutendolo con DEBUG de las dos formas (busque en su sistema un exe lo maacutes pequentildeo posible) Ademaacutes de la capacidad de leer archivos antes mencionada quizaacutes una de las opciones maacutes interesantes (y peligrosas) de DEBUG es la posibilidad de leerescribir el contenido de disco a bajo nivel mediante los prefijos L (Load) y W (Write) Se utiliza la siguiente sintaxis L [Direccioacuten] [Unidad] [Primer_sector] [Nuacutemero] W [Direccioacuten] [Unidad] [Primer_sector] [Nuacutemero] El significado de los paraacutemetros es como sigue

Direccioacuten Posicioacuten de la memoria de DEBUG a partir de la cual se instalaraacuten los datos leiacutedos del disco o se tomaraacuten para el proceso de escritura (aquiacute se utiliza generalmente el valor 100h)

Unidad Valor numeacuterico que indica la loacutegica a utilizar 0 = A 1 = B 2 = C 3 = D etc [6]

Primer sector A partir del que se realizaraacute la lectura o se comenzaraacute a escribir

Nuacutemero Nuacutemero de sectores que se desea cargarescribir Como DEBUG no puede leerescribir maacutes de 64 Kbytes (2

16 = 65536) y los sectores de disco son de 512 bytes

el maacuteximo nuacutemero de sectores es 128 (80h) Asiacute pues el valor maacuteximo aquiacute es 80 Ejemplo Para obtener el contenido del sector de arranque (Master boot sector MBR) de un disquete en A utilizaremos el comando CWINDOWSgtDEBUG - L 100 0 0 1 - D 100 L 200 Como el resultado no cabe en una pantalla ingeniaremos un procedimiento para conservarlo en un archivo (maacutes adelante nos serviraacute para otro propoacutesito) Para ello creamos un archivo scripttxt con el siguiente contenido (dos INTRO despueacutes de la Q) L 100 0 0 1 D 100 L 200 Q A continuacioacuten invocamos DEBUG con el comando CWINDOWSgtDEBUG lt Dbuzonscripttxt gt Dbuzonresultadtxt Despueacutes de un breve parpadeo del disco y del disquete vuelve el prompt del DOS La operacioacuten ha concluido y en el directorio correspondiente de la unidad D tenemos el archivo resultadtxt con el volcado del sector de arranque del disquete ademaacutes de los ecos de los comandos introducidos (los hemos mantenido para orientacioacuten del lector) Otra forma de poder visualizar el contenido del Sector de Arranque del disco es utilizando el DEBUG Por ejemplo dentro del DEBUG tecleamos lo siguiente -L 100 0 0 1

-D 100 L 200

177C0100 EB 3E 90 2B 79 73 57 29-49 48 43 00 02 01 01 00 gt+ysW)IHC

177C0110 02 E0 00 40 0B F0 09 00-12 00 02 00 00 00 00 00

177C0120 00 00 00 00 00 00 29 5D-3B DD 10 4E 4F 20 4E 41 )]NO NA

177C0130 4D 45 20 20 20 20 46 41-54 31 32 20 20 20 F1 7D ME FAT12

177C0140 FA 33 C9 8E D1 BC FC 7B-16 07 BD 78 00 C5 76 00 3xv

177C0150 1E 56 16 55 BF 22 05 89-7E 00 89 4E 02 B1 0B FC VU~N

177C0160 F3 A4 06 1F BD 00 7C C6-45 FE 0F 8B 46 18 88 45 |EFE

177C0170 F9 FB 38 66 24 7C 04 CD-13 72 3C 8A 46 10 98 F7 8f$|rltF

177C0180 66 16 03 46 1C 13 56 1E-03 46 0E 13 D1 50 52 89 fFVFPR

177C0190 46 FC 89 56 FE B8 20 00-8B 76 11 F7 E6 8B 5E 0B FV v^

177C01A0 03 C3 48 F7 F3 01 46 FC-11 4E FE 5A 58 BB 00 07 HFNZX

177C01B0 8B FB B1 01 E8 94 00 72-47 38 2D 74 19 B1 0B 56 rG8-tV

177C01C0 8B 76 3E F3 A6 5E 74 4A-4E 74 0B 03 F9 83 C7 15 vgt^tJNt

177C01D0 3B FB 72 E5 EB D7 2B C9-B8 D8 7D 87 46 3E 3C D8 r+Fgtlt

177C01E0 75 99 BE 80 7D AC 98 03-F0 AC 84 C0 74 17 3C FF utlt

177C01F0 74 09 B4 0E BB 07 00 CD-10 EB EE BE 83 7D EB E5 t

177C0200 BE 81 7D EB E0 33 C0 CD-16 5E 1F 8F 04 8F 44 02 3^D

177C0210 CD 19 BE 82 7D 8B 7D 0F-83 FF 02 72 C8 8B C7 48 rH

177C0220 48 8A 4E 0D F7 E1 03 46-FC 13 56 FE BB 00 07 53 HNFVS

177C0230 B1 04 E8 16 00 5B 72 C8-81 3F 4D 5A 75 A7 81 BF [rMZu

177C0240 00 02 42 4A 75 9F EA 00-02 70 00 50 52 51 91 92 BJupPRQ

177C0250 33 D2 F7 76 18 91 F7 76-18 42 87 CA F7 76 1A 8A 3vvBv

177C0260 F2 8A 56 24 8A E8 D0 CC-D0 CC 0A CC B8 01 02 CD V$

177C0270 13 59 5A 58 72 09 40 75-01 42 03 5E 0B E2 CC C3 YZXruB^

177C0280 03 18 01 27 0D 0A 44 69-73 63 6F 20 69 6E 63 6F Disco inco

177C0290 72 72 65 63 74 6F 20 20-20 FF 0D 0A 45 72 72 6F rrecto Erro

177C02A0 72 20 45 2F 53 20 20 20-20 20 FF 0D 0A 43 61 6D r ES Cam

177C02B0 62 69 65 20 65 6C 20 64-69 73 63 6F 20 79 20 70 bie el disco y p

177C02C0 72 65 73 69 6F 6E 65 20-75 6E 61 20 74 65 63 6C resione una tecl

177C02D0 61 20 20 20 20 0D 0A 00-49 4F 20 20 20 20 20 20 a IO

177C02E0 53 59 53 4D 53 44 4F 53-20 20 20 53 59 53 80 01 SYSMSDOS SYS

177C02F0 00 57 49 4E 42 4F 4F 54-20 53 59 53 00 00 55 AA WINBOOT SYSU

-

-Q

FIN [1] En las primeras versiones de MS-DOS era un modesto programita DEBUGCOM de apenas 16 KB La versioacuten que acompantildea a Windows98 es ya un ejecutable en formato EXE de 21 KB [2] En realidad DEBUG es una utilidad de enorme potencia que requeririacutea todo un libro para ella sola Puede encontrarse una amplia descripcioacuten de esta herramienta en el libro de Paul Somerson PC Magazine DOS Powers Tools [3] Desgraciadamente no hay una convencioacuten estaacutendar sobre la colocacioacuten de los datos en la BIOS de forma que cada fabricante sigue sus propias reglas y es imposible por tanto utilizarla para cualquier tipo de identificacioacuten del sistema [4] En palabras del mencionado Paul Somerson Desgraciadamente debido a que DEBUG es un programa tan increiacuteblemente potente tambieacuten es increiacuteblemente peligroso Hay un dicho que afirma que El software no puede destruir el hardware Desgraciadamente esto no es cierto Ademaacutes de enviar mecanismos sensibles de la unidad de disco a tierra de nadie es posible hacer saltar monitores o transformadores Repito si sigue al pie de la letra las instrucciones y hace caso a todos los avisos todo iraacute bien [5] Recuerde que la imagen de un ejecutable exe cargado en memoria es distinta de su imagen en disco Solo en los ejecutables com la imagen en disco es una imagen exacta de su disposicioacuten en memoria [6] Es evidente que un pequentildeo error de nuacutemero en este paraacutemetro puede acarrear consecuencias nefastas Por ejemplo si cree que estaacute jugando con el disquete e inadvertidamente se dirige al disco duro (relea la nota [4])

Page 16: El Comando DEBUG

Aunque en este momento no es necesario darle un paraacutemetro al comando a es recomendable hacerlo para evitar problemas una vez que se haga uso de los registros CSIP por lo tanto tecleamos

- a 100 [Enter] Al hacer esto apareceraacute en la pantalla algo como 0C1B0100 y el cursor se posiciona a la derecha de estos nuacutemeros noacutetese que los primeros cuatro diacutegitos (en sistema hexadecimal) pueden ser diferentes pero los uacuteltimos cuatro deben ser 0100 ya que es la direccioacuten que indicamos como inicio Ahora podemos introducir las instrucciones

0C1B0100 mov ax0002 coloca el valor 0002 en el registro ax 0C1B0103 mov bx0004 coloca el valor 0004 en el registro bx 0C1B0106 add axbx le adiciona al contenido de ax el contenido de bx 0C1B0108 int 20 provoca la terminacioacuten del programa 0C1B010A

No es necesario escribir los comentarios que van despueacutes del Una vez escrito el uacuteltimo comando int 20 se le da [Enter] sin escribir nada maacutes para volver al prompt del DEBUG La uacuteltima liacutenea escrita no es propiamente una instruccioacuten de ensamblador es una llamada a una interrupcioacuten del sistema operativo estas interrupciones seraacuten tratadas maacutes a fondo en un capiacutetulo posterior por el momento solo es necesario saber que nos ahorran un gran nuacutemero de liacuteneas y son muy uacutetiles para accesar a funciones del sistema operativo Para ejecutar el programa que escribimos se utiliza el comando g al utilizarlo veremos que aparece un mensaje que dice Program terminated normally Naturalmente con un mensaje como eacuteste no podemos estar seguros que el programa haya hecho la suma pero existe una forma sencilla de verificarlo utilizando el comando r del DEBUG podemos ver los contenidos de todos los registros del microprocesador simplemente teclee

- r [Enter] Apareceraacute en pantalla cada registro con su respectivo valor actual -R AX=0006 BX=0004 CX=0000 DX=0000 SP=FFFE BP=0000 SI=0000 DI=0000 DS=0C1B ES=0C1B SS=0C1B CS=0C1B IP=010A NV UP EI PL NZ NA PO NC 17A70100 E8CD0F CALL 10D0 - Existe la posibilidad de que los registros contengan valores diferentes pero AX y BX deben ser los mismos ya que son los que acabamos de modificar Otra forma de ver los valores mientras se ejecuta el programa es utilizando como paraacutemetro para g la direccioacuten donde queremos que termine la ejecucioacuten y muestre los valores de los registros en este caso seraacute g108 esta instruccioacuten ejecuta el programa se detiene en la direccioacuten 108 y muestra los contenidos de los registros Tambieacuten se puede llevar un seguimiento de lo que pasa en los registros utilizando el comando t (trace) la funcioacuten de este comando es ejecutar liacutenea por liacutenea lo que se ensambloacute mostrando cada vez los contenidos de los registros Para salir del DEBUG se utiliza el comando q (quit)

Guardar y cargar los programas No seriacutea praacutectico tener que escribir todo un programa cada vez que se necesite para evitar eso es posible guardar un programa en el disco con la enorme ventaja de que ya ensamblado no seraacute necesario correr de nuevo DEBUG para ejecutarlo ya que cuando el DEBUG guardo nuestro programa en el disco eacuteste se guardo en binario (archivo con la extensioacuten com) Los pasos a seguir para guardar un programa ya almacenado en la memoria son

Obtener la longitud del programa restando la direccioacuten final de la direccioacuten inicial naturalmente en sistema hexadecimal

Darle un nombre al programa y una extensioacuten

Poner la longitud del programa en el registro CX

Ordenar a DEBUG que escriba el programa en el disco Utilizando como ejemplo el programa del ejemplo anterior tendremos una idea maacutes clara de coacutemo llevar estos pasos Al terminar de ensamblar el programa se veriacutea asiacute

0C1B0100 mov ax0002 0C1B0103 mov bx0004 0C1B0106 add axbx 0C1B0108 int 20 0C1B010A

Para almacenarlo en el disco hacemos lo siguiente - h 10a 100 020a 000a - n pruebacom - r cx CX 0000 000a -w Writing 000A bytes

Para obtener la longitud de un programa se utiliza el comando h el cual nos muestra la suma y resta de dos nuacutemeros en hexadecimal Para obtener la longitud del programa le proporcionamos como paraacutemetros el valor de la direccioacuten final de nuestro programa (10A) y el valor de la direccioacuten inicial (0100) El primer resultado que nos muestra el comando es la suma de los paraacutemetros y el segundo es la resta El comando n nos permite poner un nombre al programa El comando r cx nos permite cambiar el contenido del registro CX al valor que obtuvimos del tamantildeo del archivo con h en este caso 000a ya que nos interesa el resultado de la resta de la direccioacuten inicial a la direccioacuten final

Por uacuteltimo el comando w escribe nuestro programa en el disco indicaacutendonos cuantos bytes escribioacute

NOTA Si se trabaja en una ventana de DOS de Windows Vista o 7 es probable que al momento de guardar su programa el DEBUG escriba mas coacutedigo que el sentildealado por el registro CX por consiguiente seraacute necesario limpiar el registro BX esto es ponerlo a ceros y despueacutes utilizar el comando w Por ejemplo _r bx BX 000E 0000 w

Para cargar un archivo ya guardado son necesarios dos pasos

Proporcionar el nombre del archivo que se cargaraacute a memoria

Cargarlo utilizando el comando l (load) Para obtener el resultado correcto de los siguientes pasos es necesario que previamente se haya creado el programa anterior Dentro del DEBUG escribimos lo siguiente

- n pruebacom - l - u 100 109 0C3D0100 B80200 MOV AX0002 0C3D0103 BB0400 MOV BX0004 0C3D0106 01D8 ADD AXBX 0C3D0108 CD20 INT 20

El uacuteltimo comando u se utiliza para verificar que el programa se cargoacute en memoria lo que hace es desensamblar el coacutedigo y mostrarlo ya desensamblado Los paraacutemetros le indican a DEBUG desde donde y hasta donde desensamblar DEBUG siempre carga los programas en memoria en la direccioacuten 100H a menos que se le indique alguna otra Un programa que realiza un conteo en pantalla Con el DEBUG es posible escribir un programa que realice un conteo en pantalla por razones de comprensioacuten nuestro programa solo realizara un conteo de 9 a 0 (conteo descendente) 0B3B0100 B90A00 MOV CX000A CX=10 en decimal 0B3B0103 88CA MOV DLCL 0B3B0105 80C22F ADD DL2F sumamos 02Fh a DL 0B3B0108 B402 MOV AH02 funcioacuten 02 de INT 21 para imprimir un caracter 0B3B010A CD21 INT 21

0B3B010C E2F5 LOOP 0103 CX=0 Si no salta a 0103 0B3B010E CD20 INT 20 termina el programa En la liacutenea 0103 se puede observar que el valor del registro CX en su parte baja (en CL) se almacena en el registro DL Si se omitiera la liacutenea 0105 entonces cuando se ejecutara la liacutenea 010A solo se imprimiriacutea en pantalla el coacutedigo ASCII del valor que contenga DL (el coacutedigo ASCII de 0Ah que es 10 en decimal es un caraacutecter especial no imprimible) Para conseguir el ldquoefectordquo de que el programa realiza el conteo en decimal se hace un corrimiento de 02F (47 en decimal) Por ejemplo cuando se ejecuta la liacutenea 0105 DL tendriacutea el valor de 39h=57d (02Fh+0Ah=39h=57d) y el coacutedigo ASCII de 57d es el caraacutecter ldquo9rdquo El sentencia LOOP decrementa CX en 1 si CX es diferente a 0 salta a la liacutenea 0103 El proceso se repite y el programa imprime en pantalla 9876543210 Seriacutea interesante que el programa anterior fuera modificado para que la numeracioacuten se imprimiera de la siguiente manera 9 8 7 6 5 4 3 2 1 0

NOTA Como se dijo anteriormente cuando el DEBUG almacena un programa en el disco este archivo se graba en binario esto es en ejecutable Por lo tanto no es necesario cargar el DEBUG para volver a ejecutar nuestro programa sino que se hace de manera directa desde DOS El problema surge cuando al ejecutar nuestro programa el resultado no se puede observar porque el DOS borra la pantalla despueacutes de terminar de ejecutar el programa Para evitar el borrado automaacutetico seraacute necesario agregarle a nuestro programa antes de la INT 20h una instruccioacuten para la lectura de un caraacutecter desde el teclado Para tal efecto utilizaremos la funcioacuten 08 de la INT 21h (un buen truco para que el programa haga una pausa) asiacute el programa esperara hasta que el usuario presiona una tecla permitiendo observar el resultado Ejemplo mov ah08 Int 21 Int 20

Condiciones ciclos y bifurcaciones Estas estructuras o formas de control le dan a la maacutequina un cierto grado de decisioacuten basado en la informacioacuten que recibe La forma maacutes sencilla de comprender este tema es por medio de ejemplos Vamos a crear tres programas que hagan lo mismo desplegar un nuacutemero determinado de veces una cadena de caracteres en la pantalla

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV CX000F veces que se desplegara la cadena 0C1B0128 MOV DX0102 copia cadena al registro DX 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F LOOP 012D si CXgt0 salta a 012D 0C1B0131 INT 20 termina el programa

Por medio del comando e es posible introducir una cadena de caracteres en una determinada localidad de memoria dada como paraacutemetro la cadena se introduce entre comillas le sigue un espacio luego el valor hexadecimal del retorno de carro un espacio el valor de liacutenea nueva y por uacuteltimo el siacutembolo $ que el ensamblador interpreta como final de la cadena La interrupcioacuten 21 utiliza el valor almacenado en el registro AH para ejecutar una determinada funcioacuten en este caso mostrar la cadena en pantalla la cadena que muestra es la que estaacute almacenada en el registro DX La instruccioacuten LOOP decrementa automaacuteticamente el registro CX en uno y si no ha llegado el valor de este registro a cero salta a la posicioacuten de memoria indicada como paraacutemetro lo cual crea un ciclo que se repite el nuacutemero de veces especificado por el valor de CX La interrupcioacuten 20 termina la ejecucioacuten del programa Otra forma de realizar la misma funcioacuten pero sin utilizar el comando LOOP es la siguiente

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV BX000F veces que se desplegara la cadena 0C1B0128 MOV DX0102 copia cadena al registro DX 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F DEC BX decrementa en 1 a BX 0C1B0130 JNZ 012D si BX es diferente a 0 salta a 012D 0C1B0132 INT 20 termina el programa

En este caso se utiliza el registro BX como contador para el programa y por medio de la instruccioacuten DEC se disminuye su valor en 1 La instruccioacuten JNZ verifica si el valor de BX es diferente a 0 esto con base en la bandera NZ en caso afirmativo salta hacia la direccioacuten 012D En caso contrario continuacutea la ejecucioacuten normal del programa y por lo tanto se termina Una uacuteltima variante del programa es utilizando de nuevo a CX como contador pero en lugar de utilizar LOOP utilizaremos decrementos a CX y comparacioacuten de CX a 0

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV DX0102 copia cadena al registro DX 0C1B0128 MOV CX000F veces que se desplegara la cadena 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F DEC CX decrementa en 1 a CX 0C1B0130 JCXZ 0134 si CX es igual a 0 salta a 0134 0C1B0132 JMP 012D salta a la direccioacuten 012D 0C1B0134 INT 20 termina el programa

En este ejemplo se usoacute la instruccioacuten JCXZ para controlar la condicioacuten de salto el significado de tal funcioacuten es salta si CX=0 El tipo de control a utilizar dependeraacute de las necesidades de programacioacuten en determinado momento

Manipulacioacuten de Posiciones de Memoria Con el DEBUG es posible almacenar y recuperar datos numeacutericos en memoria por medio de un programa a traveacutes de los registros del microprocesador Por ejemplo el siguiente programa almacena previamente dos valores numeacutericos en la posicioacuten 0300h y 0400h respectivamente despueacutes el programa los recupera realiza la operacioacuten de suma con esos valores y el resultado lo almacena en la posicioacuten 0500h -a 100 0B1C0100 mov ax0002 ax=2 0B1C0103 mov [0300]ax almacenamos 2 en la direccioacuten 0300h 0B1C0106 mov ax0004 ax=4 0B1C0109 mov [0400]ax almacenamos 4 en la direccioacuten 0400h 0B1C010C mov ax[0300] recuperamos el dato1 en AX 0B1C010F mov bx[0400] recuperamos el dato2 en BX 0B1C0113 add axbx hacemos la operacioacuten de suma en AX 0B1C0115 mov [0500]ax almacenamos el 6 en la direccioacuten 0500h 0B1C0118 int 21 0B1C011A - Un nuacutemero entre corchetes [numero_hex] indica una posicioacuten de memoria y su manejo se hace a traveacutes de registros ya que no es posible almacenar valores numeacutericos de manera directa Ejecutamos el programa -g 118 AX=0006 BX=0004 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=0B1C ES=0B1C SS=0B1C CS=0B1C IP=0118 NV UP EI PL NZ NA PE NC 0B1C0118 CD21 INT 21 - Para ver si el resultado se almaceno en la direccioacuten correcta hacemos

Como se puede observar en la direccioacuten 0B1C0500 se encuentra el 06 y en 0B1C0501 se encuentra el 00 que es el resultado de la operacioacuten 2+4 Perohellip Porque aparece el 06 y despueacutes el 00 pareceriacutea que el resultado fue de 0600 pero no es asiacute lo que sucedes que los datos se almacenan en memoria de la siguiente manera

Como se hizo la operacioacuten AX=AX+BX entonces el resultado es de 16 bits (dos bytes) AX=6 entonces AX=0000 0000 0000 0110 (16 bits) por lo tanto los 8 bits de menor peso de AX son 0000 0110 y deben almacenarse en la direccioacuten 0500 y en la direccioacuten 0501 se almacena 0000 0000

0 0 0 0 0 1 1 0 0500

0 0 0 0 0 0 0 0 0501

x x x x x x x x 0502

x x x x x x x x 0503

x x x x x x x x 0504

x x x x x x x x 0505

Interrupciones Definicioacuten de interrupcioacuten

Una interrupcioacuten es una instruccioacuten que detiene la ejecucioacuten de un programa para permitir el uso del microprocesador en un proceso prioritario Una vez concluido este uacuteltimo proceso se devuelve el control a la aplicacioacuten anterior

Por ejemplo cuando estamos trabajando con un procesador de palabras y en ese momento llega un aviso de uno de los puertos de comunicaciones se detiene temporalmente la aplicacioacuten que estaacutebamos utilizando para permitir el uso del microprocesador al manejo de la informacioacuten que estaacute llegando en ese momento Una vez terminada la transferencia de informacioacuten se reanudan las funciones normales del procesador de palabras Las interrupciones ocurren muy seguido sencillamente la interrupcioacuten que actualiza la hora del diacutea ocurre aproximadamente 18 veces por segundo Para lograr administrar todas estas interrupciones la computadora cuenta con un espacio de memoria llamado memoria baja donde se almacenan las direcciones de cierta localidad de memoria donde se encuentran un juego de instrucciones que el microprocesador ejecutaraacute para despueacutes regresar a la aplicacioacuten que estaba en proceso En los programas anteriores hicimos uso de la interrupcioacuten nuacutemero 20H para terminar la ejecucioacuten de nuestros programas y en otros ejemplos utilizamos otra interrupcioacuten para mostrar informacioacuten en pantalla (INT 21h) Utilizando DEBUG tecleamos

- a100 2C1B0100 JMP 011D 2C1B0102 [ENTER] - E 102 Hola como estas 0D 0A $ - A011D 2C1B011D MOV DX0102 2C1B0120 MOV AH09 2C1B0122 INT 21 2C1B0123 INT 20

Orden

creciente

de la

memoria

En este programa la interrupcioacuten 21h manda al monitor la cadena localizada en la direccioacuten a la que apunta el registro DX El valor que se le da a AH determina cual de las opciones de la interrupcioacuten 21h seraacute utilizada ya que esta interrupcioacuten cuenta con varias opciones El manejo directo de interrupciones es una de las partes maacutes fuertes del lenguaje ensamblador ya que con ellas es posible controlar eficientemente todos los dispositivos internos y externos de una computadora gracias al completo control que se tiene sobre operaciones de entrada y salida Maacutes del DEBUG Una caracteriacutestica poco conocida es que DEBUG puede aceptar entradas desde un archivo Script que puede ser un simple archivo de texto ASCII en el que cada comando esteacute separado del anterior por un INTRO Despueacutes del uacuteltimo que debe ser una Q para salir de DEBUG es conveniente dejar una liacutenea en blanco pulsando INTRO dos veces Las liacuteneas pueden contener comentarios Cualquier cosa a partir del caracter punto y coma () hasta el final de la liacutenea seraacute ignorado esto es un comentario D aquiacute se mostraraacute algo Suponiendo que tengamos un archivo Script de nombre Ordenestxt puede ser utilizado como entrada para DEBUG mediante un comando de redireccioacuten en la siguiente forma DEBUG lt ordenestxt Tambieacuten puede conseguirse que el programa redireccione la salida hacia un archivo que puede ser inspeccionado maacutes 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 podriacutea obtenerse un archivo Resulttxt con el siguiente comando DEBUG lt ordenestxt gt Resulttxt Errores Cuando DEBUG no sabe interpretar un comando muestra un mensaje de error y un indicador ^ debajo del sitio del comando donde estaacute el error Entradas y Salidas DEBUG asume que los datos numeacutericos proporcionados son hexadecimales y cuando se trate de direcciones de memoria deben introducirse en forma segmentada A su vez los resultados son mostrados tambieacuten 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

Cada fila muestra 16 posiciones de memoria a partir de la posicioacuten sentildealada por las columnas de la izquierda que las muestran como segmentodesplazamiento El bloque central muestra el contenido hexadecimal de cada byte mientras que el bloque derecho contiene la representacioacuten ASCII Por ejemplo la 3ra fila muestra el contenido de las posiciones 0B770120 a 0B77012F (ambas inclusive) Sus tres uacuteltimos bytes contienen respectivamente los caracteres r 9 y 2 que corresponden a las cantidades 72h 39h y 32h del bloque central Que como sabemos equivalen a los decimales 114 57 y 50 que son precisamente los valores ASCII de los caracteres ldquorrdquo ldquo9rdquo y ldquo2rdquo anteriormente mencionados

Nota Por razoacuten de que eacuteste tipo de salida pueda ser listado a impresora el bloque derecho no contiene en realidad la representacioacuten ASCII de todos los caracteres (algunos ni siquiera tienen una representacioacuten imprimible) En realidad solo se muestran los caracteres imprimibles del primer bloque (US-ASCII) El resto estaacute 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 caraacutecter imprimible Esto no significa que dichas posiciones representen efectivamente tales valores para la aplicacioacuten que las utiliza Por ejemplo puede que en realidad las dos posiciones de memoria mencionadas (dos octetos o bytes) en vez de los caracteres ldquo5rdquo y ldquoardquo representen una palabra de 16 bits en formato Little Endian que a su vez representan una cantidad entera (un nuacutemero) Comandos Aunque su descripcioacuten completa llenariacutea todo un capiacutetulo a continuacioacuten comentamos algunas de las opciones maacutes interesantes relativas a inspeccioacuten del coacutedigo y de contenidos de memoria La opcioacuten D (Dump) permite obtener un volcado del contenido de la memoria (de DEBUG) La sintaxis acepta dos formas D [direccioacuten-inicial] [L posiciones-desde-direccioacuten-inicial ] D [direccioacuten-inicial][direccioacuten-final] Naturalmente para que exista algo en el buacutefer de memoria (al principio quizaacutes solo contiene basura) es preciso indicarle que lea algo Este algo puede ser un rango de direcciones de memoria RAM una direccioacuten absoluta de disco (sector) un archivo o el contenido de los registros del procesador Para empezar puede indicaacutersele que cargue un archivo xxxxyz que tenemos en el directorio actual o en el PATH cuyo contenido queremos ver Cgt DEBUG xxxxyz -D aquiacute se obtendriacutea una salida anaacuteloga a la comentada

Hemos visto un ejemplo al tratar de los servicios de interrupciones del PC aquiacute mostraremos otro Sabemos que el punto de inicio de la BIOS es la direccioacuten F000FFF0 y que desde eacutesta posicioacuten hasta el final de la memoria DOS hay 16 bytes Puede obtenerse un volcado de estas posiciones con el siguiente comando -D F000FFF0 La salida en un equipo puede ser F000FFF0 CD 19 E0 00 F0 30 36 2F-33 30 2F 39 37 00 FC 38 0630978 En este caso el comando solo muestra una liacutenea porque ha alcanzado el final de la memoria Puede verse que la fecha de la BIOS del sistema ocupa las uacuteltimas posiciones Si se ordena el volcado de una direccioacuten suficientemente alejada del final de la memoria sin indicar ninguacuten nuacutemero de posiciones por defecto se toma el valor 128 (8 filas de 16 posiciones) Si desea una cantidad distinta hay que antildeadir una L (Long) y el nuacutemero de posiciones hasta un maacuteximo de 64 KB (FFFF) Todos los nuacutemeros deben ser expresados en hexadecimal Por consiguiente los dos comandos que siguen son equivalentes (recuerde que 80 es el equivalente hexadecimal de 128) D FE000000 D FE000000 L 80 He aquiacute el resultado

Sabemos que esta zona corresponde al aacuterea de la BIOS del Sistema Otra opcioacuten muy interesante nos permite buscar determinados contenidos a traveacutes de la memoria utilizando el prefijo S (Search) Existen dos sintaxis alternativas S direccioacuten-de-inicio L longitud-a-explorar contenido-a-buscar S direccioacuten-de-inicio direccioacuten-final L contenido-a-buscar El contenido debe ser proporcionado en hexadecimal (tal como apareceriacutea en la columna central del ejemplo anterior) o entre comillas si es un texto ASCII Por ejemplo en un equipo IBM deseo ver algunas caracteriacutesticas de la BIOS Seacute que estos datos se alojan a partir de la posicioacuten F0000000 hasta el final de la memoria Es decir una longitud de 64 Kbytes (FFFF) a partir de la posicioacuten de inicio y que seguramente los datos buscados estaraacuten cerca de la identificacioacuten de la propia BIOS (la cadena IBM) Por lo que se utiliza la siguiente sintaxis [3] -s f0000000 L ffff IBM

y se obtiene la siguiente salida F000E00E F000E111 con las direcciones donde se ha encontrado la ocurrencia buscada A continuacioacuten puedo explorar las proximidades de cada posicioacuten Por ejemplo para la primera -D f000e000

Si lo que se busca estaacute en un archivo primero hay que cargarlo Lo que se puede hacer de dos formas en la propia invocacioacuten de DEBUG o mediante los comandos N y L Por ejemplo si queremos inspeccionar el contenido del archivo morecom podemos utilizar dos formas CWINDOWSgtDEBUG cwindowscommandmorecom CWINDOWSgtDEBUG - N cwindowscommandmorecom - L La sintaxis para el prefijo N es N [path-name]nombre-de-archivo En ambos casos el contenido del archivo seraacute cargado en memoria y podraacute ser utilizado Atencioacuten despueacutes de la orden L (Load) DEBUG le avisaraacute si no encuentra el archivo pero seguiraacute su funcionamiento En tal caso simplemente piensa que N sentildeala el nombre de un nuevo archivo que crearaacute con el contenido de la memoria -de DEBUG- cuando posteriormente seleccione la opcioacuten escribir W (Write)[4]

Nota Como ya habraacute deducido DEBUG permite leer un archivo realizar modificaciones en eacutel (con la opcioacuten E) y escribir el archivo modificado bajo otro nombre con NW

A continuacioacuten podemos comprobar el tamantildeo del archivo cargado Para ello usamos la opcioacuten 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 17A70100 E8CD0F CALL 10D0 -

Aquiacute nos interesa especialmente el contenido del registro CX cuyo valor 2917h (1519d) en este caso sentildeala el tamantildeo del archivo en bytes Tambieacuten podiacuteamos haber utilizado directamente el comando R CX que nos proporciona el valor de dicho registro -R CX CX 2917 -

Nota A continuacioacuten del valor correspondiente DEBUG muestra dos puntos () sentildealando que puede cambiar el valor del registro introduciendo un nuevo nuacutemero Pulse INTRO para dejar las cosas como estaacuten y volver al prompt (-) de DEBUG

Al llegar a este punto es importante sentildealar que a excepcioacuten de los archivos exe DEBUG carga los archivos a partir de la direccioacuten 100h (256d) de su memoria De forma que el primer octeto del archivo se carga en la direccioacuten 100 el segundo en 101 etc En nuestro caso el archivo se extenderaacute desde la posicioacuten 100h hasta 2A17h (100h + 2917h) A continuacioacuten para buscar la cadena Microsoft en el archivo utilizamos cualquiera de los siguientes comandos - S 100 L 2917 Microsoft - S 100 2a17 Microsoft El primer comando sentildeala el punto de inicio y el tamantildeo de la zona a buscar el segundo utiliza los puntos inicial y final de la exploracioacuten Con ambos se obtiene la misma respuesta 17A71083 17A710B2

Truco Debido a la forma especial en que se cargan los ejecutables exe si quiere inspeccionar la forma nativa de uno de estos archivos (como es su imagen en el disco) debe hacer una copia del archivo renombrarlo con cualquier otra terminacioacuten (o sin ella) y cargar esta copia En caso contrario DEBUG se prepararaacute para funcionar como un verdadero depurador de tiempo de ejecucioacuten (run-time) para lo que cargaraacute el archivo y lo acomodaraacute en memoria de forma que pueda ejecutarse [5]

Como ejercicio compruebe las distintas longitudes y aspecto (especialmente al principio) de un mismo archivo exe cargaacutendolo con DEBUG de las dos formas (busque en su sistema un exe lo maacutes pequentildeo posible) Ademaacutes de la capacidad de leer archivos antes mencionada quizaacutes una de las opciones maacutes interesantes (y peligrosas) de DEBUG es la posibilidad de leerescribir el contenido de disco a bajo nivel mediante los prefijos L (Load) y W (Write) Se utiliza la siguiente sintaxis L [Direccioacuten] [Unidad] [Primer_sector] [Nuacutemero] W [Direccioacuten] [Unidad] [Primer_sector] [Nuacutemero] El significado de los paraacutemetros es como sigue

Direccioacuten Posicioacuten de la memoria de DEBUG a partir de la cual se instalaraacuten los datos leiacutedos del disco o se tomaraacuten para el proceso de escritura (aquiacute se utiliza generalmente el valor 100h)

Unidad Valor numeacuterico que indica la loacutegica a utilizar 0 = A 1 = B 2 = C 3 = D etc [6]

Primer sector A partir del que se realizaraacute la lectura o se comenzaraacute a escribir

Nuacutemero Nuacutemero de sectores que se desea cargarescribir Como DEBUG no puede leerescribir maacutes de 64 Kbytes (2

16 = 65536) y los sectores de disco son de 512 bytes

el maacuteximo nuacutemero de sectores es 128 (80h) Asiacute pues el valor maacuteximo aquiacute es 80 Ejemplo Para obtener el contenido del sector de arranque (Master boot sector MBR) de un disquete en A utilizaremos el comando CWINDOWSgtDEBUG - L 100 0 0 1 - D 100 L 200 Como el resultado no cabe en una pantalla ingeniaremos un procedimiento para conservarlo en un archivo (maacutes adelante nos serviraacute para otro propoacutesito) Para ello creamos un archivo scripttxt con el siguiente contenido (dos INTRO despueacutes de la Q) L 100 0 0 1 D 100 L 200 Q A continuacioacuten invocamos DEBUG con el comando CWINDOWSgtDEBUG lt Dbuzonscripttxt gt Dbuzonresultadtxt Despueacutes de un breve parpadeo del disco y del disquete vuelve el prompt del DOS La operacioacuten ha concluido y en el directorio correspondiente de la unidad D tenemos el archivo resultadtxt con el volcado del sector de arranque del disquete ademaacutes de los ecos de los comandos introducidos (los hemos mantenido para orientacioacuten del lector) Otra forma de poder visualizar el contenido del Sector de Arranque del disco es utilizando el DEBUG Por ejemplo dentro del DEBUG tecleamos lo siguiente -L 100 0 0 1

-D 100 L 200

177C0100 EB 3E 90 2B 79 73 57 29-49 48 43 00 02 01 01 00 gt+ysW)IHC

177C0110 02 E0 00 40 0B F0 09 00-12 00 02 00 00 00 00 00

177C0120 00 00 00 00 00 00 29 5D-3B DD 10 4E 4F 20 4E 41 )]NO NA

177C0130 4D 45 20 20 20 20 46 41-54 31 32 20 20 20 F1 7D ME FAT12

177C0140 FA 33 C9 8E D1 BC FC 7B-16 07 BD 78 00 C5 76 00 3xv

177C0150 1E 56 16 55 BF 22 05 89-7E 00 89 4E 02 B1 0B FC VU~N

177C0160 F3 A4 06 1F BD 00 7C C6-45 FE 0F 8B 46 18 88 45 |EFE

177C0170 F9 FB 38 66 24 7C 04 CD-13 72 3C 8A 46 10 98 F7 8f$|rltF

177C0180 66 16 03 46 1C 13 56 1E-03 46 0E 13 D1 50 52 89 fFVFPR

177C0190 46 FC 89 56 FE B8 20 00-8B 76 11 F7 E6 8B 5E 0B FV v^

177C01A0 03 C3 48 F7 F3 01 46 FC-11 4E FE 5A 58 BB 00 07 HFNZX

177C01B0 8B FB B1 01 E8 94 00 72-47 38 2D 74 19 B1 0B 56 rG8-tV

177C01C0 8B 76 3E F3 A6 5E 74 4A-4E 74 0B 03 F9 83 C7 15 vgt^tJNt

177C01D0 3B FB 72 E5 EB D7 2B C9-B8 D8 7D 87 46 3E 3C D8 r+Fgtlt

177C01E0 75 99 BE 80 7D AC 98 03-F0 AC 84 C0 74 17 3C FF utlt

177C01F0 74 09 B4 0E BB 07 00 CD-10 EB EE BE 83 7D EB E5 t

177C0200 BE 81 7D EB E0 33 C0 CD-16 5E 1F 8F 04 8F 44 02 3^D

177C0210 CD 19 BE 82 7D 8B 7D 0F-83 FF 02 72 C8 8B C7 48 rH

177C0220 48 8A 4E 0D F7 E1 03 46-FC 13 56 FE BB 00 07 53 HNFVS

177C0230 B1 04 E8 16 00 5B 72 C8-81 3F 4D 5A 75 A7 81 BF [rMZu

177C0240 00 02 42 4A 75 9F EA 00-02 70 00 50 52 51 91 92 BJupPRQ

177C0250 33 D2 F7 76 18 91 F7 76-18 42 87 CA F7 76 1A 8A 3vvBv

177C0260 F2 8A 56 24 8A E8 D0 CC-D0 CC 0A CC B8 01 02 CD V$

177C0270 13 59 5A 58 72 09 40 75-01 42 03 5E 0B E2 CC C3 YZXruB^

177C0280 03 18 01 27 0D 0A 44 69-73 63 6F 20 69 6E 63 6F Disco inco

177C0290 72 72 65 63 74 6F 20 20-20 FF 0D 0A 45 72 72 6F rrecto Erro

177C02A0 72 20 45 2F 53 20 20 20-20 20 FF 0D 0A 43 61 6D r ES Cam

177C02B0 62 69 65 20 65 6C 20 64-69 73 63 6F 20 79 20 70 bie el disco y p

177C02C0 72 65 73 69 6F 6E 65 20-75 6E 61 20 74 65 63 6C resione una tecl

177C02D0 61 20 20 20 20 0D 0A 00-49 4F 20 20 20 20 20 20 a IO

177C02E0 53 59 53 4D 53 44 4F 53-20 20 20 53 59 53 80 01 SYSMSDOS SYS

177C02F0 00 57 49 4E 42 4F 4F 54-20 53 59 53 00 00 55 AA WINBOOT SYSU

-

-Q

FIN [1] En las primeras versiones de MS-DOS era un modesto programita DEBUGCOM de apenas 16 KB La versioacuten que acompantildea a Windows98 es ya un ejecutable en formato EXE de 21 KB [2] En realidad DEBUG es una utilidad de enorme potencia que requeririacutea todo un libro para ella sola Puede encontrarse una amplia descripcioacuten de esta herramienta en el libro de Paul Somerson PC Magazine DOS Powers Tools [3] Desgraciadamente no hay una convencioacuten estaacutendar sobre la colocacioacuten de los datos en la BIOS de forma que cada fabricante sigue sus propias reglas y es imposible por tanto utilizarla para cualquier tipo de identificacioacuten del sistema [4] En palabras del mencionado Paul Somerson Desgraciadamente debido a que DEBUG es un programa tan increiacuteblemente potente tambieacuten es increiacuteblemente peligroso Hay un dicho que afirma que El software no puede destruir el hardware Desgraciadamente esto no es cierto Ademaacutes de enviar mecanismos sensibles de la unidad de disco a tierra de nadie es posible hacer saltar monitores o transformadores Repito si sigue al pie de la letra las instrucciones y hace caso a todos los avisos todo iraacute bien [5] Recuerde que la imagen de un ejecutable exe cargado en memoria es distinta de su imagen en disco Solo en los ejecutables com la imagen en disco es una imagen exacta de su disposicioacuten en memoria [6] Es evidente que un pequentildeo error de nuacutemero en este paraacutemetro puede acarrear consecuencias nefastas Por ejemplo si cree que estaacute jugando con el disquete e inadvertidamente se dirige al disco duro (relea la nota [4])

Page 17: El Comando DEBUG

Guardar y cargar los programas No seriacutea praacutectico tener que escribir todo un programa cada vez que se necesite para evitar eso es posible guardar un programa en el disco con la enorme ventaja de que ya ensamblado no seraacute necesario correr de nuevo DEBUG para ejecutarlo ya que cuando el DEBUG guardo nuestro programa en el disco eacuteste se guardo en binario (archivo con la extensioacuten com) Los pasos a seguir para guardar un programa ya almacenado en la memoria son

Obtener la longitud del programa restando la direccioacuten final de la direccioacuten inicial naturalmente en sistema hexadecimal

Darle un nombre al programa y una extensioacuten

Poner la longitud del programa en el registro CX

Ordenar a DEBUG que escriba el programa en el disco Utilizando como ejemplo el programa del ejemplo anterior tendremos una idea maacutes clara de coacutemo llevar estos pasos Al terminar de ensamblar el programa se veriacutea asiacute

0C1B0100 mov ax0002 0C1B0103 mov bx0004 0C1B0106 add axbx 0C1B0108 int 20 0C1B010A

Para almacenarlo en el disco hacemos lo siguiente - h 10a 100 020a 000a - n pruebacom - r cx CX 0000 000a -w Writing 000A bytes

Para obtener la longitud de un programa se utiliza el comando h el cual nos muestra la suma y resta de dos nuacutemeros en hexadecimal Para obtener la longitud del programa le proporcionamos como paraacutemetros el valor de la direccioacuten final de nuestro programa (10A) y el valor de la direccioacuten inicial (0100) El primer resultado que nos muestra el comando es la suma de los paraacutemetros y el segundo es la resta El comando n nos permite poner un nombre al programa El comando r cx nos permite cambiar el contenido del registro CX al valor que obtuvimos del tamantildeo del archivo con h en este caso 000a ya que nos interesa el resultado de la resta de la direccioacuten inicial a la direccioacuten final

Por uacuteltimo el comando w escribe nuestro programa en el disco indicaacutendonos cuantos bytes escribioacute

NOTA Si se trabaja en una ventana de DOS de Windows Vista o 7 es probable que al momento de guardar su programa el DEBUG escriba mas coacutedigo que el sentildealado por el registro CX por consiguiente seraacute necesario limpiar el registro BX esto es ponerlo a ceros y despueacutes utilizar el comando w Por ejemplo _r bx BX 000E 0000 w

Para cargar un archivo ya guardado son necesarios dos pasos

Proporcionar el nombre del archivo que se cargaraacute a memoria

Cargarlo utilizando el comando l (load) Para obtener el resultado correcto de los siguientes pasos es necesario que previamente se haya creado el programa anterior Dentro del DEBUG escribimos lo siguiente

- n pruebacom - l - u 100 109 0C3D0100 B80200 MOV AX0002 0C3D0103 BB0400 MOV BX0004 0C3D0106 01D8 ADD AXBX 0C3D0108 CD20 INT 20

El uacuteltimo comando u se utiliza para verificar que el programa se cargoacute en memoria lo que hace es desensamblar el coacutedigo y mostrarlo ya desensamblado Los paraacutemetros le indican a DEBUG desde donde y hasta donde desensamblar DEBUG siempre carga los programas en memoria en la direccioacuten 100H a menos que se le indique alguna otra Un programa que realiza un conteo en pantalla Con el DEBUG es posible escribir un programa que realice un conteo en pantalla por razones de comprensioacuten nuestro programa solo realizara un conteo de 9 a 0 (conteo descendente) 0B3B0100 B90A00 MOV CX000A CX=10 en decimal 0B3B0103 88CA MOV DLCL 0B3B0105 80C22F ADD DL2F sumamos 02Fh a DL 0B3B0108 B402 MOV AH02 funcioacuten 02 de INT 21 para imprimir un caracter 0B3B010A CD21 INT 21

0B3B010C E2F5 LOOP 0103 CX=0 Si no salta a 0103 0B3B010E CD20 INT 20 termina el programa En la liacutenea 0103 se puede observar que el valor del registro CX en su parte baja (en CL) se almacena en el registro DL Si se omitiera la liacutenea 0105 entonces cuando se ejecutara la liacutenea 010A solo se imprimiriacutea en pantalla el coacutedigo ASCII del valor que contenga DL (el coacutedigo ASCII de 0Ah que es 10 en decimal es un caraacutecter especial no imprimible) Para conseguir el ldquoefectordquo de que el programa realiza el conteo en decimal se hace un corrimiento de 02F (47 en decimal) Por ejemplo cuando se ejecuta la liacutenea 0105 DL tendriacutea el valor de 39h=57d (02Fh+0Ah=39h=57d) y el coacutedigo ASCII de 57d es el caraacutecter ldquo9rdquo El sentencia LOOP decrementa CX en 1 si CX es diferente a 0 salta a la liacutenea 0103 El proceso se repite y el programa imprime en pantalla 9876543210 Seriacutea interesante que el programa anterior fuera modificado para que la numeracioacuten se imprimiera de la siguiente manera 9 8 7 6 5 4 3 2 1 0

NOTA Como se dijo anteriormente cuando el DEBUG almacena un programa en el disco este archivo se graba en binario esto es en ejecutable Por lo tanto no es necesario cargar el DEBUG para volver a ejecutar nuestro programa sino que se hace de manera directa desde DOS El problema surge cuando al ejecutar nuestro programa el resultado no se puede observar porque el DOS borra la pantalla despueacutes de terminar de ejecutar el programa Para evitar el borrado automaacutetico seraacute necesario agregarle a nuestro programa antes de la INT 20h una instruccioacuten para la lectura de un caraacutecter desde el teclado Para tal efecto utilizaremos la funcioacuten 08 de la INT 21h (un buen truco para que el programa haga una pausa) asiacute el programa esperara hasta que el usuario presiona una tecla permitiendo observar el resultado Ejemplo mov ah08 Int 21 Int 20

Condiciones ciclos y bifurcaciones Estas estructuras o formas de control le dan a la maacutequina un cierto grado de decisioacuten basado en la informacioacuten que recibe La forma maacutes sencilla de comprender este tema es por medio de ejemplos Vamos a crear tres programas que hagan lo mismo desplegar un nuacutemero determinado de veces una cadena de caracteres en la pantalla

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV CX000F veces que se desplegara la cadena 0C1B0128 MOV DX0102 copia cadena al registro DX 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F LOOP 012D si CXgt0 salta a 012D 0C1B0131 INT 20 termina el programa

Por medio del comando e es posible introducir una cadena de caracteres en una determinada localidad de memoria dada como paraacutemetro la cadena se introduce entre comillas le sigue un espacio luego el valor hexadecimal del retorno de carro un espacio el valor de liacutenea nueva y por uacuteltimo el siacutembolo $ que el ensamblador interpreta como final de la cadena La interrupcioacuten 21 utiliza el valor almacenado en el registro AH para ejecutar una determinada funcioacuten en este caso mostrar la cadena en pantalla la cadena que muestra es la que estaacute almacenada en el registro DX La instruccioacuten LOOP decrementa automaacuteticamente el registro CX en uno y si no ha llegado el valor de este registro a cero salta a la posicioacuten de memoria indicada como paraacutemetro lo cual crea un ciclo que se repite el nuacutemero de veces especificado por el valor de CX La interrupcioacuten 20 termina la ejecucioacuten del programa Otra forma de realizar la misma funcioacuten pero sin utilizar el comando LOOP es la siguiente

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV BX000F veces que se desplegara la cadena 0C1B0128 MOV DX0102 copia cadena al registro DX 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F DEC BX decrementa en 1 a BX 0C1B0130 JNZ 012D si BX es diferente a 0 salta a 012D 0C1B0132 INT 20 termina el programa

En este caso se utiliza el registro BX como contador para el programa y por medio de la instruccioacuten DEC se disminuye su valor en 1 La instruccioacuten JNZ verifica si el valor de BX es diferente a 0 esto con base en la bandera NZ en caso afirmativo salta hacia la direccioacuten 012D En caso contrario continuacutea la ejecucioacuten normal del programa y por lo tanto se termina Una uacuteltima variante del programa es utilizando de nuevo a CX como contador pero en lugar de utilizar LOOP utilizaremos decrementos a CX y comparacioacuten de CX a 0

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV DX0102 copia cadena al registro DX 0C1B0128 MOV CX000F veces que se desplegara la cadena 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F DEC CX decrementa en 1 a CX 0C1B0130 JCXZ 0134 si CX es igual a 0 salta a 0134 0C1B0132 JMP 012D salta a la direccioacuten 012D 0C1B0134 INT 20 termina el programa

En este ejemplo se usoacute la instruccioacuten JCXZ para controlar la condicioacuten de salto el significado de tal funcioacuten es salta si CX=0 El tipo de control a utilizar dependeraacute de las necesidades de programacioacuten en determinado momento

Manipulacioacuten de Posiciones de Memoria Con el DEBUG es posible almacenar y recuperar datos numeacutericos en memoria por medio de un programa a traveacutes de los registros del microprocesador Por ejemplo el siguiente programa almacena previamente dos valores numeacutericos en la posicioacuten 0300h y 0400h respectivamente despueacutes el programa los recupera realiza la operacioacuten de suma con esos valores y el resultado lo almacena en la posicioacuten 0500h -a 100 0B1C0100 mov ax0002 ax=2 0B1C0103 mov [0300]ax almacenamos 2 en la direccioacuten 0300h 0B1C0106 mov ax0004 ax=4 0B1C0109 mov [0400]ax almacenamos 4 en la direccioacuten 0400h 0B1C010C mov ax[0300] recuperamos el dato1 en AX 0B1C010F mov bx[0400] recuperamos el dato2 en BX 0B1C0113 add axbx hacemos la operacioacuten de suma en AX 0B1C0115 mov [0500]ax almacenamos el 6 en la direccioacuten 0500h 0B1C0118 int 21 0B1C011A - Un nuacutemero entre corchetes [numero_hex] indica una posicioacuten de memoria y su manejo se hace a traveacutes de registros ya que no es posible almacenar valores numeacutericos de manera directa Ejecutamos el programa -g 118 AX=0006 BX=0004 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=0B1C ES=0B1C SS=0B1C CS=0B1C IP=0118 NV UP EI PL NZ NA PE NC 0B1C0118 CD21 INT 21 - Para ver si el resultado se almaceno en la direccioacuten correcta hacemos

Como se puede observar en la direccioacuten 0B1C0500 se encuentra el 06 y en 0B1C0501 se encuentra el 00 que es el resultado de la operacioacuten 2+4 Perohellip Porque aparece el 06 y despueacutes el 00 pareceriacutea que el resultado fue de 0600 pero no es asiacute lo que sucedes que los datos se almacenan en memoria de la siguiente manera

Como se hizo la operacioacuten AX=AX+BX entonces el resultado es de 16 bits (dos bytes) AX=6 entonces AX=0000 0000 0000 0110 (16 bits) por lo tanto los 8 bits de menor peso de AX son 0000 0110 y deben almacenarse en la direccioacuten 0500 y en la direccioacuten 0501 se almacena 0000 0000

0 0 0 0 0 1 1 0 0500

0 0 0 0 0 0 0 0 0501

x x x x x x x x 0502

x x x x x x x x 0503

x x x x x x x x 0504

x x x x x x x x 0505

Interrupciones Definicioacuten de interrupcioacuten

Una interrupcioacuten es una instruccioacuten que detiene la ejecucioacuten de un programa para permitir el uso del microprocesador en un proceso prioritario Una vez concluido este uacuteltimo proceso se devuelve el control a la aplicacioacuten anterior

Por ejemplo cuando estamos trabajando con un procesador de palabras y en ese momento llega un aviso de uno de los puertos de comunicaciones se detiene temporalmente la aplicacioacuten que estaacutebamos utilizando para permitir el uso del microprocesador al manejo de la informacioacuten que estaacute llegando en ese momento Una vez terminada la transferencia de informacioacuten se reanudan las funciones normales del procesador de palabras Las interrupciones ocurren muy seguido sencillamente la interrupcioacuten que actualiza la hora del diacutea ocurre aproximadamente 18 veces por segundo Para lograr administrar todas estas interrupciones la computadora cuenta con un espacio de memoria llamado memoria baja donde se almacenan las direcciones de cierta localidad de memoria donde se encuentran un juego de instrucciones que el microprocesador ejecutaraacute para despueacutes regresar a la aplicacioacuten que estaba en proceso En los programas anteriores hicimos uso de la interrupcioacuten nuacutemero 20H para terminar la ejecucioacuten de nuestros programas y en otros ejemplos utilizamos otra interrupcioacuten para mostrar informacioacuten en pantalla (INT 21h) Utilizando DEBUG tecleamos

- a100 2C1B0100 JMP 011D 2C1B0102 [ENTER] - E 102 Hola como estas 0D 0A $ - A011D 2C1B011D MOV DX0102 2C1B0120 MOV AH09 2C1B0122 INT 21 2C1B0123 INT 20

Orden

creciente

de la

memoria

En este programa la interrupcioacuten 21h manda al monitor la cadena localizada en la direccioacuten a la que apunta el registro DX El valor que se le da a AH determina cual de las opciones de la interrupcioacuten 21h seraacute utilizada ya que esta interrupcioacuten cuenta con varias opciones El manejo directo de interrupciones es una de las partes maacutes fuertes del lenguaje ensamblador ya que con ellas es posible controlar eficientemente todos los dispositivos internos y externos de una computadora gracias al completo control que se tiene sobre operaciones de entrada y salida Maacutes del DEBUG Una caracteriacutestica poco conocida es que DEBUG puede aceptar entradas desde un archivo Script que puede ser un simple archivo de texto ASCII en el que cada comando esteacute separado del anterior por un INTRO Despueacutes del uacuteltimo que debe ser una Q para salir de DEBUG es conveniente dejar una liacutenea en blanco pulsando INTRO dos veces Las liacuteneas pueden contener comentarios Cualquier cosa a partir del caracter punto y coma () hasta el final de la liacutenea seraacute ignorado esto es un comentario D aquiacute se mostraraacute algo Suponiendo que tengamos un archivo Script de nombre Ordenestxt puede ser utilizado como entrada para DEBUG mediante un comando de redireccioacuten en la siguiente forma DEBUG lt ordenestxt Tambieacuten puede conseguirse que el programa redireccione la salida hacia un archivo que puede ser inspeccionado maacutes 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 podriacutea obtenerse un archivo Resulttxt con el siguiente comando DEBUG lt ordenestxt gt Resulttxt Errores Cuando DEBUG no sabe interpretar un comando muestra un mensaje de error y un indicador ^ debajo del sitio del comando donde estaacute el error Entradas y Salidas DEBUG asume que los datos numeacutericos proporcionados son hexadecimales y cuando se trate de direcciones de memoria deben introducirse en forma segmentada A su vez los resultados son mostrados tambieacuten 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

Cada fila muestra 16 posiciones de memoria a partir de la posicioacuten sentildealada por las columnas de la izquierda que las muestran como segmentodesplazamiento El bloque central muestra el contenido hexadecimal de cada byte mientras que el bloque derecho contiene la representacioacuten ASCII Por ejemplo la 3ra fila muestra el contenido de las posiciones 0B770120 a 0B77012F (ambas inclusive) Sus tres uacuteltimos bytes contienen respectivamente los caracteres r 9 y 2 que corresponden a las cantidades 72h 39h y 32h del bloque central Que como sabemos equivalen a los decimales 114 57 y 50 que son precisamente los valores ASCII de los caracteres ldquorrdquo ldquo9rdquo y ldquo2rdquo anteriormente mencionados

Nota Por razoacuten de que eacuteste tipo de salida pueda ser listado a impresora el bloque derecho no contiene en realidad la representacioacuten ASCII de todos los caracteres (algunos ni siquiera tienen una representacioacuten imprimible) En realidad solo se muestran los caracteres imprimibles del primer bloque (US-ASCII) El resto estaacute 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 caraacutecter imprimible Esto no significa que dichas posiciones representen efectivamente tales valores para la aplicacioacuten que las utiliza Por ejemplo puede que en realidad las dos posiciones de memoria mencionadas (dos octetos o bytes) en vez de los caracteres ldquo5rdquo y ldquoardquo representen una palabra de 16 bits en formato Little Endian que a su vez representan una cantidad entera (un nuacutemero) Comandos Aunque su descripcioacuten completa llenariacutea todo un capiacutetulo a continuacioacuten comentamos algunas de las opciones maacutes interesantes relativas a inspeccioacuten del coacutedigo y de contenidos de memoria La opcioacuten D (Dump) permite obtener un volcado del contenido de la memoria (de DEBUG) La sintaxis acepta dos formas D [direccioacuten-inicial] [L posiciones-desde-direccioacuten-inicial ] D [direccioacuten-inicial][direccioacuten-final] Naturalmente para que exista algo en el buacutefer de memoria (al principio quizaacutes solo contiene basura) es preciso indicarle que lea algo Este algo puede ser un rango de direcciones de memoria RAM una direccioacuten absoluta de disco (sector) un archivo o el contenido de los registros del procesador Para empezar puede indicaacutersele que cargue un archivo xxxxyz que tenemos en el directorio actual o en el PATH cuyo contenido queremos ver Cgt DEBUG xxxxyz -D aquiacute se obtendriacutea una salida anaacuteloga a la comentada

Hemos visto un ejemplo al tratar de los servicios de interrupciones del PC aquiacute mostraremos otro Sabemos que el punto de inicio de la BIOS es la direccioacuten F000FFF0 y que desde eacutesta posicioacuten hasta el final de la memoria DOS hay 16 bytes Puede obtenerse un volcado de estas posiciones con el siguiente comando -D F000FFF0 La salida en un equipo puede ser F000FFF0 CD 19 E0 00 F0 30 36 2F-33 30 2F 39 37 00 FC 38 0630978 En este caso el comando solo muestra una liacutenea porque ha alcanzado el final de la memoria Puede verse que la fecha de la BIOS del sistema ocupa las uacuteltimas posiciones Si se ordena el volcado de una direccioacuten suficientemente alejada del final de la memoria sin indicar ninguacuten nuacutemero de posiciones por defecto se toma el valor 128 (8 filas de 16 posiciones) Si desea una cantidad distinta hay que antildeadir una L (Long) y el nuacutemero de posiciones hasta un maacuteximo de 64 KB (FFFF) Todos los nuacutemeros deben ser expresados en hexadecimal Por consiguiente los dos comandos que siguen son equivalentes (recuerde que 80 es el equivalente hexadecimal de 128) D FE000000 D FE000000 L 80 He aquiacute el resultado

Sabemos que esta zona corresponde al aacuterea de la BIOS del Sistema Otra opcioacuten muy interesante nos permite buscar determinados contenidos a traveacutes de la memoria utilizando el prefijo S (Search) Existen dos sintaxis alternativas S direccioacuten-de-inicio L longitud-a-explorar contenido-a-buscar S direccioacuten-de-inicio direccioacuten-final L contenido-a-buscar El contenido debe ser proporcionado en hexadecimal (tal como apareceriacutea en la columna central del ejemplo anterior) o entre comillas si es un texto ASCII Por ejemplo en un equipo IBM deseo ver algunas caracteriacutesticas de la BIOS Seacute que estos datos se alojan a partir de la posicioacuten F0000000 hasta el final de la memoria Es decir una longitud de 64 Kbytes (FFFF) a partir de la posicioacuten de inicio y que seguramente los datos buscados estaraacuten cerca de la identificacioacuten de la propia BIOS (la cadena IBM) Por lo que se utiliza la siguiente sintaxis [3] -s f0000000 L ffff IBM

y se obtiene la siguiente salida F000E00E F000E111 con las direcciones donde se ha encontrado la ocurrencia buscada A continuacioacuten puedo explorar las proximidades de cada posicioacuten Por ejemplo para la primera -D f000e000

Si lo que se busca estaacute en un archivo primero hay que cargarlo Lo que se puede hacer de dos formas en la propia invocacioacuten de DEBUG o mediante los comandos N y L Por ejemplo si queremos inspeccionar el contenido del archivo morecom podemos utilizar dos formas CWINDOWSgtDEBUG cwindowscommandmorecom CWINDOWSgtDEBUG - N cwindowscommandmorecom - L La sintaxis para el prefijo N es N [path-name]nombre-de-archivo En ambos casos el contenido del archivo seraacute cargado en memoria y podraacute ser utilizado Atencioacuten despueacutes de la orden L (Load) DEBUG le avisaraacute si no encuentra el archivo pero seguiraacute su funcionamiento En tal caso simplemente piensa que N sentildeala el nombre de un nuevo archivo que crearaacute con el contenido de la memoria -de DEBUG- cuando posteriormente seleccione la opcioacuten escribir W (Write)[4]

Nota Como ya habraacute deducido DEBUG permite leer un archivo realizar modificaciones en eacutel (con la opcioacuten E) y escribir el archivo modificado bajo otro nombre con NW

A continuacioacuten podemos comprobar el tamantildeo del archivo cargado Para ello usamos la opcioacuten 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 17A70100 E8CD0F CALL 10D0 -

Aquiacute nos interesa especialmente el contenido del registro CX cuyo valor 2917h (1519d) en este caso sentildeala el tamantildeo del archivo en bytes Tambieacuten podiacuteamos haber utilizado directamente el comando R CX que nos proporciona el valor de dicho registro -R CX CX 2917 -

Nota A continuacioacuten del valor correspondiente DEBUG muestra dos puntos () sentildealando que puede cambiar el valor del registro introduciendo un nuevo nuacutemero Pulse INTRO para dejar las cosas como estaacuten y volver al prompt (-) de DEBUG

Al llegar a este punto es importante sentildealar que a excepcioacuten de los archivos exe DEBUG carga los archivos a partir de la direccioacuten 100h (256d) de su memoria De forma que el primer octeto del archivo se carga en la direccioacuten 100 el segundo en 101 etc En nuestro caso el archivo se extenderaacute desde la posicioacuten 100h hasta 2A17h (100h + 2917h) A continuacioacuten para buscar la cadena Microsoft en el archivo utilizamos cualquiera de los siguientes comandos - S 100 L 2917 Microsoft - S 100 2a17 Microsoft El primer comando sentildeala el punto de inicio y el tamantildeo de la zona a buscar el segundo utiliza los puntos inicial y final de la exploracioacuten Con ambos se obtiene la misma respuesta 17A71083 17A710B2

Truco Debido a la forma especial en que se cargan los ejecutables exe si quiere inspeccionar la forma nativa de uno de estos archivos (como es su imagen en el disco) debe hacer una copia del archivo renombrarlo con cualquier otra terminacioacuten (o sin ella) y cargar esta copia En caso contrario DEBUG se prepararaacute para funcionar como un verdadero depurador de tiempo de ejecucioacuten (run-time) para lo que cargaraacute el archivo y lo acomodaraacute en memoria de forma que pueda ejecutarse [5]

Como ejercicio compruebe las distintas longitudes y aspecto (especialmente al principio) de un mismo archivo exe cargaacutendolo con DEBUG de las dos formas (busque en su sistema un exe lo maacutes pequentildeo posible) Ademaacutes de la capacidad de leer archivos antes mencionada quizaacutes una de las opciones maacutes interesantes (y peligrosas) de DEBUG es la posibilidad de leerescribir el contenido de disco a bajo nivel mediante los prefijos L (Load) y W (Write) Se utiliza la siguiente sintaxis L [Direccioacuten] [Unidad] [Primer_sector] [Nuacutemero] W [Direccioacuten] [Unidad] [Primer_sector] [Nuacutemero] El significado de los paraacutemetros es como sigue

Direccioacuten Posicioacuten de la memoria de DEBUG a partir de la cual se instalaraacuten los datos leiacutedos del disco o se tomaraacuten para el proceso de escritura (aquiacute se utiliza generalmente el valor 100h)

Unidad Valor numeacuterico que indica la loacutegica a utilizar 0 = A 1 = B 2 = C 3 = D etc [6]

Primer sector A partir del que se realizaraacute la lectura o se comenzaraacute a escribir

Nuacutemero Nuacutemero de sectores que se desea cargarescribir Como DEBUG no puede leerescribir maacutes de 64 Kbytes (2

16 = 65536) y los sectores de disco son de 512 bytes

el maacuteximo nuacutemero de sectores es 128 (80h) Asiacute pues el valor maacuteximo aquiacute es 80 Ejemplo Para obtener el contenido del sector de arranque (Master boot sector MBR) de un disquete en A utilizaremos el comando CWINDOWSgtDEBUG - L 100 0 0 1 - D 100 L 200 Como el resultado no cabe en una pantalla ingeniaremos un procedimiento para conservarlo en un archivo (maacutes adelante nos serviraacute para otro propoacutesito) Para ello creamos un archivo scripttxt con el siguiente contenido (dos INTRO despueacutes de la Q) L 100 0 0 1 D 100 L 200 Q A continuacioacuten invocamos DEBUG con el comando CWINDOWSgtDEBUG lt Dbuzonscripttxt gt Dbuzonresultadtxt Despueacutes de un breve parpadeo del disco y del disquete vuelve el prompt del DOS La operacioacuten ha concluido y en el directorio correspondiente de la unidad D tenemos el archivo resultadtxt con el volcado del sector de arranque del disquete ademaacutes de los ecos de los comandos introducidos (los hemos mantenido para orientacioacuten del lector) Otra forma de poder visualizar el contenido del Sector de Arranque del disco es utilizando el DEBUG Por ejemplo dentro del DEBUG tecleamos lo siguiente -L 100 0 0 1

-D 100 L 200

177C0100 EB 3E 90 2B 79 73 57 29-49 48 43 00 02 01 01 00 gt+ysW)IHC

177C0110 02 E0 00 40 0B F0 09 00-12 00 02 00 00 00 00 00

177C0120 00 00 00 00 00 00 29 5D-3B DD 10 4E 4F 20 4E 41 )]NO NA

177C0130 4D 45 20 20 20 20 46 41-54 31 32 20 20 20 F1 7D ME FAT12

177C0140 FA 33 C9 8E D1 BC FC 7B-16 07 BD 78 00 C5 76 00 3xv

177C0150 1E 56 16 55 BF 22 05 89-7E 00 89 4E 02 B1 0B FC VU~N

177C0160 F3 A4 06 1F BD 00 7C C6-45 FE 0F 8B 46 18 88 45 |EFE

177C0170 F9 FB 38 66 24 7C 04 CD-13 72 3C 8A 46 10 98 F7 8f$|rltF

177C0180 66 16 03 46 1C 13 56 1E-03 46 0E 13 D1 50 52 89 fFVFPR

177C0190 46 FC 89 56 FE B8 20 00-8B 76 11 F7 E6 8B 5E 0B FV v^

177C01A0 03 C3 48 F7 F3 01 46 FC-11 4E FE 5A 58 BB 00 07 HFNZX

177C01B0 8B FB B1 01 E8 94 00 72-47 38 2D 74 19 B1 0B 56 rG8-tV

177C01C0 8B 76 3E F3 A6 5E 74 4A-4E 74 0B 03 F9 83 C7 15 vgt^tJNt

177C01D0 3B FB 72 E5 EB D7 2B C9-B8 D8 7D 87 46 3E 3C D8 r+Fgtlt

177C01E0 75 99 BE 80 7D AC 98 03-F0 AC 84 C0 74 17 3C FF utlt

177C01F0 74 09 B4 0E BB 07 00 CD-10 EB EE BE 83 7D EB E5 t

177C0200 BE 81 7D EB E0 33 C0 CD-16 5E 1F 8F 04 8F 44 02 3^D

177C0210 CD 19 BE 82 7D 8B 7D 0F-83 FF 02 72 C8 8B C7 48 rH

177C0220 48 8A 4E 0D F7 E1 03 46-FC 13 56 FE BB 00 07 53 HNFVS

177C0230 B1 04 E8 16 00 5B 72 C8-81 3F 4D 5A 75 A7 81 BF [rMZu

177C0240 00 02 42 4A 75 9F EA 00-02 70 00 50 52 51 91 92 BJupPRQ

177C0250 33 D2 F7 76 18 91 F7 76-18 42 87 CA F7 76 1A 8A 3vvBv

177C0260 F2 8A 56 24 8A E8 D0 CC-D0 CC 0A CC B8 01 02 CD V$

177C0270 13 59 5A 58 72 09 40 75-01 42 03 5E 0B E2 CC C3 YZXruB^

177C0280 03 18 01 27 0D 0A 44 69-73 63 6F 20 69 6E 63 6F Disco inco

177C0290 72 72 65 63 74 6F 20 20-20 FF 0D 0A 45 72 72 6F rrecto Erro

177C02A0 72 20 45 2F 53 20 20 20-20 20 FF 0D 0A 43 61 6D r ES Cam

177C02B0 62 69 65 20 65 6C 20 64-69 73 63 6F 20 79 20 70 bie el disco y p

177C02C0 72 65 73 69 6F 6E 65 20-75 6E 61 20 74 65 63 6C resione una tecl

177C02D0 61 20 20 20 20 0D 0A 00-49 4F 20 20 20 20 20 20 a IO

177C02E0 53 59 53 4D 53 44 4F 53-20 20 20 53 59 53 80 01 SYSMSDOS SYS

177C02F0 00 57 49 4E 42 4F 4F 54-20 53 59 53 00 00 55 AA WINBOOT SYSU

-

-Q

FIN [1] En las primeras versiones de MS-DOS era un modesto programita DEBUGCOM de apenas 16 KB La versioacuten que acompantildea a Windows98 es ya un ejecutable en formato EXE de 21 KB [2] En realidad DEBUG es una utilidad de enorme potencia que requeririacutea todo un libro para ella sola Puede encontrarse una amplia descripcioacuten de esta herramienta en el libro de Paul Somerson PC Magazine DOS Powers Tools [3] Desgraciadamente no hay una convencioacuten estaacutendar sobre la colocacioacuten de los datos en la BIOS de forma que cada fabricante sigue sus propias reglas y es imposible por tanto utilizarla para cualquier tipo de identificacioacuten del sistema [4] En palabras del mencionado Paul Somerson Desgraciadamente debido a que DEBUG es un programa tan increiacuteblemente potente tambieacuten es increiacuteblemente peligroso Hay un dicho que afirma que El software no puede destruir el hardware Desgraciadamente esto no es cierto Ademaacutes de enviar mecanismos sensibles de la unidad de disco a tierra de nadie es posible hacer saltar monitores o transformadores Repito si sigue al pie de la letra las instrucciones y hace caso a todos los avisos todo iraacute bien [5] Recuerde que la imagen de un ejecutable exe cargado en memoria es distinta de su imagen en disco Solo en los ejecutables com la imagen en disco es una imagen exacta de su disposicioacuten en memoria [6] Es evidente que un pequentildeo error de nuacutemero en este paraacutemetro puede acarrear consecuencias nefastas Por ejemplo si cree que estaacute jugando con el disquete e inadvertidamente se dirige al disco duro (relea la nota [4])

Page 18: El Comando DEBUG

Por uacuteltimo el comando w escribe nuestro programa en el disco indicaacutendonos cuantos bytes escribioacute

NOTA Si se trabaja en una ventana de DOS de Windows Vista o 7 es probable que al momento de guardar su programa el DEBUG escriba mas coacutedigo que el sentildealado por el registro CX por consiguiente seraacute necesario limpiar el registro BX esto es ponerlo a ceros y despueacutes utilizar el comando w Por ejemplo _r bx BX 000E 0000 w

Para cargar un archivo ya guardado son necesarios dos pasos

Proporcionar el nombre del archivo que se cargaraacute a memoria

Cargarlo utilizando el comando l (load) Para obtener el resultado correcto de los siguientes pasos es necesario que previamente se haya creado el programa anterior Dentro del DEBUG escribimos lo siguiente

- n pruebacom - l - u 100 109 0C3D0100 B80200 MOV AX0002 0C3D0103 BB0400 MOV BX0004 0C3D0106 01D8 ADD AXBX 0C3D0108 CD20 INT 20

El uacuteltimo comando u se utiliza para verificar que el programa se cargoacute en memoria lo que hace es desensamblar el coacutedigo y mostrarlo ya desensamblado Los paraacutemetros le indican a DEBUG desde donde y hasta donde desensamblar DEBUG siempre carga los programas en memoria en la direccioacuten 100H a menos que se le indique alguna otra Un programa que realiza un conteo en pantalla Con el DEBUG es posible escribir un programa que realice un conteo en pantalla por razones de comprensioacuten nuestro programa solo realizara un conteo de 9 a 0 (conteo descendente) 0B3B0100 B90A00 MOV CX000A CX=10 en decimal 0B3B0103 88CA MOV DLCL 0B3B0105 80C22F ADD DL2F sumamos 02Fh a DL 0B3B0108 B402 MOV AH02 funcioacuten 02 de INT 21 para imprimir un caracter 0B3B010A CD21 INT 21

0B3B010C E2F5 LOOP 0103 CX=0 Si no salta a 0103 0B3B010E CD20 INT 20 termina el programa En la liacutenea 0103 se puede observar que el valor del registro CX en su parte baja (en CL) se almacena en el registro DL Si se omitiera la liacutenea 0105 entonces cuando se ejecutara la liacutenea 010A solo se imprimiriacutea en pantalla el coacutedigo ASCII del valor que contenga DL (el coacutedigo ASCII de 0Ah que es 10 en decimal es un caraacutecter especial no imprimible) Para conseguir el ldquoefectordquo de que el programa realiza el conteo en decimal se hace un corrimiento de 02F (47 en decimal) Por ejemplo cuando se ejecuta la liacutenea 0105 DL tendriacutea el valor de 39h=57d (02Fh+0Ah=39h=57d) y el coacutedigo ASCII de 57d es el caraacutecter ldquo9rdquo El sentencia LOOP decrementa CX en 1 si CX es diferente a 0 salta a la liacutenea 0103 El proceso se repite y el programa imprime en pantalla 9876543210 Seriacutea interesante que el programa anterior fuera modificado para que la numeracioacuten se imprimiera de la siguiente manera 9 8 7 6 5 4 3 2 1 0

NOTA Como se dijo anteriormente cuando el DEBUG almacena un programa en el disco este archivo se graba en binario esto es en ejecutable Por lo tanto no es necesario cargar el DEBUG para volver a ejecutar nuestro programa sino que se hace de manera directa desde DOS El problema surge cuando al ejecutar nuestro programa el resultado no se puede observar porque el DOS borra la pantalla despueacutes de terminar de ejecutar el programa Para evitar el borrado automaacutetico seraacute necesario agregarle a nuestro programa antes de la INT 20h una instruccioacuten para la lectura de un caraacutecter desde el teclado Para tal efecto utilizaremos la funcioacuten 08 de la INT 21h (un buen truco para que el programa haga una pausa) asiacute el programa esperara hasta que el usuario presiona una tecla permitiendo observar el resultado Ejemplo mov ah08 Int 21 Int 20

Condiciones ciclos y bifurcaciones Estas estructuras o formas de control le dan a la maacutequina un cierto grado de decisioacuten basado en la informacioacuten que recibe La forma maacutes sencilla de comprender este tema es por medio de ejemplos Vamos a crear tres programas que hagan lo mismo desplegar un nuacutemero determinado de veces una cadena de caracteres en la pantalla

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV CX000F veces que se desplegara la cadena 0C1B0128 MOV DX0102 copia cadena al registro DX 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F LOOP 012D si CXgt0 salta a 012D 0C1B0131 INT 20 termina el programa

Por medio del comando e es posible introducir una cadena de caracteres en una determinada localidad de memoria dada como paraacutemetro la cadena se introduce entre comillas le sigue un espacio luego el valor hexadecimal del retorno de carro un espacio el valor de liacutenea nueva y por uacuteltimo el siacutembolo $ que el ensamblador interpreta como final de la cadena La interrupcioacuten 21 utiliza el valor almacenado en el registro AH para ejecutar una determinada funcioacuten en este caso mostrar la cadena en pantalla la cadena que muestra es la que estaacute almacenada en el registro DX La instruccioacuten LOOP decrementa automaacuteticamente el registro CX en uno y si no ha llegado el valor de este registro a cero salta a la posicioacuten de memoria indicada como paraacutemetro lo cual crea un ciclo que se repite el nuacutemero de veces especificado por el valor de CX La interrupcioacuten 20 termina la ejecucioacuten del programa Otra forma de realizar la misma funcioacuten pero sin utilizar el comando LOOP es la siguiente

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV BX000F veces que se desplegara la cadena 0C1B0128 MOV DX0102 copia cadena al registro DX 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F DEC BX decrementa en 1 a BX 0C1B0130 JNZ 012D si BX es diferente a 0 salta a 012D 0C1B0132 INT 20 termina el programa

En este caso se utiliza el registro BX como contador para el programa y por medio de la instruccioacuten DEC se disminuye su valor en 1 La instruccioacuten JNZ verifica si el valor de BX es diferente a 0 esto con base en la bandera NZ en caso afirmativo salta hacia la direccioacuten 012D En caso contrario continuacutea la ejecucioacuten normal del programa y por lo tanto se termina Una uacuteltima variante del programa es utilizando de nuevo a CX como contador pero en lugar de utilizar LOOP utilizaremos decrementos a CX y comparacioacuten de CX a 0

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV DX0102 copia cadena al registro DX 0C1B0128 MOV CX000F veces que se desplegara la cadena 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F DEC CX decrementa en 1 a CX 0C1B0130 JCXZ 0134 si CX es igual a 0 salta a 0134 0C1B0132 JMP 012D salta a la direccioacuten 012D 0C1B0134 INT 20 termina el programa

En este ejemplo se usoacute la instruccioacuten JCXZ para controlar la condicioacuten de salto el significado de tal funcioacuten es salta si CX=0 El tipo de control a utilizar dependeraacute de las necesidades de programacioacuten en determinado momento

Manipulacioacuten de Posiciones de Memoria Con el DEBUG es posible almacenar y recuperar datos numeacutericos en memoria por medio de un programa a traveacutes de los registros del microprocesador Por ejemplo el siguiente programa almacena previamente dos valores numeacutericos en la posicioacuten 0300h y 0400h respectivamente despueacutes el programa los recupera realiza la operacioacuten de suma con esos valores y el resultado lo almacena en la posicioacuten 0500h -a 100 0B1C0100 mov ax0002 ax=2 0B1C0103 mov [0300]ax almacenamos 2 en la direccioacuten 0300h 0B1C0106 mov ax0004 ax=4 0B1C0109 mov [0400]ax almacenamos 4 en la direccioacuten 0400h 0B1C010C mov ax[0300] recuperamos el dato1 en AX 0B1C010F mov bx[0400] recuperamos el dato2 en BX 0B1C0113 add axbx hacemos la operacioacuten de suma en AX 0B1C0115 mov [0500]ax almacenamos el 6 en la direccioacuten 0500h 0B1C0118 int 21 0B1C011A - Un nuacutemero entre corchetes [numero_hex] indica una posicioacuten de memoria y su manejo se hace a traveacutes de registros ya que no es posible almacenar valores numeacutericos de manera directa Ejecutamos el programa -g 118 AX=0006 BX=0004 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=0B1C ES=0B1C SS=0B1C CS=0B1C IP=0118 NV UP EI PL NZ NA PE NC 0B1C0118 CD21 INT 21 - Para ver si el resultado se almaceno en la direccioacuten correcta hacemos

Como se puede observar en la direccioacuten 0B1C0500 se encuentra el 06 y en 0B1C0501 se encuentra el 00 que es el resultado de la operacioacuten 2+4 Perohellip Porque aparece el 06 y despueacutes el 00 pareceriacutea que el resultado fue de 0600 pero no es asiacute lo que sucedes que los datos se almacenan en memoria de la siguiente manera

Como se hizo la operacioacuten AX=AX+BX entonces el resultado es de 16 bits (dos bytes) AX=6 entonces AX=0000 0000 0000 0110 (16 bits) por lo tanto los 8 bits de menor peso de AX son 0000 0110 y deben almacenarse en la direccioacuten 0500 y en la direccioacuten 0501 se almacena 0000 0000

0 0 0 0 0 1 1 0 0500

0 0 0 0 0 0 0 0 0501

x x x x x x x x 0502

x x x x x x x x 0503

x x x x x x x x 0504

x x x x x x x x 0505

Interrupciones Definicioacuten de interrupcioacuten

Una interrupcioacuten es una instruccioacuten que detiene la ejecucioacuten de un programa para permitir el uso del microprocesador en un proceso prioritario Una vez concluido este uacuteltimo proceso se devuelve el control a la aplicacioacuten anterior

Por ejemplo cuando estamos trabajando con un procesador de palabras y en ese momento llega un aviso de uno de los puertos de comunicaciones se detiene temporalmente la aplicacioacuten que estaacutebamos utilizando para permitir el uso del microprocesador al manejo de la informacioacuten que estaacute llegando en ese momento Una vez terminada la transferencia de informacioacuten se reanudan las funciones normales del procesador de palabras Las interrupciones ocurren muy seguido sencillamente la interrupcioacuten que actualiza la hora del diacutea ocurre aproximadamente 18 veces por segundo Para lograr administrar todas estas interrupciones la computadora cuenta con un espacio de memoria llamado memoria baja donde se almacenan las direcciones de cierta localidad de memoria donde se encuentran un juego de instrucciones que el microprocesador ejecutaraacute para despueacutes regresar a la aplicacioacuten que estaba en proceso En los programas anteriores hicimos uso de la interrupcioacuten nuacutemero 20H para terminar la ejecucioacuten de nuestros programas y en otros ejemplos utilizamos otra interrupcioacuten para mostrar informacioacuten en pantalla (INT 21h) Utilizando DEBUG tecleamos

- a100 2C1B0100 JMP 011D 2C1B0102 [ENTER] - E 102 Hola como estas 0D 0A $ - A011D 2C1B011D MOV DX0102 2C1B0120 MOV AH09 2C1B0122 INT 21 2C1B0123 INT 20

Orden

creciente

de la

memoria

En este programa la interrupcioacuten 21h manda al monitor la cadena localizada en la direccioacuten a la que apunta el registro DX El valor que se le da a AH determina cual de las opciones de la interrupcioacuten 21h seraacute utilizada ya que esta interrupcioacuten cuenta con varias opciones El manejo directo de interrupciones es una de las partes maacutes fuertes del lenguaje ensamblador ya que con ellas es posible controlar eficientemente todos los dispositivos internos y externos de una computadora gracias al completo control que se tiene sobre operaciones de entrada y salida Maacutes del DEBUG Una caracteriacutestica poco conocida es que DEBUG puede aceptar entradas desde un archivo Script que puede ser un simple archivo de texto ASCII en el que cada comando esteacute separado del anterior por un INTRO Despueacutes del uacuteltimo que debe ser una Q para salir de DEBUG es conveniente dejar una liacutenea en blanco pulsando INTRO dos veces Las liacuteneas pueden contener comentarios Cualquier cosa a partir del caracter punto y coma () hasta el final de la liacutenea seraacute ignorado esto es un comentario D aquiacute se mostraraacute algo Suponiendo que tengamos un archivo Script de nombre Ordenestxt puede ser utilizado como entrada para DEBUG mediante un comando de redireccioacuten en la siguiente forma DEBUG lt ordenestxt Tambieacuten puede conseguirse que el programa redireccione la salida hacia un archivo que puede ser inspeccionado maacutes 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 podriacutea obtenerse un archivo Resulttxt con el siguiente comando DEBUG lt ordenestxt gt Resulttxt Errores Cuando DEBUG no sabe interpretar un comando muestra un mensaje de error y un indicador ^ debajo del sitio del comando donde estaacute el error Entradas y Salidas DEBUG asume que los datos numeacutericos proporcionados son hexadecimales y cuando se trate de direcciones de memoria deben introducirse en forma segmentada A su vez los resultados son mostrados tambieacuten 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

Cada fila muestra 16 posiciones de memoria a partir de la posicioacuten sentildealada por las columnas de la izquierda que las muestran como segmentodesplazamiento El bloque central muestra el contenido hexadecimal de cada byte mientras que el bloque derecho contiene la representacioacuten ASCII Por ejemplo la 3ra fila muestra el contenido de las posiciones 0B770120 a 0B77012F (ambas inclusive) Sus tres uacuteltimos bytes contienen respectivamente los caracteres r 9 y 2 que corresponden a las cantidades 72h 39h y 32h del bloque central Que como sabemos equivalen a los decimales 114 57 y 50 que son precisamente los valores ASCII de los caracteres ldquorrdquo ldquo9rdquo y ldquo2rdquo anteriormente mencionados

Nota Por razoacuten de que eacuteste tipo de salida pueda ser listado a impresora el bloque derecho no contiene en realidad la representacioacuten ASCII de todos los caracteres (algunos ni siquiera tienen una representacioacuten imprimible) En realidad solo se muestran los caracteres imprimibles del primer bloque (US-ASCII) El resto estaacute 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 caraacutecter imprimible Esto no significa que dichas posiciones representen efectivamente tales valores para la aplicacioacuten que las utiliza Por ejemplo puede que en realidad las dos posiciones de memoria mencionadas (dos octetos o bytes) en vez de los caracteres ldquo5rdquo y ldquoardquo representen una palabra de 16 bits en formato Little Endian que a su vez representan una cantidad entera (un nuacutemero) Comandos Aunque su descripcioacuten completa llenariacutea todo un capiacutetulo a continuacioacuten comentamos algunas de las opciones maacutes interesantes relativas a inspeccioacuten del coacutedigo y de contenidos de memoria La opcioacuten D (Dump) permite obtener un volcado del contenido de la memoria (de DEBUG) La sintaxis acepta dos formas D [direccioacuten-inicial] [L posiciones-desde-direccioacuten-inicial ] D [direccioacuten-inicial][direccioacuten-final] Naturalmente para que exista algo en el buacutefer de memoria (al principio quizaacutes solo contiene basura) es preciso indicarle que lea algo Este algo puede ser un rango de direcciones de memoria RAM una direccioacuten absoluta de disco (sector) un archivo o el contenido de los registros del procesador Para empezar puede indicaacutersele que cargue un archivo xxxxyz que tenemos en el directorio actual o en el PATH cuyo contenido queremos ver Cgt DEBUG xxxxyz -D aquiacute se obtendriacutea una salida anaacuteloga a la comentada

Hemos visto un ejemplo al tratar de los servicios de interrupciones del PC aquiacute mostraremos otro Sabemos que el punto de inicio de la BIOS es la direccioacuten F000FFF0 y que desde eacutesta posicioacuten hasta el final de la memoria DOS hay 16 bytes Puede obtenerse un volcado de estas posiciones con el siguiente comando -D F000FFF0 La salida en un equipo puede ser F000FFF0 CD 19 E0 00 F0 30 36 2F-33 30 2F 39 37 00 FC 38 0630978 En este caso el comando solo muestra una liacutenea porque ha alcanzado el final de la memoria Puede verse que la fecha de la BIOS del sistema ocupa las uacuteltimas posiciones Si se ordena el volcado de una direccioacuten suficientemente alejada del final de la memoria sin indicar ninguacuten nuacutemero de posiciones por defecto se toma el valor 128 (8 filas de 16 posiciones) Si desea una cantidad distinta hay que antildeadir una L (Long) y el nuacutemero de posiciones hasta un maacuteximo de 64 KB (FFFF) Todos los nuacutemeros deben ser expresados en hexadecimal Por consiguiente los dos comandos que siguen son equivalentes (recuerde que 80 es el equivalente hexadecimal de 128) D FE000000 D FE000000 L 80 He aquiacute el resultado

Sabemos que esta zona corresponde al aacuterea de la BIOS del Sistema Otra opcioacuten muy interesante nos permite buscar determinados contenidos a traveacutes de la memoria utilizando el prefijo S (Search) Existen dos sintaxis alternativas S direccioacuten-de-inicio L longitud-a-explorar contenido-a-buscar S direccioacuten-de-inicio direccioacuten-final L contenido-a-buscar El contenido debe ser proporcionado en hexadecimal (tal como apareceriacutea en la columna central del ejemplo anterior) o entre comillas si es un texto ASCII Por ejemplo en un equipo IBM deseo ver algunas caracteriacutesticas de la BIOS Seacute que estos datos se alojan a partir de la posicioacuten F0000000 hasta el final de la memoria Es decir una longitud de 64 Kbytes (FFFF) a partir de la posicioacuten de inicio y que seguramente los datos buscados estaraacuten cerca de la identificacioacuten de la propia BIOS (la cadena IBM) Por lo que se utiliza la siguiente sintaxis [3] -s f0000000 L ffff IBM

y se obtiene la siguiente salida F000E00E F000E111 con las direcciones donde se ha encontrado la ocurrencia buscada A continuacioacuten puedo explorar las proximidades de cada posicioacuten Por ejemplo para la primera -D f000e000

Si lo que se busca estaacute en un archivo primero hay que cargarlo Lo que se puede hacer de dos formas en la propia invocacioacuten de DEBUG o mediante los comandos N y L Por ejemplo si queremos inspeccionar el contenido del archivo morecom podemos utilizar dos formas CWINDOWSgtDEBUG cwindowscommandmorecom CWINDOWSgtDEBUG - N cwindowscommandmorecom - L La sintaxis para el prefijo N es N [path-name]nombre-de-archivo En ambos casos el contenido del archivo seraacute cargado en memoria y podraacute ser utilizado Atencioacuten despueacutes de la orden L (Load) DEBUG le avisaraacute si no encuentra el archivo pero seguiraacute su funcionamiento En tal caso simplemente piensa que N sentildeala el nombre de un nuevo archivo que crearaacute con el contenido de la memoria -de DEBUG- cuando posteriormente seleccione la opcioacuten escribir W (Write)[4]

Nota Como ya habraacute deducido DEBUG permite leer un archivo realizar modificaciones en eacutel (con la opcioacuten E) y escribir el archivo modificado bajo otro nombre con NW

A continuacioacuten podemos comprobar el tamantildeo del archivo cargado Para ello usamos la opcioacuten 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 17A70100 E8CD0F CALL 10D0 -

Aquiacute nos interesa especialmente el contenido del registro CX cuyo valor 2917h (1519d) en este caso sentildeala el tamantildeo del archivo en bytes Tambieacuten podiacuteamos haber utilizado directamente el comando R CX que nos proporciona el valor de dicho registro -R CX CX 2917 -

Nota A continuacioacuten del valor correspondiente DEBUG muestra dos puntos () sentildealando que puede cambiar el valor del registro introduciendo un nuevo nuacutemero Pulse INTRO para dejar las cosas como estaacuten y volver al prompt (-) de DEBUG

Al llegar a este punto es importante sentildealar que a excepcioacuten de los archivos exe DEBUG carga los archivos a partir de la direccioacuten 100h (256d) de su memoria De forma que el primer octeto del archivo se carga en la direccioacuten 100 el segundo en 101 etc En nuestro caso el archivo se extenderaacute desde la posicioacuten 100h hasta 2A17h (100h + 2917h) A continuacioacuten para buscar la cadena Microsoft en el archivo utilizamos cualquiera de los siguientes comandos - S 100 L 2917 Microsoft - S 100 2a17 Microsoft El primer comando sentildeala el punto de inicio y el tamantildeo de la zona a buscar el segundo utiliza los puntos inicial y final de la exploracioacuten Con ambos se obtiene la misma respuesta 17A71083 17A710B2

Truco Debido a la forma especial en que se cargan los ejecutables exe si quiere inspeccionar la forma nativa de uno de estos archivos (como es su imagen en el disco) debe hacer una copia del archivo renombrarlo con cualquier otra terminacioacuten (o sin ella) y cargar esta copia En caso contrario DEBUG se prepararaacute para funcionar como un verdadero depurador de tiempo de ejecucioacuten (run-time) para lo que cargaraacute el archivo y lo acomodaraacute en memoria de forma que pueda ejecutarse [5]

Como ejercicio compruebe las distintas longitudes y aspecto (especialmente al principio) de un mismo archivo exe cargaacutendolo con DEBUG de las dos formas (busque en su sistema un exe lo maacutes pequentildeo posible) Ademaacutes de la capacidad de leer archivos antes mencionada quizaacutes una de las opciones maacutes interesantes (y peligrosas) de DEBUG es la posibilidad de leerescribir el contenido de disco a bajo nivel mediante los prefijos L (Load) y W (Write) Se utiliza la siguiente sintaxis L [Direccioacuten] [Unidad] [Primer_sector] [Nuacutemero] W [Direccioacuten] [Unidad] [Primer_sector] [Nuacutemero] El significado de los paraacutemetros es como sigue

Direccioacuten Posicioacuten de la memoria de DEBUG a partir de la cual se instalaraacuten los datos leiacutedos del disco o se tomaraacuten para el proceso de escritura (aquiacute se utiliza generalmente el valor 100h)

Unidad Valor numeacuterico que indica la loacutegica a utilizar 0 = A 1 = B 2 = C 3 = D etc [6]

Primer sector A partir del que se realizaraacute la lectura o se comenzaraacute a escribir

Nuacutemero Nuacutemero de sectores que se desea cargarescribir Como DEBUG no puede leerescribir maacutes de 64 Kbytes (2

16 = 65536) y los sectores de disco son de 512 bytes

el maacuteximo nuacutemero de sectores es 128 (80h) Asiacute pues el valor maacuteximo aquiacute es 80 Ejemplo Para obtener el contenido del sector de arranque (Master boot sector MBR) de un disquete en A utilizaremos el comando CWINDOWSgtDEBUG - L 100 0 0 1 - D 100 L 200 Como el resultado no cabe en una pantalla ingeniaremos un procedimiento para conservarlo en un archivo (maacutes adelante nos serviraacute para otro propoacutesito) Para ello creamos un archivo scripttxt con el siguiente contenido (dos INTRO despueacutes de la Q) L 100 0 0 1 D 100 L 200 Q A continuacioacuten invocamos DEBUG con el comando CWINDOWSgtDEBUG lt Dbuzonscripttxt gt Dbuzonresultadtxt Despueacutes de un breve parpadeo del disco y del disquete vuelve el prompt del DOS La operacioacuten ha concluido y en el directorio correspondiente de la unidad D tenemos el archivo resultadtxt con el volcado del sector de arranque del disquete ademaacutes de los ecos de los comandos introducidos (los hemos mantenido para orientacioacuten del lector) Otra forma de poder visualizar el contenido del Sector de Arranque del disco es utilizando el DEBUG Por ejemplo dentro del DEBUG tecleamos lo siguiente -L 100 0 0 1

-D 100 L 200

177C0100 EB 3E 90 2B 79 73 57 29-49 48 43 00 02 01 01 00 gt+ysW)IHC

177C0110 02 E0 00 40 0B F0 09 00-12 00 02 00 00 00 00 00

177C0120 00 00 00 00 00 00 29 5D-3B DD 10 4E 4F 20 4E 41 )]NO NA

177C0130 4D 45 20 20 20 20 46 41-54 31 32 20 20 20 F1 7D ME FAT12

177C0140 FA 33 C9 8E D1 BC FC 7B-16 07 BD 78 00 C5 76 00 3xv

177C0150 1E 56 16 55 BF 22 05 89-7E 00 89 4E 02 B1 0B FC VU~N

177C0160 F3 A4 06 1F BD 00 7C C6-45 FE 0F 8B 46 18 88 45 |EFE

177C0170 F9 FB 38 66 24 7C 04 CD-13 72 3C 8A 46 10 98 F7 8f$|rltF

177C0180 66 16 03 46 1C 13 56 1E-03 46 0E 13 D1 50 52 89 fFVFPR

177C0190 46 FC 89 56 FE B8 20 00-8B 76 11 F7 E6 8B 5E 0B FV v^

177C01A0 03 C3 48 F7 F3 01 46 FC-11 4E FE 5A 58 BB 00 07 HFNZX

177C01B0 8B FB B1 01 E8 94 00 72-47 38 2D 74 19 B1 0B 56 rG8-tV

177C01C0 8B 76 3E F3 A6 5E 74 4A-4E 74 0B 03 F9 83 C7 15 vgt^tJNt

177C01D0 3B FB 72 E5 EB D7 2B C9-B8 D8 7D 87 46 3E 3C D8 r+Fgtlt

177C01E0 75 99 BE 80 7D AC 98 03-F0 AC 84 C0 74 17 3C FF utlt

177C01F0 74 09 B4 0E BB 07 00 CD-10 EB EE BE 83 7D EB E5 t

177C0200 BE 81 7D EB E0 33 C0 CD-16 5E 1F 8F 04 8F 44 02 3^D

177C0210 CD 19 BE 82 7D 8B 7D 0F-83 FF 02 72 C8 8B C7 48 rH

177C0220 48 8A 4E 0D F7 E1 03 46-FC 13 56 FE BB 00 07 53 HNFVS

177C0230 B1 04 E8 16 00 5B 72 C8-81 3F 4D 5A 75 A7 81 BF [rMZu

177C0240 00 02 42 4A 75 9F EA 00-02 70 00 50 52 51 91 92 BJupPRQ

177C0250 33 D2 F7 76 18 91 F7 76-18 42 87 CA F7 76 1A 8A 3vvBv

177C0260 F2 8A 56 24 8A E8 D0 CC-D0 CC 0A CC B8 01 02 CD V$

177C0270 13 59 5A 58 72 09 40 75-01 42 03 5E 0B E2 CC C3 YZXruB^

177C0280 03 18 01 27 0D 0A 44 69-73 63 6F 20 69 6E 63 6F Disco inco

177C0290 72 72 65 63 74 6F 20 20-20 FF 0D 0A 45 72 72 6F rrecto Erro

177C02A0 72 20 45 2F 53 20 20 20-20 20 FF 0D 0A 43 61 6D r ES Cam

177C02B0 62 69 65 20 65 6C 20 64-69 73 63 6F 20 79 20 70 bie el disco y p

177C02C0 72 65 73 69 6F 6E 65 20-75 6E 61 20 74 65 63 6C resione una tecl

177C02D0 61 20 20 20 20 0D 0A 00-49 4F 20 20 20 20 20 20 a IO

177C02E0 53 59 53 4D 53 44 4F 53-20 20 20 53 59 53 80 01 SYSMSDOS SYS

177C02F0 00 57 49 4E 42 4F 4F 54-20 53 59 53 00 00 55 AA WINBOOT SYSU

-

-Q

FIN [1] En las primeras versiones de MS-DOS era un modesto programita DEBUGCOM de apenas 16 KB La versioacuten que acompantildea a Windows98 es ya un ejecutable en formato EXE de 21 KB [2] En realidad DEBUG es una utilidad de enorme potencia que requeririacutea todo un libro para ella sola Puede encontrarse una amplia descripcioacuten de esta herramienta en el libro de Paul Somerson PC Magazine DOS Powers Tools [3] Desgraciadamente no hay una convencioacuten estaacutendar sobre la colocacioacuten de los datos en la BIOS de forma que cada fabricante sigue sus propias reglas y es imposible por tanto utilizarla para cualquier tipo de identificacioacuten del sistema [4] En palabras del mencionado Paul Somerson Desgraciadamente debido a que DEBUG es un programa tan increiacuteblemente potente tambieacuten es increiacuteblemente peligroso Hay un dicho que afirma que El software no puede destruir el hardware Desgraciadamente esto no es cierto Ademaacutes de enviar mecanismos sensibles de la unidad de disco a tierra de nadie es posible hacer saltar monitores o transformadores Repito si sigue al pie de la letra las instrucciones y hace caso a todos los avisos todo iraacute bien [5] Recuerde que la imagen de un ejecutable exe cargado en memoria es distinta de su imagen en disco Solo en los ejecutables com la imagen en disco es una imagen exacta de su disposicioacuten en memoria [6] Es evidente que un pequentildeo error de nuacutemero en este paraacutemetro puede acarrear consecuencias nefastas Por ejemplo si cree que estaacute jugando con el disquete e inadvertidamente se dirige al disco duro (relea la nota [4])

Page 19: El Comando DEBUG

0B3B010C E2F5 LOOP 0103 CX=0 Si no salta a 0103 0B3B010E CD20 INT 20 termina el programa En la liacutenea 0103 se puede observar que el valor del registro CX en su parte baja (en CL) se almacena en el registro DL Si se omitiera la liacutenea 0105 entonces cuando se ejecutara la liacutenea 010A solo se imprimiriacutea en pantalla el coacutedigo ASCII del valor que contenga DL (el coacutedigo ASCII de 0Ah que es 10 en decimal es un caraacutecter especial no imprimible) Para conseguir el ldquoefectordquo de que el programa realiza el conteo en decimal se hace un corrimiento de 02F (47 en decimal) Por ejemplo cuando se ejecuta la liacutenea 0105 DL tendriacutea el valor de 39h=57d (02Fh+0Ah=39h=57d) y el coacutedigo ASCII de 57d es el caraacutecter ldquo9rdquo El sentencia LOOP decrementa CX en 1 si CX es diferente a 0 salta a la liacutenea 0103 El proceso se repite y el programa imprime en pantalla 9876543210 Seriacutea interesante que el programa anterior fuera modificado para que la numeracioacuten se imprimiera de la siguiente manera 9 8 7 6 5 4 3 2 1 0

NOTA Como se dijo anteriormente cuando el DEBUG almacena un programa en el disco este archivo se graba en binario esto es en ejecutable Por lo tanto no es necesario cargar el DEBUG para volver a ejecutar nuestro programa sino que se hace de manera directa desde DOS El problema surge cuando al ejecutar nuestro programa el resultado no se puede observar porque el DOS borra la pantalla despueacutes de terminar de ejecutar el programa Para evitar el borrado automaacutetico seraacute necesario agregarle a nuestro programa antes de la INT 20h una instruccioacuten para la lectura de un caraacutecter desde el teclado Para tal efecto utilizaremos la funcioacuten 08 de la INT 21h (un buen truco para que el programa haga una pausa) asiacute el programa esperara hasta que el usuario presiona una tecla permitiendo observar el resultado Ejemplo mov ah08 Int 21 Int 20

Condiciones ciclos y bifurcaciones Estas estructuras o formas de control le dan a la maacutequina un cierto grado de decisioacuten basado en la informacioacuten que recibe La forma maacutes sencilla de comprender este tema es por medio de ejemplos Vamos a crear tres programas que hagan lo mismo desplegar un nuacutemero determinado de veces una cadena de caracteres en la pantalla

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV CX000F veces que se desplegara la cadena 0C1B0128 MOV DX0102 copia cadena al registro DX 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F LOOP 012D si CXgt0 salta a 012D 0C1B0131 INT 20 termina el programa

Por medio del comando e es posible introducir una cadena de caracteres en una determinada localidad de memoria dada como paraacutemetro la cadena se introduce entre comillas le sigue un espacio luego el valor hexadecimal del retorno de carro un espacio el valor de liacutenea nueva y por uacuteltimo el siacutembolo $ que el ensamblador interpreta como final de la cadena La interrupcioacuten 21 utiliza el valor almacenado en el registro AH para ejecutar una determinada funcioacuten en este caso mostrar la cadena en pantalla la cadena que muestra es la que estaacute almacenada en el registro DX La instruccioacuten LOOP decrementa automaacuteticamente el registro CX en uno y si no ha llegado el valor de este registro a cero salta a la posicioacuten de memoria indicada como paraacutemetro lo cual crea un ciclo que se repite el nuacutemero de veces especificado por el valor de CX La interrupcioacuten 20 termina la ejecucioacuten del programa Otra forma de realizar la misma funcioacuten pero sin utilizar el comando LOOP es la siguiente

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV BX000F veces que se desplegara la cadena 0C1B0128 MOV DX0102 copia cadena al registro DX 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F DEC BX decrementa en 1 a BX 0C1B0130 JNZ 012D si BX es diferente a 0 salta a 012D 0C1B0132 INT 20 termina el programa

En este caso se utiliza el registro BX como contador para el programa y por medio de la instruccioacuten DEC se disminuye su valor en 1 La instruccioacuten JNZ verifica si el valor de BX es diferente a 0 esto con base en la bandera NZ en caso afirmativo salta hacia la direccioacuten 012D En caso contrario continuacutea la ejecucioacuten normal del programa y por lo tanto se termina Una uacuteltima variante del programa es utilizando de nuevo a CX como contador pero en lugar de utilizar LOOP utilizaremos decrementos a CX y comparacioacuten de CX a 0

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV DX0102 copia cadena al registro DX 0C1B0128 MOV CX000F veces que se desplegara la cadena 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F DEC CX decrementa en 1 a CX 0C1B0130 JCXZ 0134 si CX es igual a 0 salta a 0134 0C1B0132 JMP 012D salta a la direccioacuten 012D 0C1B0134 INT 20 termina el programa

En este ejemplo se usoacute la instruccioacuten JCXZ para controlar la condicioacuten de salto el significado de tal funcioacuten es salta si CX=0 El tipo de control a utilizar dependeraacute de las necesidades de programacioacuten en determinado momento

Manipulacioacuten de Posiciones de Memoria Con el DEBUG es posible almacenar y recuperar datos numeacutericos en memoria por medio de un programa a traveacutes de los registros del microprocesador Por ejemplo el siguiente programa almacena previamente dos valores numeacutericos en la posicioacuten 0300h y 0400h respectivamente despueacutes el programa los recupera realiza la operacioacuten de suma con esos valores y el resultado lo almacena en la posicioacuten 0500h -a 100 0B1C0100 mov ax0002 ax=2 0B1C0103 mov [0300]ax almacenamos 2 en la direccioacuten 0300h 0B1C0106 mov ax0004 ax=4 0B1C0109 mov [0400]ax almacenamos 4 en la direccioacuten 0400h 0B1C010C mov ax[0300] recuperamos el dato1 en AX 0B1C010F mov bx[0400] recuperamos el dato2 en BX 0B1C0113 add axbx hacemos la operacioacuten de suma en AX 0B1C0115 mov [0500]ax almacenamos el 6 en la direccioacuten 0500h 0B1C0118 int 21 0B1C011A - Un nuacutemero entre corchetes [numero_hex] indica una posicioacuten de memoria y su manejo se hace a traveacutes de registros ya que no es posible almacenar valores numeacutericos de manera directa Ejecutamos el programa -g 118 AX=0006 BX=0004 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=0B1C ES=0B1C SS=0B1C CS=0B1C IP=0118 NV UP EI PL NZ NA PE NC 0B1C0118 CD21 INT 21 - Para ver si el resultado se almaceno en la direccioacuten correcta hacemos

Como se puede observar en la direccioacuten 0B1C0500 se encuentra el 06 y en 0B1C0501 se encuentra el 00 que es el resultado de la operacioacuten 2+4 Perohellip Porque aparece el 06 y despueacutes el 00 pareceriacutea que el resultado fue de 0600 pero no es asiacute lo que sucedes que los datos se almacenan en memoria de la siguiente manera

Como se hizo la operacioacuten AX=AX+BX entonces el resultado es de 16 bits (dos bytes) AX=6 entonces AX=0000 0000 0000 0110 (16 bits) por lo tanto los 8 bits de menor peso de AX son 0000 0110 y deben almacenarse en la direccioacuten 0500 y en la direccioacuten 0501 se almacena 0000 0000

0 0 0 0 0 1 1 0 0500

0 0 0 0 0 0 0 0 0501

x x x x x x x x 0502

x x x x x x x x 0503

x x x x x x x x 0504

x x x x x x x x 0505

Interrupciones Definicioacuten de interrupcioacuten

Una interrupcioacuten es una instruccioacuten que detiene la ejecucioacuten de un programa para permitir el uso del microprocesador en un proceso prioritario Una vez concluido este uacuteltimo proceso se devuelve el control a la aplicacioacuten anterior

Por ejemplo cuando estamos trabajando con un procesador de palabras y en ese momento llega un aviso de uno de los puertos de comunicaciones se detiene temporalmente la aplicacioacuten que estaacutebamos utilizando para permitir el uso del microprocesador al manejo de la informacioacuten que estaacute llegando en ese momento Una vez terminada la transferencia de informacioacuten se reanudan las funciones normales del procesador de palabras Las interrupciones ocurren muy seguido sencillamente la interrupcioacuten que actualiza la hora del diacutea ocurre aproximadamente 18 veces por segundo Para lograr administrar todas estas interrupciones la computadora cuenta con un espacio de memoria llamado memoria baja donde se almacenan las direcciones de cierta localidad de memoria donde se encuentran un juego de instrucciones que el microprocesador ejecutaraacute para despueacutes regresar a la aplicacioacuten que estaba en proceso En los programas anteriores hicimos uso de la interrupcioacuten nuacutemero 20H para terminar la ejecucioacuten de nuestros programas y en otros ejemplos utilizamos otra interrupcioacuten para mostrar informacioacuten en pantalla (INT 21h) Utilizando DEBUG tecleamos

- a100 2C1B0100 JMP 011D 2C1B0102 [ENTER] - E 102 Hola como estas 0D 0A $ - A011D 2C1B011D MOV DX0102 2C1B0120 MOV AH09 2C1B0122 INT 21 2C1B0123 INT 20

Orden

creciente

de la

memoria

En este programa la interrupcioacuten 21h manda al monitor la cadena localizada en la direccioacuten a la que apunta el registro DX El valor que se le da a AH determina cual de las opciones de la interrupcioacuten 21h seraacute utilizada ya que esta interrupcioacuten cuenta con varias opciones El manejo directo de interrupciones es una de las partes maacutes fuertes del lenguaje ensamblador ya que con ellas es posible controlar eficientemente todos los dispositivos internos y externos de una computadora gracias al completo control que se tiene sobre operaciones de entrada y salida Maacutes del DEBUG Una caracteriacutestica poco conocida es que DEBUG puede aceptar entradas desde un archivo Script que puede ser un simple archivo de texto ASCII en el que cada comando esteacute separado del anterior por un INTRO Despueacutes del uacuteltimo que debe ser una Q para salir de DEBUG es conveniente dejar una liacutenea en blanco pulsando INTRO dos veces Las liacuteneas pueden contener comentarios Cualquier cosa a partir del caracter punto y coma () hasta el final de la liacutenea seraacute ignorado esto es un comentario D aquiacute se mostraraacute algo Suponiendo que tengamos un archivo Script de nombre Ordenestxt puede ser utilizado como entrada para DEBUG mediante un comando de redireccioacuten en la siguiente forma DEBUG lt ordenestxt Tambieacuten puede conseguirse que el programa redireccione la salida hacia un archivo que puede ser inspeccionado maacutes 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 podriacutea obtenerse un archivo Resulttxt con el siguiente comando DEBUG lt ordenestxt gt Resulttxt Errores Cuando DEBUG no sabe interpretar un comando muestra un mensaje de error y un indicador ^ debajo del sitio del comando donde estaacute el error Entradas y Salidas DEBUG asume que los datos numeacutericos proporcionados son hexadecimales y cuando se trate de direcciones de memoria deben introducirse en forma segmentada A su vez los resultados son mostrados tambieacuten 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

Cada fila muestra 16 posiciones de memoria a partir de la posicioacuten sentildealada por las columnas de la izquierda que las muestran como segmentodesplazamiento El bloque central muestra el contenido hexadecimal de cada byte mientras que el bloque derecho contiene la representacioacuten ASCII Por ejemplo la 3ra fila muestra el contenido de las posiciones 0B770120 a 0B77012F (ambas inclusive) Sus tres uacuteltimos bytes contienen respectivamente los caracteres r 9 y 2 que corresponden a las cantidades 72h 39h y 32h del bloque central Que como sabemos equivalen a los decimales 114 57 y 50 que son precisamente los valores ASCII de los caracteres ldquorrdquo ldquo9rdquo y ldquo2rdquo anteriormente mencionados

Nota Por razoacuten de que eacuteste tipo de salida pueda ser listado a impresora el bloque derecho no contiene en realidad la representacioacuten ASCII de todos los caracteres (algunos ni siquiera tienen una representacioacuten imprimible) En realidad solo se muestran los caracteres imprimibles del primer bloque (US-ASCII) El resto estaacute 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 caraacutecter imprimible Esto no significa que dichas posiciones representen efectivamente tales valores para la aplicacioacuten que las utiliza Por ejemplo puede que en realidad las dos posiciones de memoria mencionadas (dos octetos o bytes) en vez de los caracteres ldquo5rdquo y ldquoardquo representen una palabra de 16 bits en formato Little Endian que a su vez representan una cantidad entera (un nuacutemero) Comandos Aunque su descripcioacuten completa llenariacutea todo un capiacutetulo a continuacioacuten comentamos algunas de las opciones maacutes interesantes relativas a inspeccioacuten del coacutedigo y de contenidos de memoria La opcioacuten D (Dump) permite obtener un volcado del contenido de la memoria (de DEBUG) La sintaxis acepta dos formas D [direccioacuten-inicial] [L posiciones-desde-direccioacuten-inicial ] D [direccioacuten-inicial][direccioacuten-final] Naturalmente para que exista algo en el buacutefer de memoria (al principio quizaacutes solo contiene basura) es preciso indicarle que lea algo Este algo puede ser un rango de direcciones de memoria RAM una direccioacuten absoluta de disco (sector) un archivo o el contenido de los registros del procesador Para empezar puede indicaacutersele que cargue un archivo xxxxyz que tenemos en el directorio actual o en el PATH cuyo contenido queremos ver Cgt DEBUG xxxxyz -D aquiacute se obtendriacutea una salida anaacuteloga a la comentada

Hemos visto un ejemplo al tratar de los servicios de interrupciones del PC aquiacute mostraremos otro Sabemos que el punto de inicio de la BIOS es la direccioacuten F000FFF0 y que desde eacutesta posicioacuten hasta el final de la memoria DOS hay 16 bytes Puede obtenerse un volcado de estas posiciones con el siguiente comando -D F000FFF0 La salida en un equipo puede ser F000FFF0 CD 19 E0 00 F0 30 36 2F-33 30 2F 39 37 00 FC 38 0630978 En este caso el comando solo muestra una liacutenea porque ha alcanzado el final de la memoria Puede verse que la fecha de la BIOS del sistema ocupa las uacuteltimas posiciones Si se ordena el volcado de una direccioacuten suficientemente alejada del final de la memoria sin indicar ninguacuten nuacutemero de posiciones por defecto se toma el valor 128 (8 filas de 16 posiciones) Si desea una cantidad distinta hay que antildeadir una L (Long) y el nuacutemero de posiciones hasta un maacuteximo de 64 KB (FFFF) Todos los nuacutemeros deben ser expresados en hexadecimal Por consiguiente los dos comandos que siguen son equivalentes (recuerde que 80 es el equivalente hexadecimal de 128) D FE000000 D FE000000 L 80 He aquiacute el resultado

Sabemos que esta zona corresponde al aacuterea de la BIOS del Sistema Otra opcioacuten muy interesante nos permite buscar determinados contenidos a traveacutes de la memoria utilizando el prefijo S (Search) Existen dos sintaxis alternativas S direccioacuten-de-inicio L longitud-a-explorar contenido-a-buscar S direccioacuten-de-inicio direccioacuten-final L contenido-a-buscar El contenido debe ser proporcionado en hexadecimal (tal como apareceriacutea en la columna central del ejemplo anterior) o entre comillas si es un texto ASCII Por ejemplo en un equipo IBM deseo ver algunas caracteriacutesticas de la BIOS Seacute que estos datos se alojan a partir de la posicioacuten F0000000 hasta el final de la memoria Es decir una longitud de 64 Kbytes (FFFF) a partir de la posicioacuten de inicio y que seguramente los datos buscados estaraacuten cerca de la identificacioacuten de la propia BIOS (la cadena IBM) Por lo que se utiliza la siguiente sintaxis [3] -s f0000000 L ffff IBM

y se obtiene la siguiente salida F000E00E F000E111 con las direcciones donde se ha encontrado la ocurrencia buscada A continuacioacuten puedo explorar las proximidades de cada posicioacuten Por ejemplo para la primera -D f000e000

Si lo que se busca estaacute en un archivo primero hay que cargarlo Lo que se puede hacer de dos formas en la propia invocacioacuten de DEBUG o mediante los comandos N y L Por ejemplo si queremos inspeccionar el contenido del archivo morecom podemos utilizar dos formas CWINDOWSgtDEBUG cwindowscommandmorecom CWINDOWSgtDEBUG - N cwindowscommandmorecom - L La sintaxis para el prefijo N es N [path-name]nombre-de-archivo En ambos casos el contenido del archivo seraacute cargado en memoria y podraacute ser utilizado Atencioacuten despueacutes de la orden L (Load) DEBUG le avisaraacute si no encuentra el archivo pero seguiraacute su funcionamiento En tal caso simplemente piensa que N sentildeala el nombre de un nuevo archivo que crearaacute con el contenido de la memoria -de DEBUG- cuando posteriormente seleccione la opcioacuten escribir W (Write)[4]

Nota Como ya habraacute deducido DEBUG permite leer un archivo realizar modificaciones en eacutel (con la opcioacuten E) y escribir el archivo modificado bajo otro nombre con NW

A continuacioacuten podemos comprobar el tamantildeo del archivo cargado Para ello usamos la opcioacuten 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 17A70100 E8CD0F CALL 10D0 -

Aquiacute nos interesa especialmente el contenido del registro CX cuyo valor 2917h (1519d) en este caso sentildeala el tamantildeo del archivo en bytes Tambieacuten podiacuteamos haber utilizado directamente el comando R CX que nos proporciona el valor de dicho registro -R CX CX 2917 -

Nota A continuacioacuten del valor correspondiente DEBUG muestra dos puntos () sentildealando que puede cambiar el valor del registro introduciendo un nuevo nuacutemero Pulse INTRO para dejar las cosas como estaacuten y volver al prompt (-) de DEBUG

Al llegar a este punto es importante sentildealar que a excepcioacuten de los archivos exe DEBUG carga los archivos a partir de la direccioacuten 100h (256d) de su memoria De forma que el primer octeto del archivo se carga en la direccioacuten 100 el segundo en 101 etc En nuestro caso el archivo se extenderaacute desde la posicioacuten 100h hasta 2A17h (100h + 2917h) A continuacioacuten para buscar la cadena Microsoft en el archivo utilizamos cualquiera de los siguientes comandos - S 100 L 2917 Microsoft - S 100 2a17 Microsoft El primer comando sentildeala el punto de inicio y el tamantildeo de la zona a buscar el segundo utiliza los puntos inicial y final de la exploracioacuten Con ambos se obtiene la misma respuesta 17A71083 17A710B2

Truco Debido a la forma especial en que se cargan los ejecutables exe si quiere inspeccionar la forma nativa de uno de estos archivos (como es su imagen en el disco) debe hacer una copia del archivo renombrarlo con cualquier otra terminacioacuten (o sin ella) y cargar esta copia En caso contrario DEBUG se prepararaacute para funcionar como un verdadero depurador de tiempo de ejecucioacuten (run-time) para lo que cargaraacute el archivo y lo acomodaraacute en memoria de forma que pueda ejecutarse [5]

Como ejercicio compruebe las distintas longitudes y aspecto (especialmente al principio) de un mismo archivo exe cargaacutendolo con DEBUG de las dos formas (busque en su sistema un exe lo maacutes pequentildeo posible) Ademaacutes de la capacidad de leer archivos antes mencionada quizaacutes una de las opciones maacutes interesantes (y peligrosas) de DEBUG es la posibilidad de leerescribir el contenido de disco a bajo nivel mediante los prefijos L (Load) y W (Write) Se utiliza la siguiente sintaxis L [Direccioacuten] [Unidad] [Primer_sector] [Nuacutemero] W [Direccioacuten] [Unidad] [Primer_sector] [Nuacutemero] El significado de los paraacutemetros es como sigue

Direccioacuten Posicioacuten de la memoria de DEBUG a partir de la cual se instalaraacuten los datos leiacutedos del disco o se tomaraacuten para el proceso de escritura (aquiacute se utiliza generalmente el valor 100h)

Unidad Valor numeacuterico que indica la loacutegica a utilizar 0 = A 1 = B 2 = C 3 = D etc [6]

Primer sector A partir del que se realizaraacute la lectura o se comenzaraacute a escribir

Nuacutemero Nuacutemero de sectores que se desea cargarescribir Como DEBUG no puede leerescribir maacutes de 64 Kbytes (2

16 = 65536) y los sectores de disco son de 512 bytes

el maacuteximo nuacutemero de sectores es 128 (80h) Asiacute pues el valor maacuteximo aquiacute es 80 Ejemplo Para obtener el contenido del sector de arranque (Master boot sector MBR) de un disquete en A utilizaremos el comando CWINDOWSgtDEBUG - L 100 0 0 1 - D 100 L 200 Como el resultado no cabe en una pantalla ingeniaremos un procedimiento para conservarlo en un archivo (maacutes adelante nos serviraacute para otro propoacutesito) Para ello creamos un archivo scripttxt con el siguiente contenido (dos INTRO despueacutes de la Q) L 100 0 0 1 D 100 L 200 Q A continuacioacuten invocamos DEBUG con el comando CWINDOWSgtDEBUG lt Dbuzonscripttxt gt Dbuzonresultadtxt Despueacutes de un breve parpadeo del disco y del disquete vuelve el prompt del DOS La operacioacuten ha concluido y en el directorio correspondiente de la unidad D tenemos el archivo resultadtxt con el volcado del sector de arranque del disquete ademaacutes de los ecos de los comandos introducidos (los hemos mantenido para orientacioacuten del lector) Otra forma de poder visualizar el contenido del Sector de Arranque del disco es utilizando el DEBUG Por ejemplo dentro del DEBUG tecleamos lo siguiente -L 100 0 0 1

-D 100 L 200

177C0100 EB 3E 90 2B 79 73 57 29-49 48 43 00 02 01 01 00 gt+ysW)IHC

177C0110 02 E0 00 40 0B F0 09 00-12 00 02 00 00 00 00 00

177C0120 00 00 00 00 00 00 29 5D-3B DD 10 4E 4F 20 4E 41 )]NO NA

177C0130 4D 45 20 20 20 20 46 41-54 31 32 20 20 20 F1 7D ME FAT12

177C0140 FA 33 C9 8E D1 BC FC 7B-16 07 BD 78 00 C5 76 00 3xv

177C0150 1E 56 16 55 BF 22 05 89-7E 00 89 4E 02 B1 0B FC VU~N

177C0160 F3 A4 06 1F BD 00 7C C6-45 FE 0F 8B 46 18 88 45 |EFE

177C0170 F9 FB 38 66 24 7C 04 CD-13 72 3C 8A 46 10 98 F7 8f$|rltF

177C0180 66 16 03 46 1C 13 56 1E-03 46 0E 13 D1 50 52 89 fFVFPR

177C0190 46 FC 89 56 FE B8 20 00-8B 76 11 F7 E6 8B 5E 0B FV v^

177C01A0 03 C3 48 F7 F3 01 46 FC-11 4E FE 5A 58 BB 00 07 HFNZX

177C01B0 8B FB B1 01 E8 94 00 72-47 38 2D 74 19 B1 0B 56 rG8-tV

177C01C0 8B 76 3E F3 A6 5E 74 4A-4E 74 0B 03 F9 83 C7 15 vgt^tJNt

177C01D0 3B FB 72 E5 EB D7 2B C9-B8 D8 7D 87 46 3E 3C D8 r+Fgtlt

177C01E0 75 99 BE 80 7D AC 98 03-F0 AC 84 C0 74 17 3C FF utlt

177C01F0 74 09 B4 0E BB 07 00 CD-10 EB EE BE 83 7D EB E5 t

177C0200 BE 81 7D EB E0 33 C0 CD-16 5E 1F 8F 04 8F 44 02 3^D

177C0210 CD 19 BE 82 7D 8B 7D 0F-83 FF 02 72 C8 8B C7 48 rH

177C0220 48 8A 4E 0D F7 E1 03 46-FC 13 56 FE BB 00 07 53 HNFVS

177C0230 B1 04 E8 16 00 5B 72 C8-81 3F 4D 5A 75 A7 81 BF [rMZu

177C0240 00 02 42 4A 75 9F EA 00-02 70 00 50 52 51 91 92 BJupPRQ

177C0250 33 D2 F7 76 18 91 F7 76-18 42 87 CA F7 76 1A 8A 3vvBv

177C0260 F2 8A 56 24 8A E8 D0 CC-D0 CC 0A CC B8 01 02 CD V$

177C0270 13 59 5A 58 72 09 40 75-01 42 03 5E 0B E2 CC C3 YZXruB^

177C0280 03 18 01 27 0D 0A 44 69-73 63 6F 20 69 6E 63 6F Disco inco

177C0290 72 72 65 63 74 6F 20 20-20 FF 0D 0A 45 72 72 6F rrecto Erro

177C02A0 72 20 45 2F 53 20 20 20-20 20 FF 0D 0A 43 61 6D r ES Cam

177C02B0 62 69 65 20 65 6C 20 64-69 73 63 6F 20 79 20 70 bie el disco y p

177C02C0 72 65 73 69 6F 6E 65 20-75 6E 61 20 74 65 63 6C resione una tecl

177C02D0 61 20 20 20 20 0D 0A 00-49 4F 20 20 20 20 20 20 a IO

177C02E0 53 59 53 4D 53 44 4F 53-20 20 20 53 59 53 80 01 SYSMSDOS SYS

177C02F0 00 57 49 4E 42 4F 4F 54-20 53 59 53 00 00 55 AA WINBOOT SYSU

-

-Q

FIN [1] En las primeras versiones de MS-DOS era un modesto programita DEBUGCOM de apenas 16 KB La versioacuten que acompantildea a Windows98 es ya un ejecutable en formato EXE de 21 KB [2] En realidad DEBUG es una utilidad de enorme potencia que requeririacutea todo un libro para ella sola Puede encontrarse una amplia descripcioacuten de esta herramienta en el libro de Paul Somerson PC Magazine DOS Powers Tools [3] Desgraciadamente no hay una convencioacuten estaacutendar sobre la colocacioacuten de los datos en la BIOS de forma que cada fabricante sigue sus propias reglas y es imposible por tanto utilizarla para cualquier tipo de identificacioacuten del sistema [4] En palabras del mencionado Paul Somerson Desgraciadamente debido a que DEBUG es un programa tan increiacuteblemente potente tambieacuten es increiacuteblemente peligroso Hay un dicho que afirma que El software no puede destruir el hardware Desgraciadamente esto no es cierto Ademaacutes de enviar mecanismos sensibles de la unidad de disco a tierra de nadie es posible hacer saltar monitores o transformadores Repito si sigue al pie de la letra las instrucciones y hace caso a todos los avisos todo iraacute bien [5] Recuerde que la imagen de un ejecutable exe cargado en memoria es distinta de su imagen en disco Solo en los ejecutables com la imagen en disco es una imagen exacta de su disposicioacuten en memoria [6] Es evidente que un pequentildeo error de nuacutemero en este paraacutemetro puede acarrear consecuencias nefastas Por ejemplo si cree que estaacute jugando con el disquete e inadvertidamente se dirige al disco duro (relea la nota [4])

Page 20: El Comando DEBUG

Por medio del comando e es posible introducir una cadena de caracteres en una determinada localidad de memoria dada como paraacutemetro la cadena se introduce entre comillas le sigue un espacio luego el valor hexadecimal del retorno de carro un espacio el valor de liacutenea nueva y por uacuteltimo el siacutembolo $ que el ensamblador interpreta como final de la cadena La interrupcioacuten 21 utiliza el valor almacenado en el registro AH para ejecutar una determinada funcioacuten en este caso mostrar la cadena en pantalla la cadena que muestra es la que estaacute almacenada en el registro DX La instruccioacuten LOOP decrementa automaacuteticamente el registro CX en uno y si no ha llegado el valor de este registro a cero salta a la posicioacuten de memoria indicada como paraacutemetro lo cual crea un ciclo que se repite el nuacutemero de veces especificado por el valor de CX La interrupcioacuten 20 termina la ejecucioacuten del programa Otra forma de realizar la misma funcioacuten pero sin utilizar el comando LOOP es la siguiente

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV BX000F veces que se desplegara la cadena 0C1B0128 MOV DX0102 copia cadena al registro DX 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F DEC BX decrementa en 1 a BX 0C1B0130 JNZ 012D si BX es diferente a 0 salta a 012D 0C1B0132 INT 20 termina el programa

En este caso se utiliza el registro BX como contador para el programa y por medio de la instruccioacuten DEC se disminuye su valor en 1 La instruccioacuten JNZ verifica si el valor de BX es diferente a 0 esto con base en la bandera NZ en caso afirmativo salta hacia la direccioacuten 012D En caso contrario continuacutea la ejecucioacuten normal del programa y por lo tanto se termina Una uacuteltima variante del programa es utilizando de nuevo a CX como contador pero en lugar de utilizar LOOP utilizaremos decrementos a CX y comparacioacuten de CX a 0

- a100 0C1B0100 jmp 125 salta a la direccioacuten 125H 0C1B0102 [Enter] - e 102 Cadena a visualizar 15 veces 0d 0a $ - a125 0C1B0125 MOV DX0102 copia cadena al registro DX 0C1B0128 MOV CX000F veces que se desplegara la cadena 0C1B012B MOV AH09 copia valor 09 al registro AH 0C1B012D INT 21 despliega cadena 0C1B012F DEC CX decrementa en 1 a CX 0C1B0130 JCXZ 0134 si CX es igual a 0 salta a 0134 0C1B0132 JMP 012D salta a la direccioacuten 012D 0C1B0134 INT 20 termina el programa

En este ejemplo se usoacute la instruccioacuten JCXZ para controlar la condicioacuten de salto el significado de tal funcioacuten es salta si CX=0 El tipo de control a utilizar dependeraacute de las necesidades de programacioacuten en determinado momento

Manipulacioacuten de Posiciones de Memoria Con el DEBUG es posible almacenar y recuperar datos numeacutericos en memoria por medio de un programa a traveacutes de los registros del microprocesador Por ejemplo el siguiente programa almacena previamente dos valores numeacutericos en la posicioacuten 0300h y 0400h respectivamente despueacutes el programa los recupera realiza la operacioacuten de suma con esos valores y el resultado lo almacena en la posicioacuten 0500h -a 100 0B1C0100 mov ax0002 ax=2 0B1C0103 mov [0300]ax almacenamos 2 en la direccioacuten 0300h 0B1C0106 mov ax0004 ax=4 0B1C0109 mov [0400]ax almacenamos 4 en la direccioacuten 0400h 0B1C010C mov ax[0300] recuperamos el dato1 en AX 0B1C010F mov bx[0400] recuperamos el dato2 en BX 0B1C0113 add axbx hacemos la operacioacuten de suma en AX 0B1C0115 mov [0500]ax almacenamos el 6 en la direccioacuten 0500h 0B1C0118 int 21 0B1C011A - Un nuacutemero entre corchetes [numero_hex] indica una posicioacuten de memoria y su manejo se hace a traveacutes de registros ya que no es posible almacenar valores numeacutericos de manera directa Ejecutamos el programa -g 118 AX=0006 BX=0004 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=0B1C ES=0B1C SS=0B1C CS=0B1C IP=0118 NV UP EI PL NZ NA PE NC 0B1C0118 CD21 INT 21 - Para ver si el resultado se almaceno en la direccioacuten correcta hacemos

Como se puede observar en la direccioacuten 0B1C0500 se encuentra el 06 y en 0B1C0501 se encuentra el 00 que es el resultado de la operacioacuten 2+4 Perohellip Porque aparece el 06 y despueacutes el 00 pareceriacutea que el resultado fue de 0600 pero no es asiacute lo que sucedes que los datos se almacenan en memoria de la siguiente manera

Como se hizo la operacioacuten AX=AX+BX entonces el resultado es de 16 bits (dos bytes) AX=6 entonces AX=0000 0000 0000 0110 (16 bits) por lo tanto los 8 bits de menor peso de AX son 0000 0110 y deben almacenarse en la direccioacuten 0500 y en la direccioacuten 0501 se almacena 0000 0000

0 0 0 0 0 1 1 0 0500

0 0 0 0 0 0 0 0 0501

x x x x x x x x 0502

x x x x x x x x 0503

x x x x x x x x 0504

x x x x x x x x 0505

Interrupciones Definicioacuten de interrupcioacuten

Una interrupcioacuten es una instruccioacuten que detiene la ejecucioacuten de un programa para permitir el uso del microprocesador en un proceso prioritario Una vez concluido este uacuteltimo proceso se devuelve el control a la aplicacioacuten anterior

Por ejemplo cuando estamos trabajando con un procesador de palabras y en ese momento llega un aviso de uno de los puertos de comunicaciones se detiene temporalmente la aplicacioacuten que estaacutebamos utilizando para permitir el uso del microprocesador al manejo de la informacioacuten que estaacute llegando en ese momento Una vez terminada la transferencia de informacioacuten se reanudan las funciones normales del procesador de palabras Las interrupciones ocurren muy seguido sencillamente la interrupcioacuten que actualiza la hora del diacutea ocurre aproximadamente 18 veces por segundo Para lograr administrar todas estas interrupciones la computadora cuenta con un espacio de memoria llamado memoria baja donde se almacenan las direcciones de cierta localidad de memoria donde se encuentran un juego de instrucciones que el microprocesador ejecutaraacute para despueacutes regresar a la aplicacioacuten que estaba en proceso En los programas anteriores hicimos uso de la interrupcioacuten nuacutemero 20H para terminar la ejecucioacuten de nuestros programas y en otros ejemplos utilizamos otra interrupcioacuten para mostrar informacioacuten en pantalla (INT 21h) Utilizando DEBUG tecleamos

- a100 2C1B0100 JMP 011D 2C1B0102 [ENTER] - E 102 Hola como estas 0D 0A $ - A011D 2C1B011D MOV DX0102 2C1B0120 MOV AH09 2C1B0122 INT 21 2C1B0123 INT 20

Orden

creciente

de la

memoria

En este programa la interrupcioacuten 21h manda al monitor la cadena localizada en la direccioacuten a la que apunta el registro DX El valor que se le da a AH determina cual de las opciones de la interrupcioacuten 21h seraacute utilizada ya que esta interrupcioacuten cuenta con varias opciones El manejo directo de interrupciones es una de las partes maacutes fuertes del lenguaje ensamblador ya que con ellas es posible controlar eficientemente todos los dispositivos internos y externos de una computadora gracias al completo control que se tiene sobre operaciones de entrada y salida Maacutes del DEBUG Una caracteriacutestica poco conocida es que DEBUG puede aceptar entradas desde un archivo Script que puede ser un simple archivo de texto ASCII en el que cada comando esteacute separado del anterior por un INTRO Despueacutes del uacuteltimo que debe ser una Q para salir de DEBUG es conveniente dejar una liacutenea en blanco pulsando INTRO dos veces Las liacuteneas pueden contener comentarios Cualquier cosa a partir del caracter punto y coma () hasta el final de la liacutenea seraacute ignorado esto es un comentario D aquiacute se mostraraacute algo Suponiendo que tengamos un archivo Script de nombre Ordenestxt puede ser utilizado como entrada para DEBUG mediante un comando de redireccioacuten en la siguiente forma DEBUG lt ordenestxt Tambieacuten puede conseguirse que el programa redireccione la salida hacia un archivo que puede ser inspeccionado maacutes 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 podriacutea obtenerse un archivo Resulttxt con el siguiente comando DEBUG lt ordenestxt gt Resulttxt Errores Cuando DEBUG no sabe interpretar un comando muestra un mensaje de error y un indicador ^ debajo del sitio del comando donde estaacute el error Entradas y Salidas DEBUG asume que los datos numeacutericos proporcionados son hexadecimales y cuando se trate de direcciones de memoria deben introducirse en forma segmentada A su vez los resultados son mostrados tambieacuten 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

Cada fila muestra 16 posiciones de memoria a partir de la posicioacuten sentildealada por las columnas de la izquierda que las muestran como segmentodesplazamiento El bloque central muestra el contenido hexadecimal de cada byte mientras que el bloque derecho contiene la representacioacuten ASCII Por ejemplo la 3ra fila muestra el contenido de las posiciones 0B770120 a 0B77012F (ambas inclusive) Sus tres uacuteltimos bytes contienen respectivamente los caracteres r 9 y 2 que corresponden a las cantidades 72h 39h y 32h del bloque central Que como sabemos equivalen a los decimales 114 57 y 50 que son precisamente los valores ASCII de los caracteres ldquorrdquo ldquo9rdquo y ldquo2rdquo anteriormente mencionados

Nota Por razoacuten de que eacuteste tipo de salida pueda ser listado a impresora el bloque derecho no contiene en realidad la representacioacuten ASCII de todos los caracteres (algunos ni siquiera tienen una representacioacuten imprimible) En realidad solo se muestran los caracteres imprimibles del primer bloque (US-ASCII) El resto estaacute 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 caraacutecter imprimible Esto no significa que dichas posiciones representen efectivamente tales valores para la aplicacioacuten que las utiliza Por ejemplo puede que en realidad las dos posiciones de memoria mencionadas (dos octetos o bytes) en vez de los caracteres ldquo5rdquo y ldquoardquo representen una palabra de 16 bits en formato Little Endian que a su vez representan una cantidad entera (un nuacutemero) Comandos Aunque su descripcioacuten completa llenariacutea todo un capiacutetulo a continuacioacuten comentamos algunas de las opciones maacutes interesantes relativas a inspeccioacuten del coacutedigo y de contenidos de memoria La opcioacuten D (Dump) permite obtener un volcado del contenido de la memoria (de DEBUG) La sintaxis acepta dos formas D [direccioacuten-inicial] [L posiciones-desde-direccioacuten-inicial ] D [direccioacuten-inicial][direccioacuten-final] Naturalmente para que exista algo en el buacutefer de memoria (al principio quizaacutes solo contiene basura) es preciso indicarle que lea algo Este algo puede ser un rango de direcciones de memoria RAM una direccioacuten absoluta de disco (sector) un archivo o el contenido de los registros del procesador Para empezar puede indicaacutersele que cargue un archivo xxxxyz que tenemos en el directorio actual o en el PATH cuyo contenido queremos ver Cgt DEBUG xxxxyz -D aquiacute se obtendriacutea una salida anaacuteloga a la comentada

Hemos visto un ejemplo al tratar de los servicios de interrupciones del PC aquiacute mostraremos otro Sabemos que el punto de inicio de la BIOS es la direccioacuten F000FFF0 y que desde eacutesta posicioacuten hasta el final de la memoria DOS hay 16 bytes Puede obtenerse un volcado de estas posiciones con el siguiente comando -D F000FFF0 La salida en un equipo puede ser F000FFF0 CD 19 E0 00 F0 30 36 2F-33 30 2F 39 37 00 FC 38 0630978 En este caso el comando solo muestra una liacutenea porque ha alcanzado el final de la memoria Puede verse que la fecha de la BIOS del sistema ocupa las uacuteltimas posiciones Si se ordena el volcado de una direccioacuten suficientemente alejada del final de la memoria sin indicar ninguacuten nuacutemero de posiciones por defecto se toma el valor 128 (8 filas de 16 posiciones) Si desea una cantidad distinta hay que antildeadir una L (Long) y el nuacutemero de posiciones hasta un maacuteximo de 64 KB (FFFF) Todos los nuacutemeros deben ser expresados en hexadecimal Por consiguiente los dos comandos que siguen son equivalentes (recuerde que 80 es el equivalente hexadecimal de 128) D FE000000 D FE000000 L 80 He aquiacute el resultado

Sabemos que esta zona corresponde al aacuterea de la BIOS del Sistema Otra opcioacuten muy interesante nos permite buscar determinados contenidos a traveacutes de la memoria utilizando el prefijo S (Search) Existen dos sintaxis alternativas S direccioacuten-de-inicio L longitud-a-explorar contenido-a-buscar S direccioacuten-de-inicio direccioacuten-final L contenido-a-buscar El contenido debe ser proporcionado en hexadecimal (tal como apareceriacutea en la columna central del ejemplo anterior) o entre comillas si es un texto ASCII Por ejemplo en un equipo IBM deseo ver algunas caracteriacutesticas de la BIOS Seacute que estos datos se alojan a partir de la posicioacuten F0000000 hasta el final de la memoria Es decir una longitud de 64 Kbytes (FFFF) a partir de la posicioacuten de inicio y que seguramente los datos buscados estaraacuten cerca de la identificacioacuten de la propia BIOS (la cadena IBM) Por lo que se utiliza la siguiente sintaxis [3] -s f0000000 L ffff IBM

y se obtiene la siguiente salida F000E00E F000E111 con las direcciones donde se ha encontrado la ocurrencia buscada A continuacioacuten puedo explorar las proximidades de cada posicioacuten Por ejemplo para la primera -D f000e000

Si lo que se busca estaacute en un archivo primero hay que cargarlo Lo que se puede hacer de dos formas en la propia invocacioacuten de DEBUG o mediante los comandos N y L Por ejemplo si queremos inspeccionar el contenido del archivo morecom podemos utilizar dos formas CWINDOWSgtDEBUG cwindowscommandmorecom CWINDOWSgtDEBUG - N cwindowscommandmorecom - L La sintaxis para el prefijo N es N [path-name]nombre-de-archivo En ambos casos el contenido del archivo seraacute cargado en memoria y podraacute ser utilizado Atencioacuten despueacutes de la orden L (Load) DEBUG le avisaraacute si no encuentra el archivo pero seguiraacute su funcionamiento En tal caso simplemente piensa que N sentildeala el nombre de un nuevo archivo que crearaacute con el contenido de la memoria -de DEBUG- cuando posteriormente seleccione la opcioacuten escribir W (Write)[4]

Nota Como ya habraacute deducido DEBUG permite leer un archivo realizar modificaciones en eacutel (con la opcioacuten E) y escribir el archivo modificado bajo otro nombre con NW

A continuacioacuten podemos comprobar el tamantildeo del archivo cargado Para ello usamos la opcioacuten 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 17A70100 E8CD0F CALL 10D0 -

Aquiacute nos interesa especialmente el contenido del registro CX cuyo valor 2917h (1519d) en este caso sentildeala el tamantildeo del archivo en bytes Tambieacuten podiacuteamos haber utilizado directamente el comando R CX que nos proporciona el valor de dicho registro -R CX CX 2917 -

Nota A continuacioacuten del valor correspondiente DEBUG muestra dos puntos () sentildealando que puede cambiar el valor del registro introduciendo un nuevo nuacutemero Pulse INTRO para dejar las cosas como estaacuten y volver al prompt (-) de DEBUG

Al llegar a este punto es importante sentildealar que a excepcioacuten de los archivos exe DEBUG carga los archivos a partir de la direccioacuten 100h (256d) de su memoria De forma que el primer octeto del archivo se carga en la direccioacuten 100 el segundo en 101 etc En nuestro caso el archivo se extenderaacute desde la posicioacuten 100h hasta 2A17h (100h + 2917h) A continuacioacuten para buscar la cadena Microsoft en el archivo utilizamos cualquiera de los siguientes comandos - S 100 L 2917 Microsoft - S 100 2a17 Microsoft El primer comando sentildeala el punto de inicio y el tamantildeo de la zona a buscar el segundo utiliza los puntos inicial y final de la exploracioacuten Con ambos se obtiene la misma respuesta 17A71083 17A710B2

Truco Debido a la forma especial en que se cargan los ejecutables exe si quiere inspeccionar la forma nativa de uno de estos archivos (como es su imagen en el disco) debe hacer una copia del archivo renombrarlo con cualquier otra terminacioacuten (o sin ella) y cargar esta copia En caso contrario DEBUG se prepararaacute para funcionar como un verdadero depurador de tiempo de ejecucioacuten (run-time) para lo que cargaraacute el archivo y lo acomodaraacute en memoria de forma que pueda ejecutarse [5]

Como ejercicio compruebe las distintas longitudes y aspecto (especialmente al principio) de un mismo archivo exe cargaacutendolo con DEBUG de las dos formas (busque en su sistema un exe lo maacutes pequentildeo posible) Ademaacutes de la capacidad de leer archivos antes mencionada quizaacutes una de las opciones maacutes interesantes (y peligrosas) de DEBUG es la posibilidad de leerescribir el contenido de disco a bajo nivel mediante los prefijos L (Load) y W (Write) Se utiliza la siguiente sintaxis L [Direccioacuten] [Unidad] [Primer_sector] [Nuacutemero] W [Direccioacuten] [Unidad] [Primer_sector] [Nuacutemero] El significado de los paraacutemetros es como sigue

Direccioacuten Posicioacuten de la memoria de DEBUG a partir de la cual se instalaraacuten los datos leiacutedos del disco o se tomaraacuten para el proceso de escritura (aquiacute se utiliza generalmente el valor 100h)

Unidad Valor numeacuterico que indica la loacutegica a utilizar 0 = A 1 = B 2 = C 3 = D etc [6]

Primer sector A partir del que se realizaraacute la lectura o se comenzaraacute a escribir

Nuacutemero Nuacutemero de sectores que se desea cargarescribir Como DEBUG no puede leerescribir maacutes de 64 Kbytes (2

16 = 65536) y los sectores de disco son de 512 bytes

el maacuteximo nuacutemero de sectores es 128 (80h) Asiacute pues el valor maacuteximo aquiacute es 80 Ejemplo Para obtener el contenido del sector de arranque (Master boot sector MBR) de un disquete en A utilizaremos el comando CWINDOWSgtDEBUG - L 100 0 0 1 - D 100 L 200 Como el resultado no cabe en una pantalla ingeniaremos un procedimiento para conservarlo en un archivo (maacutes adelante nos serviraacute para otro propoacutesito) Para ello creamos un archivo scripttxt con el siguiente contenido (dos INTRO despueacutes de la Q) L 100 0 0 1 D 100 L 200 Q A continuacioacuten invocamos DEBUG con el comando CWINDOWSgtDEBUG lt Dbuzonscripttxt gt Dbuzonresultadtxt Despueacutes de un breve parpadeo del disco y del disquete vuelve el prompt del DOS La operacioacuten ha concluido y en el directorio correspondiente de la unidad D tenemos el archivo resultadtxt con el volcado del sector de arranque del disquete ademaacutes de los ecos de los comandos introducidos (los hemos mantenido para orientacioacuten del lector) Otra forma de poder visualizar el contenido del Sector de Arranque del disco es utilizando el DEBUG Por ejemplo dentro del DEBUG tecleamos lo siguiente -L 100 0 0 1

-D 100 L 200

177C0100 EB 3E 90 2B 79 73 57 29-49 48 43 00 02 01 01 00 gt+ysW)IHC

177C0110 02 E0 00 40 0B F0 09 00-12 00 02 00 00 00 00 00

177C0120 00 00 00 00 00 00 29 5D-3B DD 10 4E 4F 20 4E 41 )]NO NA

177C0130 4D 45 20 20 20 20 46 41-54 31 32 20 20 20 F1 7D ME FAT12

177C0140 FA 33 C9 8E D1 BC FC 7B-16 07 BD 78 00 C5 76 00 3xv

177C0150 1E 56 16 55 BF 22 05 89-7E 00 89 4E 02 B1 0B FC VU~N

177C0160 F3 A4 06 1F BD 00 7C C6-45 FE 0F 8B 46 18 88 45 |EFE

177C0170 F9 FB 38 66 24 7C 04 CD-13 72 3C 8A 46 10 98 F7 8f$|rltF

177C0180 66 16 03 46 1C 13 56 1E-03 46 0E 13 D1 50 52 89 fFVFPR

177C0190 46 FC 89 56 FE B8 20 00-8B 76 11 F7 E6 8B 5E 0B FV v^

177C01A0 03 C3 48 F7 F3 01 46 FC-11 4E FE 5A 58 BB 00 07 HFNZX

177C01B0 8B FB B1 01 E8 94 00 72-47 38 2D 74 19 B1 0B 56 rG8-tV

177C01C0 8B 76 3E F3 A6 5E 74 4A-4E 74 0B 03 F9 83 C7 15 vgt^tJNt

177C01D0 3B FB 72 E5 EB D7 2B C9-B8 D8 7D 87 46 3E 3C D8 r+Fgtlt

177C01E0 75 99 BE 80 7D AC 98 03-F0 AC 84 C0 74 17 3C FF utlt

177C01F0 74 09 B4 0E BB 07 00 CD-10 EB EE BE 83 7D EB E5 t

177C0200 BE 81 7D EB E0 33 C0 CD-16 5E 1F 8F 04 8F 44 02 3^D

177C0210 CD 19 BE 82 7D 8B 7D 0F-83 FF 02 72 C8 8B C7 48 rH

177C0220 48 8A 4E 0D F7 E1 03 46-FC 13 56 FE BB 00 07 53 HNFVS

177C0230 B1 04 E8 16 00 5B 72 C8-81 3F 4D 5A 75 A7 81 BF [rMZu

177C0240 00 02 42 4A 75 9F EA 00-02 70 00 50 52 51 91 92 BJupPRQ

177C0250 33 D2 F7 76 18 91 F7 76-18 42 87 CA F7 76 1A 8A 3vvBv

177C0260 F2 8A 56 24 8A E8 D0 CC-D0 CC 0A CC B8 01 02 CD V$

177C0270 13 59 5A 58 72 09 40 75-01 42 03 5E 0B E2 CC C3 YZXruB^

177C0280 03 18 01 27 0D 0A 44 69-73 63 6F 20 69 6E 63 6F Disco inco

177C0290 72 72 65 63 74 6F 20 20-20 FF 0D 0A 45 72 72 6F rrecto Erro

177C02A0 72 20 45 2F 53 20 20 20-20 20 FF 0D 0A 43 61 6D r ES Cam

177C02B0 62 69 65 20 65 6C 20 64-69 73 63 6F 20 79 20 70 bie el disco y p

177C02C0 72 65 73 69 6F 6E 65 20-75 6E 61 20 74 65 63 6C resione una tecl

177C02D0 61 20 20 20 20 0D 0A 00-49 4F 20 20 20 20 20 20 a IO

177C02E0 53 59 53 4D 53 44 4F 53-20 20 20 53 59 53 80 01 SYSMSDOS SYS

177C02F0 00 57 49 4E 42 4F 4F 54-20 53 59 53 00 00 55 AA WINBOOT SYSU

-

-Q

FIN [1] En las primeras versiones de MS-DOS era un modesto programita DEBUGCOM de apenas 16 KB La versioacuten que acompantildea a Windows98 es ya un ejecutable en formato EXE de 21 KB [2] En realidad DEBUG es una utilidad de enorme potencia que requeririacutea todo un libro para ella sola Puede encontrarse una amplia descripcioacuten de esta herramienta en el libro de Paul Somerson PC Magazine DOS Powers Tools [3] Desgraciadamente no hay una convencioacuten estaacutendar sobre la colocacioacuten de los datos en la BIOS de forma que cada fabricante sigue sus propias reglas y es imposible por tanto utilizarla para cualquier tipo de identificacioacuten del sistema [4] En palabras del mencionado Paul Somerson Desgraciadamente debido a que DEBUG es un programa tan increiacuteblemente potente tambieacuten es increiacuteblemente peligroso Hay un dicho que afirma que El software no puede destruir el hardware Desgraciadamente esto no es cierto Ademaacutes de enviar mecanismos sensibles de la unidad de disco a tierra de nadie es posible hacer saltar monitores o transformadores Repito si sigue al pie de la letra las instrucciones y hace caso a todos los avisos todo iraacute bien [5] Recuerde que la imagen de un ejecutable exe cargado en memoria es distinta de su imagen en disco Solo en los ejecutables com la imagen en disco es una imagen exacta de su disposicioacuten en memoria [6] Es evidente que un pequentildeo error de nuacutemero en este paraacutemetro puede acarrear consecuencias nefastas Por ejemplo si cree que estaacute jugando con el disquete e inadvertidamente se dirige al disco duro (relea la nota [4])

Page 21: El Comando DEBUG

Manipulacioacuten de Posiciones de Memoria Con el DEBUG es posible almacenar y recuperar datos numeacutericos en memoria por medio de un programa a traveacutes de los registros del microprocesador Por ejemplo el siguiente programa almacena previamente dos valores numeacutericos en la posicioacuten 0300h y 0400h respectivamente despueacutes el programa los recupera realiza la operacioacuten de suma con esos valores y el resultado lo almacena en la posicioacuten 0500h -a 100 0B1C0100 mov ax0002 ax=2 0B1C0103 mov [0300]ax almacenamos 2 en la direccioacuten 0300h 0B1C0106 mov ax0004 ax=4 0B1C0109 mov [0400]ax almacenamos 4 en la direccioacuten 0400h 0B1C010C mov ax[0300] recuperamos el dato1 en AX 0B1C010F mov bx[0400] recuperamos el dato2 en BX 0B1C0113 add axbx hacemos la operacioacuten de suma en AX 0B1C0115 mov [0500]ax almacenamos el 6 en la direccioacuten 0500h 0B1C0118 int 21 0B1C011A - Un nuacutemero entre corchetes [numero_hex] indica una posicioacuten de memoria y su manejo se hace a traveacutes de registros ya que no es posible almacenar valores numeacutericos de manera directa Ejecutamos el programa -g 118 AX=0006 BX=0004 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=0B1C ES=0B1C SS=0B1C CS=0B1C IP=0118 NV UP EI PL NZ NA PE NC 0B1C0118 CD21 INT 21 - Para ver si el resultado se almaceno en la direccioacuten correcta hacemos

Como se puede observar en la direccioacuten 0B1C0500 se encuentra el 06 y en 0B1C0501 se encuentra el 00 que es el resultado de la operacioacuten 2+4 Perohellip Porque aparece el 06 y despueacutes el 00 pareceriacutea que el resultado fue de 0600 pero no es asiacute lo que sucedes que los datos se almacenan en memoria de la siguiente manera

Como se hizo la operacioacuten AX=AX+BX entonces el resultado es de 16 bits (dos bytes) AX=6 entonces AX=0000 0000 0000 0110 (16 bits) por lo tanto los 8 bits de menor peso de AX son 0000 0110 y deben almacenarse en la direccioacuten 0500 y en la direccioacuten 0501 se almacena 0000 0000

0 0 0 0 0 1 1 0 0500

0 0 0 0 0 0 0 0 0501

x x x x x x x x 0502

x x x x x x x x 0503

x x x x x x x x 0504

x x x x x x x x 0505

Interrupciones Definicioacuten de interrupcioacuten

Una interrupcioacuten es una instruccioacuten que detiene la ejecucioacuten de un programa para permitir el uso del microprocesador en un proceso prioritario Una vez concluido este uacuteltimo proceso se devuelve el control a la aplicacioacuten anterior

Por ejemplo cuando estamos trabajando con un procesador de palabras y en ese momento llega un aviso de uno de los puertos de comunicaciones se detiene temporalmente la aplicacioacuten que estaacutebamos utilizando para permitir el uso del microprocesador al manejo de la informacioacuten que estaacute llegando en ese momento Una vez terminada la transferencia de informacioacuten se reanudan las funciones normales del procesador de palabras Las interrupciones ocurren muy seguido sencillamente la interrupcioacuten que actualiza la hora del diacutea ocurre aproximadamente 18 veces por segundo Para lograr administrar todas estas interrupciones la computadora cuenta con un espacio de memoria llamado memoria baja donde se almacenan las direcciones de cierta localidad de memoria donde se encuentran un juego de instrucciones que el microprocesador ejecutaraacute para despueacutes regresar a la aplicacioacuten que estaba en proceso En los programas anteriores hicimos uso de la interrupcioacuten nuacutemero 20H para terminar la ejecucioacuten de nuestros programas y en otros ejemplos utilizamos otra interrupcioacuten para mostrar informacioacuten en pantalla (INT 21h) Utilizando DEBUG tecleamos

- a100 2C1B0100 JMP 011D 2C1B0102 [ENTER] - E 102 Hola como estas 0D 0A $ - A011D 2C1B011D MOV DX0102 2C1B0120 MOV AH09 2C1B0122 INT 21 2C1B0123 INT 20

Orden

creciente

de la

memoria

En este programa la interrupcioacuten 21h manda al monitor la cadena localizada en la direccioacuten a la que apunta el registro DX El valor que se le da a AH determina cual de las opciones de la interrupcioacuten 21h seraacute utilizada ya que esta interrupcioacuten cuenta con varias opciones El manejo directo de interrupciones es una de las partes maacutes fuertes del lenguaje ensamblador ya que con ellas es posible controlar eficientemente todos los dispositivos internos y externos de una computadora gracias al completo control que se tiene sobre operaciones de entrada y salida Maacutes del DEBUG Una caracteriacutestica poco conocida es que DEBUG puede aceptar entradas desde un archivo Script que puede ser un simple archivo de texto ASCII en el que cada comando esteacute separado del anterior por un INTRO Despueacutes del uacuteltimo que debe ser una Q para salir de DEBUG es conveniente dejar una liacutenea en blanco pulsando INTRO dos veces Las liacuteneas pueden contener comentarios Cualquier cosa a partir del caracter punto y coma () hasta el final de la liacutenea seraacute ignorado esto es un comentario D aquiacute se mostraraacute algo Suponiendo que tengamos un archivo Script de nombre Ordenestxt puede ser utilizado como entrada para DEBUG mediante un comando de redireccioacuten en la siguiente forma DEBUG lt ordenestxt Tambieacuten puede conseguirse que el programa redireccione la salida hacia un archivo que puede ser inspeccionado maacutes 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 podriacutea obtenerse un archivo Resulttxt con el siguiente comando DEBUG lt ordenestxt gt Resulttxt Errores Cuando DEBUG no sabe interpretar un comando muestra un mensaje de error y un indicador ^ debajo del sitio del comando donde estaacute el error Entradas y Salidas DEBUG asume que los datos numeacutericos proporcionados son hexadecimales y cuando se trate de direcciones de memoria deben introducirse en forma segmentada A su vez los resultados son mostrados tambieacuten 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

Cada fila muestra 16 posiciones de memoria a partir de la posicioacuten sentildealada por las columnas de la izquierda que las muestran como segmentodesplazamiento El bloque central muestra el contenido hexadecimal de cada byte mientras que el bloque derecho contiene la representacioacuten ASCII Por ejemplo la 3ra fila muestra el contenido de las posiciones 0B770120 a 0B77012F (ambas inclusive) Sus tres uacuteltimos bytes contienen respectivamente los caracteres r 9 y 2 que corresponden a las cantidades 72h 39h y 32h del bloque central Que como sabemos equivalen a los decimales 114 57 y 50 que son precisamente los valores ASCII de los caracteres ldquorrdquo ldquo9rdquo y ldquo2rdquo anteriormente mencionados

Nota Por razoacuten de que eacuteste tipo de salida pueda ser listado a impresora el bloque derecho no contiene en realidad la representacioacuten ASCII de todos los caracteres (algunos ni siquiera tienen una representacioacuten imprimible) En realidad solo se muestran los caracteres imprimibles del primer bloque (US-ASCII) El resto estaacute 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 caraacutecter imprimible Esto no significa que dichas posiciones representen efectivamente tales valores para la aplicacioacuten que las utiliza Por ejemplo puede que en realidad las dos posiciones de memoria mencionadas (dos octetos o bytes) en vez de los caracteres ldquo5rdquo y ldquoardquo representen una palabra de 16 bits en formato Little Endian que a su vez representan una cantidad entera (un nuacutemero) Comandos Aunque su descripcioacuten completa llenariacutea todo un capiacutetulo a continuacioacuten comentamos algunas de las opciones maacutes interesantes relativas a inspeccioacuten del coacutedigo y de contenidos de memoria La opcioacuten D (Dump) permite obtener un volcado del contenido de la memoria (de DEBUG) La sintaxis acepta dos formas D [direccioacuten-inicial] [L posiciones-desde-direccioacuten-inicial ] D [direccioacuten-inicial][direccioacuten-final] Naturalmente para que exista algo en el buacutefer de memoria (al principio quizaacutes solo contiene basura) es preciso indicarle que lea algo Este algo puede ser un rango de direcciones de memoria RAM una direccioacuten absoluta de disco (sector) un archivo o el contenido de los registros del procesador Para empezar puede indicaacutersele que cargue un archivo xxxxyz que tenemos en el directorio actual o en el PATH cuyo contenido queremos ver Cgt DEBUG xxxxyz -D aquiacute se obtendriacutea una salida anaacuteloga a la comentada

Hemos visto un ejemplo al tratar de los servicios de interrupciones del PC aquiacute mostraremos otro Sabemos que el punto de inicio de la BIOS es la direccioacuten F000FFF0 y que desde eacutesta posicioacuten hasta el final de la memoria DOS hay 16 bytes Puede obtenerse un volcado de estas posiciones con el siguiente comando -D F000FFF0 La salida en un equipo puede ser F000FFF0 CD 19 E0 00 F0 30 36 2F-33 30 2F 39 37 00 FC 38 0630978 En este caso el comando solo muestra una liacutenea porque ha alcanzado el final de la memoria Puede verse que la fecha de la BIOS del sistema ocupa las uacuteltimas posiciones Si se ordena el volcado de una direccioacuten suficientemente alejada del final de la memoria sin indicar ninguacuten nuacutemero de posiciones por defecto se toma el valor 128 (8 filas de 16 posiciones) Si desea una cantidad distinta hay que antildeadir una L (Long) y el nuacutemero de posiciones hasta un maacuteximo de 64 KB (FFFF) Todos los nuacutemeros deben ser expresados en hexadecimal Por consiguiente los dos comandos que siguen son equivalentes (recuerde que 80 es el equivalente hexadecimal de 128) D FE000000 D FE000000 L 80 He aquiacute el resultado

Sabemos que esta zona corresponde al aacuterea de la BIOS del Sistema Otra opcioacuten muy interesante nos permite buscar determinados contenidos a traveacutes de la memoria utilizando el prefijo S (Search) Existen dos sintaxis alternativas S direccioacuten-de-inicio L longitud-a-explorar contenido-a-buscar S direccioacuten-de-inicio direccioacuten-final L contenido-a-buscar El contenido debe ser proporcionado en hexadecimal (tal como apareceriacutea en la columna central del ejemplo anterior) o entre comillas si es un texto ASCII Por ejemplo en un equipo IBM deseo ver algunas caracteriacutesticas de la BIOS Seacute que estos datos se alojan a partir de la posicioacuten F0000000 hasta el final de la memoria Es decir una longitud de 64 Kbytes (FFFF) a partir de la posicioacuten de inicio y que seguramente los datos buscados estaraacuten cerca de la identificacioacuten de la propia BIOS (la cadena IBM) Por lo que se utiliza la siguiente sintaxis [3] -s f0000000 L ffff IBM

y se obtiene la siguiente salida F000E00E F000E111 con las direcciones donde se ha encontrado la ocurrencia buscada A continuacioacuten puedo explorar las proximidades de cada posicioacuten Por ejemplo para la primera -D f000e000

Si lo que se busca estaacute en un archivo primero hay que cargarlo Lo que se puede hacer de dos formas en la propia invocacioacuten de DEBUG o mediante los comandos N y L Por ejemplo si queremos inspeccionar el contenido del archivo morecom podemos utilizar dos formas CWINDOWSgtDEBUG cwindowscommandmorecom CWINDOWSgtDEBUG - N cwindowscommandmorecom - L La sintaxis para el prefijo N es N [path-name]nombre-de-archivo En ambos casos el contenido del archivo seraacute cargado en memoria y podraacute ser utilizado Atencioacuten despueacutes de la orden L (Load) DEBUG le avisaraacute si no encuentra el archivo pero seguiraacute su funcionamiento En tal caso simplemente piensa que N sentildeala el nombre de un nuevo archivo que crearaacute con el contenido de la memoria -de DEBUG- cuando posteriormente seleccione la opcioacuten escribir W (Write)[4]

Nota Como ya habraacute deducido DEBUG permite leer un archivo realizar modificaciones en eacutel (con la opcioacuten E) y escribir el archivo modificado bajo otro nombre con NW

A continuacioacuten podemos comprobar el tamantildeo del archivo cargado Para ello usamos la opcioacuten 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 17A70100 E8CD0F CALL 10D0 -

Aquiacute nos interesa especialmente el contenido del registro CX cuyo valor 2917h (1519d) en este caso sentildeala el tamantildeo del archivo en bytes Tambieacuten podiacuteamos haber utilizado directamente el comando R CX que nos proporciona el valor de dicho registro -R CX CX 2917 -

Nota A continuacioacuten del valor correspondiente DEBUG muestra dos puntos () sentildealando que puede cambiar el valor del registro introduciendo un nuevo nuacutemero Pulse INTRO para dejar las cosas como estaacuten y volver al prompt (-) de DEBUG

Al llegar a este punto es importante sentildealar que a excepcioacuten de los archivos exe DEBUG carga los archivos a partir de la direccioacuten 100h (256d) de su memoria De forma que el primer octeto del archivo se carga en la direccioacuten 100 el segundo en 101 etc En nuestro caso el archivo se extenderaacute desde la posicioacuten 100h hasta 2A17h (100h + 2917h) A continuacioacuten para buscar la cadena Microsoft en el archivo utilizamos cualquiera de los siguientes comandos - S 100 L 2917 Microsoft - S 100 2a17 Microsoft El primer comando sentildeala el punto de inicio y el tamantildeo de la zona a buscar el segundo utiliza los puntos inicial y final de la exploracioacuten Con ambos se obtiene la misma respuesta 17A71083 17A710B2

Truco Debido a la forma especial en que se cargan los ejecutables exe si quiere inspeccionar la forma nativa de uno de estos archivos (como es su imagen en el disco) debe hacer una copia del archivo renombrarlo con cualquier otra terminacioacuten (o sin ella) y cargar esta copia En caso contrario DEBUG se prepararaacute para funcionar como un verdadero depurador de tiempo de ejecucioacuten (run-time) para lo que cargaraacute el archivo y lo acomodaraacute en memoria de forma que pueda ejecutarse [5]

Como ejercicio compruebe las distintas longitudes y aspecto (especialmente al principio) de un mismo archivo exe cargaacutendolo con DEBUG de las dos formas (busque en su sistema un exe lo maacutes pequentildeo posible) Ademaacutes de la capacidad de leer archivos antes mencionada quizaacutes una de las opciones maacutes interesantes (y peligrosas) de DEBUG es la posibilidad de leerescribir el contenido de disco a bajo nivel mediante los prefijos L (Load) y W (Write) Se utiliza la siguiente sintaxis L [Direccioacuten] [Unidad] [Primer_sector] [Nuacutemero] W [Direccioacuten] [Unidad] [Primer_sector] [Nuacutemero] El significado de los paraacutemetros es como sigue

Direccioacuten Posicioacuten de la memoria de DEBUG a partir de la cual se instalaraacuten los datos leiacutedos del disco o se tomaraacuten para el proceso de escritura (aquiacute se utiliza generalmente el valor 100h)

Unidad Valor numeacuterico que indica la loacutegica a utilizar 0 = A 1 = B 2 = C 3 = D etc [6]

Primer sector A partir del que se realizaraacute la lectura o se comenzaraacute a escribir

Nuacutemero Nuacutemero de sectores que se desea cargarescribir Como DEBUG no puede leerescribir maacutes de 64 Kbytes (2

16 = 65536) y los sectores de disco son de 512 bytes

el maacuteximo nuacutemero de sectores es 128 (80h) Asiacute pues el valor maacuteximo aquiacute es 80 Ejemplo Para obtener el contenido del sector de arranque (Master boot sector MBR) de un disquete en A utilizaremos el comando CWINDOWSgtDEBUG - L 100 0 0 1 - D 100 L 200 Como el resultado no cabe en una pantalla ingeniaremos un procedimiento para conservarlo en un archivo (maacutes adelante nos serviraacute para otro propoacutesito) Para ello creamos un archivo scripttxt con el siguiente contenido (dos INTRO despueacutes de la Q) L 100 0 0 1 D 100 L 200 Q A continuacioacuten invocamos DEBUG con el comando CWINDOWSgtDEBUG lt Dbuzonscripttxt gt Dbuzonresultadtxt Despueacutes de un breve parpadeo del disco y del disquete vuelve el prompt del DOS La operacioacuten ha concluido y en el directorio correspondiente de la unidad D tenemos el archivo resultadtxt con el volcado del sector de arranque del disquete ademaacutes de los ecos de los comandos introducidos (los hemos mantenido para orientacioacuten del lector) Otra forma de poder visualizar el contenido del Sector de Arranque del disco es utilizando el DEBUG Por ejemplo dentro del DEBUG tecleamos lo siguiente -L 100 0 0 1

-D 100 L 200

177C0100 EB 3E 90 2B 79 73 57 29-49 48 43 00 02 01 01 00 gt+ysW)IHC

177C0110 02 E0 00 40 0B F0 09 00-12 00 02 00 00 00 00 00

177C0120 00 00 00 00 00 00 29 5D-3B DD 10 4E 4F 20 4E 41 )]NO NA

177C0130 4D 45 20 20 20 20 46 41-54 31 32 20 20 20 F1 7D ME FAT12

177C0140 FA 33 C9 8E D1 BC FC 7B-16 07 BD 78 00 C5 76 00 3xv

177C0150 1E 56 16 55 BF 22 05 89-7E 00 89 4E 02 B1 0B FC VU~N

177C0160 F3 A4 06 1F BD 00 7C C6-45 FE 0F 8B 46 18 88 45 |EFE

177C0170 F9 FB 38 66 24 7C 04 CD-13 72 3C 8A 46 10 98 F7 8f$|rltF

177C0180 66 16 03 46 1C 13 56 1E-03 46 0E 13 D1 50 52 89 fFVFPR

177C0190 46 FC 89 56 FE B8 20 00-8B 76 11 F7 E6 8B 5E 0B FV v^

177C01A0 03 C3 48 F7 F3 01 46 FC-11 4E FE 5A 58 BB 00 07 HFNZX

177C01B0 8B FB B1 01 E8 94 00 72-47 38 2D 74 19 B1 0B 56 rG8-tV

177C01C0 8B 76 3E F3 A6 5E 74 4A-4E 74 0B 03 F9 83 C7 15 vgt^tJNt

177C01D0 3B FB 72 E5 EB D7 2B C9-B8 D8 7D 87 46 3E 3C D8 r+Fgtlt

177C01E0 75 99 BE 80 7D AC 98 03-F0 AC 84 C0 74 17 3C FF utlt

177C01F0 74 09 B4 0E BB 07 00 CD-10 EB EE BE 83 7D EB E5 t

177C0200 BE 81 7D EB E0 33 C0 CD-16 5E 1F 8F 04 8F 44 02 3^D

177C0210 CD 19 BE 82 7D 8B 7D 0F-83 FF 02 72 C8 8B C7 48 rH

177C0220 48 8A 4E 0D F7 E1 03 46-FC 13 56 FE BB 00 07 53 HNFVS

177C0230 B1 04 E8 16 00 5B 72 C8-81 3F 4D 5A 75 A7 81 BF [rMZu

177C0240 00 02 42 4A 75 9F EA 00-02 70 00 50 52 51 91 92 BJupPRQ

177C0250 33 D2 F7 76 18 91 F7 76-18 42 87 CA F7 76 1A 8A 3vvBv

177C0260 F2 8A 56 24 8A E8 D0 CC-D0 CC 0A CC B8 01 02 CD V$

177C0270 13 59 5A 58 72 09 40 75-01 42 03 5E 0B E2 CC C3 YZXruB^

177C0280 03 18 01 27 0D 0A 44 69-73 63 6F 20 69 6E 63 6F Disco inco

177C0290 72 72 65 63 74 6F 20 20-20 FF 0D 0A 45 72 72 6F rrecto Erro

177C02A0 72 20 45 2F 53 20 20 20-20 20 FF 0D 0A 43 61 6D r ES Cam

177C02B0 62 69 65 20 65 6C 20 64-69 73 63 6F 20 79 20 70 bie el disco y p

177C02C0 72 65 73 69 6F 6E 65 20-75 6E 61 20 74 65 63 6C resione una tecl

177C02D0 61 20 20 20 20 0D 0A 00-49 4F 20 20 20 20 20 20 a IO

177C02E0 53 59 53 4D 53 44 4F 53-20 20 20 53 59 53 80 01 SYSMSDOS SYS

177C02F0 00 57 49 4E 42 4F 4F 54-20 53 59 53 00 00 55 AA WINBOOT SYSU

-

-Q

FIN [1] En las primeras versiones de MS-DOS era un modesto programita DEBUGCOM de apenas 16 KB La versioacuten que acompantildea a Windows98 es ya un ejecutable en formato EXE de 21 KB [2] En realidad DEBUG es una utilidad de enorme potencia que requeririacutea todo un libro para ella sola Puede encontrarse una amplia descripcioacuten de esta herramienta en el libro de Paul Somerson PC Magazine DOS Powers Tools [3] Desgraciadamente no hay una convencioacuten estaacutendar sobre la colocacioacuten de los datos en la BIOS de forma que cada fabricante sigue sus propias reglas y es imposible por tanto utilizarla para cualquier tipo de identificacioacuten del sistema [4] En palabras del mencionado Paul Somerson Desgraciadamente debido a que DEBUG es un programa tan increiacuteblemente potente tambieacuten es increiacuteblemente peligroso Hay un dicho que afirma que El software no puede destruir el hardware Desgraciadamente esto no es cierto Ademaacutes de enviar mecanismos sensibles de la unidad de disco a tierra de nadie es posible hacer saltar monitores o transformadores Repito si sigue al pie de la letra las instrucciones y hace caso a todos los avisos todo iraacute bien [5] Recuerde que la imagen de un ejecutable exe cargado en memoria es distinta de su imagen en disco Solo en los ejecutables com la imagen en disco es una imagen exacta de su disposicioacuten en memoria [6] Es evidente que un pequentildeo error de nuacutemero en este paraacutemetro puede acarrear consecuencias nefastas Por ejemplo si cree que estaacute jugando con el disquete e inadvertidamente se dirige al disco duro (relea la nota [4])

Page 22: El Comando DEBUG

Como se hizo la operacioacuten AX=AX+BX entonces el resultado es de 16 bits (dos bytes) AX=6 entonces AX=0000 0000 0000 0110 (16 bits) por lo tanto los 8 bits de menor peso de AX son 0000 0110 y deben almacenarse en la direccioacuten 0500 y en la direccioacuten 0501 se almacena 0000 0000

0 0 0 0 0 1 1 0 0500

0 0 0 0 0 0 0 0 0501

x x x x x x x x 0502

x x x x x x x x 0503

x x x x x x x x 0504

x x x x x x x x 0505

Interrupciones Definicioacuten de interrupcioacuten

Una interrupcioacuten es una instruccioacuten que detiene la ejecucioacuten de un programa para permitir el uso del microprocesador en un proceso prioritario Una vez concluido este uacuteltimo proceso se devuelve el control a la aplicacioacuten anterior

Por ejemplo cuando estamos trabajando con un procesador de palabras y en ese momento llega un aviso de uno de los puertos de comunicaciones se detiene temporalmente la aplicacioacuten que estaacutebamos utilizando para permitir el uso del microprocesador al manejo de la informacioacuten que estaacute llegando en ese momento Una vez terminada la transferencia de informacioacuten se reanudan las funciones normales del procesador de palabras Las interrupciones ocurren muy seguido sencillamente la interrupcioacuten que actualiza la hora del diacutea ocurre aproximadamente 18 veces por segundo Para lograr administrar todas estas interrupciones la computadora cuenta con un espacio de memoria llamado memoria baja donde se almacenan las direcciones de cierta localidad de memoria donde se encuentran un juego de instrucciones que el microprocesador ejecutaraacute para despueacutes regresar a la aplicacioacuten que estaba en proceso En los programas anteriores hicimos uso de la interrupcioacuten nuacutemero 20H para terminar la ejecucioacuten de nuestros programas y en otros ejemplos utilizamos otra interrupcioacuten para mostrar informacioacuten en pantalla (INT 21h) Utilizando DEBUG tecleamos

- a100 2C1B0100 JMP 011D 2C1B0102 [ENTER] - E 102 Hola como estas 0D 0A $ - A011D 2C1B011D MOV DX0102 2C1B0120 MOV AH09 2C1B0122 INT 21 2C1B0123 INT 20

Orden

creciente

de la

memoria

En este programa la interrupcioacuten 21h manda al monitor la cadena localizada en la direccioacuten a la que apunta el registro DX El valor que se le da a AH determina cual de las opciones de la interrupcioacuten 21h seraacute utilizada ya que esta interrupcioacuten cuenta con varias opciones El manejo directo de interrupciones es una de las partes maacutes fuertes del lenguaje ensamblador ya que con ellas es posible controlar eficientemente todos los dispositivos internos y externos de una computadora gracias al completo control que se tiene sobre operaciones de entrada y salida Maacutes del DEBUG Una caracteriacutestica poco conocida es que DEBUG puede aceptar entradas desde un archivo Script que puede ser un simple archivo de texto ASCII en el que cada comando esteacute separado del anterior por un INTRO Despueacutes del uacuteltimo que debe ser una Q para salir de DEBUG es conveniente dejar una liacutenea en blanco pulsando INTRO dos veces Las liacuteneas pueden contener comentarios Cualquier cosa a partir del caracter punto y coma () hasta el final de la liacutenea seraacute ignorado esto es un comentario D aquiacute se mostraraacute algo Suponiendo que tengamos un archivo Script de nombre Ordenestxt puede ser utilizado como entrada para DEBUG mediante un comando de redireccioacuten en la siguiente forma DEBUG lt ordenestxt Tambieacuten puede conseguirse que el programa redireccione la salida hacia un archivo que puede ser inspeccionado maacutes 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 podriacutea obtenerse un archivo Resulttxt con el siguiente comando DEBUG lt ordenestxt gt Resulttxt Errores Cuando DEBUG no sabe interpretar un comando muestra un mensaje de error y un indicador ^ debajo del sitio del comando donde estaacute el error Entradas y Salidas DEBUG asume que los datos numeacutericos proporcionados son hexadecimales y cuando se trate de direcciones de memoria deben introducirse en forma segmentada A su vez los resultados son mostrados tambieacuten 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

Cada fila muestra 16 posiciones de memoria a partir de la posicioacuten sentildealada por las columnas de la izquierda que las muestran como segmentodesplazamiento El bloque central muestra el contenido hexadecimal de cada byte mientras que el bloque derecho contiene la representacioacuten ASCII Por ejemplo la 3ra fila muestra el contenido de las posiciones 0B770120 a 0B77012F (ambas inclusive) Sus tres uacuteltimos bytes contienen respectivamente los caracteres r 9 y 2 que corresponden a las cantidades 72h 39h y 32h del bloque central Que como sabemos equivalen a los decimales 114 57 y 50 que son precisamente los valores ASCII de los caracteres ldquorrdquo ldquo9rdquo y ldquo2rdquo anteriormente mencionados

Nota Por razoacuten de que eacuteste tipo de salida pueda ser listado a impresora el bloque derecho no contiene en realidad la representacioacuten ASCII de todos los caracteres (algunos ni siquiera tienen una representacioacuten imprimible) En realidad solo se muestran los caracteres imprimibles del primer bloque (US-ASCII) El resto estaacute 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 caraacutecter imprimible Esto no significa que dichas posiciones representen efectivamente tales valores para la aplicacioacuten que las utiliza Por ejemplo puede que en realidad las dos posiciones de memoria mencionadas (dos octetos o bytes) en vez de los caracteres ldquo5rdquo y ldquoardquo representen una palabra de 16 bits en formato Little Endian que a su vez representan una cantidad entera (un nuacutemero) Comandos Aunque su descripcioacuten completa llenariacutea todo un capiacutetulo a continuacioacuten comentamos algunas de las opciones maacutes interesantes relativas a inspeccioacuten del coacutedigo y de contenidos de memoria La opcioacuten D (Dump) permite obtener un volcado del contenido de la memoria (de DEBUG) La sintaxis acepta dos formas D [direccioacuten-inicial] [L posiciones-desde-direccioacuten-inicial ] D [direccioacuten-inicial][direccioacuten-final] Naturalmente para que exista algo en el buacutefer de memoria (al principio quizaacutes solo contiene basura) es preciso indicarle que lea algo Este algo puede ser un rango de direcciones de memoria RAM una direccioacuten absoluta de disco (sector) un archivo o el contenido de los registros del procesador Para empezar puede indicaacutersele que cargue un archivo xxxxyz que tenemos en el directorio actual o en el PATH cuyo contenido queremos ver Cgt DEBUG xxxxyz -D aquiacute se obtendriacutea una salida anaacuteloga a la comentada

Hemos visto un ejemplo al tratar de los servicios de interrupciones del PC aquiacute mostraremos otro Sabemos que el punto de inicio de la BIOS es la direccioacuten F000FFF0 y que desde eacutesta posicioacuten hasta el final de la memoria DOS hay 16 bytes Puede obtenerse un volcado de estas posiciones con el siguiente comando -D F000FFF0 La salida en un equipo puede ser F000FFF0 CD 19 E0 00 F0 30 36 2F-33 30 2F 39 37 00 FC 38 0630978 En este caso el comando solo muestra una liacutenea porque ha alcanzado el final de la memoria Puede verse que la fecha de la BIOS del sistema ocupa las uacuteltimas posiciones Si se ordena el volcado de una direccioacuten suficientemente alejada del final de la memoria sin indicar ninguacuten nuacutemero de posiciones por defecto se toma el valor 128 (8 filas de 16 posiciones) Si desea una cantidad distinta hay que antildeadir una L (Long) y el nuacutemero de posiciones hasta un maacuteximo de 64 KB (FFFF) Todos los nuacutemeros deben ser expresados en hexadecimal Por consiguiente los dos comandos que siguen son equivalentes (recuerde que 80 es el equivalente hexadecimal de 128) D FE000000 D FE000000 L 80 He aquiacute el resultado

Sabemos que esta zona corresponde al aacuterea de la BIOS del Sistema Otra opcioacuten muy interesante nos permite buscar determinados contenidos a traveacutes de la memoria utilizando el prefijo S (Search) Existen dos sintaxis alternativas S direccioacuten-de-inicio L longitud-a-explorar contenido-a-buscar S direccioacuten-de-inicio direccioacuten-final L contenido-a-buscar El contenido debe ser proporcionado en hexadecimal (tal como apareceriacutea en la columna central del ejemplo anterior) o entre comillas si es un texto ASCII Por ejemplo en un equipo IBM deseo ver algunas caracteriacutesticas de la BIOS Seacute que estos datos se alojan a partir de la posicioacuten F0000000 hasta el final de la memoria Es decir una longitud de 64 Kbytes (FFFF) a partir de la posicioacuten de inicio y que seguramente los datos buscados estaraacuten cerca de la identificacioacuten de la propia BIOS (la cadena IBM) Por lo que se utiliza la siguiente sintaxis [3] -s f0000000 L ffff IBM

y se obtiene la siguiente salida F000E00E F000E111 con las direcciones donde se ha encontrado la ocurrencia buscada A continuacioacuten puedo explorar las proximidades de cada posicioacuten Por ejemplo para la primera -D f000e000

Si lo que se busca estaacute en un archivo primero hay que cargarlo Lo que se puede hacer de dos formas en la propia invocacioacuten de DEBUG o mediante los comandos N y L Por ejemplo si queremos inspeccionar el contenido del archivo morecom podemos utilizar dos formas CWINDOWSgtDEBUG cwindowscommandmorecom CWINDOWSgtDEBUG - N cwindowscommandmorecom - L La sintaxis para el prefijo N es N [path-name]nombre-de-archivo En ambos casos el contenido del archivo seraacute cargado en memoria y podraacute ser utilizado Atencioacuten despueacutes de la orden L (Load) DEBUG le avisaraacute si no encuentra el archivo pero seguiraacute su funcionamiento En tal caso simplemente piensa que N sentildeala el nombre de un nuevo archivo que crearaacute con el contenido de la memoria -de DEBUG- cuando posteriormente seleccione la opcioacuten escribir W (Write)[4]

Nota Como ya habraacute deducido DEBUG permite leer un archivo realizar modificaciones en eacutel (con la opcioacuten E) y escribir el archivo modificado bajo otro nombre con NW

A continuacioacuten podemos comprobar el tamantildeo del archivo cargado Para ello usamos la opcioacuten 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 17A70100 E8CD0F CALL 10D0 -

Aquiacute nos interesa especialmente el contenido del registro CX cuyo valor 2917h (1519d) en este caso sentildeala el tamantildeo del archivo en bytes Tambieacuten podiacuteamos haber utilizado directamente el comando R CX que nos proporciona el valor de dicho registro -R CX CX 2917 -

Nota A continuacioacuten del valor correspondiente DEBUG muestra dos puntos () sentildealando que puede cambiar el valor del registro introduciendo un nuevo nuacutemero Pulse INTRO para dejar las cosas como estaacuten y volver al prompt (-) de DEBUG

Al llegar a este punto es importante sentildealar que a excepcioacuten de los archivos exe DEBUG carga los archivos a partir de la direccioacuten 100h (256d) de su memoria De forma que el primer octeto del archivo se carga en la direccioacuten 100 el segundo en 101 etc En nuestro caso el archivo se extenderaacute desde la posicioacuten 100h hasta 2A17h (100h + 2917h) A continuacioacuten para buscar la cadena Microsoft en el archivo utilizamos cualquiera de los siguientes comandos - S 100 L 2917 Microsoft - S 100 2a17 Microsoft El primer comando sentildeala el punto de inicio y el tamantildeo de la zona a buscar el segundo utiliza los puntos inicial y final de la exploracioacuten Con ambos se obtiene la misma respuesta 17A71083 17A710B2

Truco Debido a la forma especial en que se cargan los ejecutables exe si quiere inspeccionar la forma nativa de uno de estos archivos (como es su imagen en el disco) debe hacer una copia del archivo renombrarlo con cualquier otra terminacioacuten (o sin ella) y cargar esta copia En caso contrario DEBUG se prepararaacute para funcionar como un verdadero depurador de tiempo de ejecucioacuten (run-time) para lo que cargaraacute el archivo y lo acomodaraacute en memoria de forma que pueda ejecutarse [5]

Como ejercicio compruebe las distintas longitudes y aspecto (especialmente al principio) de un mismo archivo exe cargaacutendolo con DEBUG de las dos formas (busque en su sistema un exe lo maacutes pequentildeo posible) Ademaacutes de la capacidad de leer archivos antes mencionada quizaacutes una de las opciones maacutes interesantes (y peligrosas) de DEBUG es la posibilidad de leerescribir el contenido de disco a bajo nivel mediante los prefijos L (Load) y W (Write) Se utiliza la siguiente sintaxis L [Direccioacuten] [Unidad] [Primer_sector] [Nuacutemero] W [Direccioacuten] [Unidad] [Primer_sector] [Nuacutemero] El significado de los paraacutemetros es como sigue

Direccioacuten Posicioacuten de la memoria de DEBUG a partir de la cual se instalaraacuten los datos leiacutedos del disco o se tomaraacuten para el proceso de escritura (aquiacute se utiliza generalmente el valor 100h)

Unidad Valor numeacuterico que indica la loacutegica a utilizar 0 = A 1 = B 2 = C 3 = D etc [6]

Primer sector A partir del que se realizaraacute la lectura o se comenzaraacute a escribir

Nuacutemero Nuacutemero de sectores que se desea cargarescribir Como DEBUG no puede leerescribir maacutes de 64 Kbytes (2

16 = 65536) y los sectores de disco son de 512 bytes

el maacuteximo nuacutemero de sectores es 128 (80h) Asiacute pues el valor maacuteximo aquiacute es 80 Ejemplo Para obtener el contenido del sector de arranque (Master boot sector MBR) de un disquete en A utilizaremos el comando CWINDOWSgtDEBUG - L 100 0 0 1 - D 100 L 200 Como el resultado no cabe en una pantalla ingeniaremos un procedimiento para conservarlo en un archivo (maacutes adelante nos serviraacute para otro propoacutesito) Para ello creamos un archivo scripttxt con el siguiente contenido (dos INTRO despueacutes de la Q) L 100 0 0 1 D 100 L 200 Q A continuacioacuten invocamos DEBUG con el comando CWINDOWSgtDEBUG lt Dbuzonscripttxt gt Dbuzonresultadtxt Despueacutes de un breve parpadeo del disco y del disquete vuelve el prompt del DOS La operacioacuten ha concluido y en el directorio correspondiente de la unidad D tenemos el archivo resultadtxt con el volcado del sector de arranque del disquete ademaacutes de los ecos de los comandos introducidos (los hemos mantenido para orientacioacuten del lector) Otra forma de poder visualizar el contenido del Sector de Arranque del disco es utilizando el DEBUG Por ejemplo dentro del DEBUG tecleamos lo siguiente -L 100 0 0 1

-D 100 L 200

177C0100 EB 3E 90 2B 79 73 57 29-49 48 43 00 02 01 01 00 gt+ysW)IHC

177C0110 02 E0 00 40 0B F0 09 00-12 00 02 00 00 00 00 00

177C0120 00 00 00 00 00 00 29 5D-3B DD 10 4E 4F 20 4E 41 )]NO NA

177C0130 4D 45 20 20 20 20 46 41-54 31 32 20 20 20 F1 7D ME FAT12

177C0140 FA 33 C9 8E D1 BC FC 7B-16 07 BD 78 00 C5 76 00 3xv

177C0150 1E 56 16 55 BF 22 05 89-7E 00 89 4E 02 B1 0B FC VU~N

177C0160 F3 A4 06 1F BD 00 7C C6-45 FE 0F 8B 46 18 88 45 |EFE

177C0170 F9 FB 38 66 24 7C 04 CD-13 72 3C 8A 46 10 98 F7 8f$|rltF

177C0180 66 16 03 46 1C 13 56 1E-03 46 0E 13 D1 50 52 89 fFVFPR

177C0190 46 FC 89 56 FE B8 20 00-8B 76 11 F7 E6 8B 5E 0B FV v^

177C01A0 03 C3 48 F7 F3 01 46 FC-11 4E FE 5A 58 BB 00 07 HFNZX

177C01B0 8B FB B1 01 E8 94 00 72-47 38 2D 74 19 B1 0B 56 rG8-tV

177C01C0 8B 76 3E F3 A6 5E 74 4A-4E 74 0B 03 F9 83 C7 15 vgt^tJNt

177C01D0 3B FB 72 E5 EB D7 2B C9-B8 D8 7D 87 46 3E 3C D8 r+Fgtlt

177C01E0 75 99 BE 80 7D AC 98 03-F0 AC 84 C0 74 17 3C FF utlt

177C01F0 74 09 B4 0E BB 07 00 CD-10 EB EE BE 83 7D EB E5 t

177C0200 BE 81 7D EB E0 33 C0 CD-16 5E 1F 8F 04 8F 44 02 3^D

177C0210 CD 19 BE 82 7D 8B 7D 0F-83 FF 02 72 C8 8B C7 48 rH

177C0220 48 8A 4E 0D F7 E1 03 46-FC 13 56 FE BB 00 07 53 HNFVS

177C0230 B1 04 E8 16 00 5B 72 C8-81 3F 4D 5A 75 A7 81 BF [rMZu

177C0240 00 02 42 4A 75 9F EA 00-02 70 00 50 52 51 91 92 BJupPRQ

177C0250 33 D2 F7 76 18 91 F7 76-18 42 87 CA F7 76 1A 8A 3vvBv

177C0260 F2 8A 56 24 8A E8 D0 CC-D0 CC 0A CC B8 01 02 CD V$

177C0270 13 59 5A 58 72 09 40 75-01 42 03 5E 0B E2 CC C3 YZXruB^

177C0280 03 18 01 27 0D 0A 44 69-73 63 6F 20 69 6E 63 6F Disco inco

177C0290 72 72 65 63 74 6F 20 20-20 FF 0D 0A 45 72 72 6F rrecto Erro

177C02A0 72 20 45 2F 53 20 20 20-20 20 FF 0D 0A 43 61 6D r ES Cam

177C02B0 62 69 65 20 65 6C 20 64-69 73 63 6F 20 79 20 70 bie el disco y p

177C02C0 72 65 73 69 6F 6E 65 20-75 6E 61 20 74 65 63 6C resione una tecl

177C02D0 61 20 20 20 20 0D 0A 00-49 4F 20 20 20 20 20 20 a IO

177C02E0 53 59 53 4D 53 44 4F 53-20 20 20 53 59 53 80 01 SYSMSDOS SYS

177C02F0 00 57 49 4E 42 4F 4F 54-20 53 59 53 00 00 55 AA WINBOOT SYSU

-

-Q

FIN [1] En las primeras versiones de MS-DOS era un modesto programita DEBUGCOM de apenas 16 KB La versioacuten que acompantildea a Windows98 es ya un ejecutable en formato EXE de 21 KB [2] En realidad DEBUG es una utilidad de enorme potencia que requeririacutea todo un libro para ella sola Puede encontrarse una amplia descripcioacuten de esta herramienta en el libro de Paul Somerson PC Magazine DOS Powers Tools [3] Desgraciadamente no hay una convencioacuten estaacutendar sobre la colocacioacuten de los datos en la BIOS de forma que cada fabricante sigue sus propias reglas y es imposible por tanto utilizarla para cualquier tipo de identificacioacuten del sistema [4] En palabras del mencionado Paul Somerson Desgraciadamente debido a que DEBUG es un programa tan increiacuteblemente potente tambieacuten es increiacuteblemente peligroso Hay un dicho que afirma que El software no puede destruir el hardware Desgraciadamente esto no es cierto Ademaacutes de enviar mecanismos sensibles de la unidad de disco a tierra de nadie es posible hacer saltar monitores o transformadores Repito si sigue al pie de la letra las instrucciones y hace caso a todos los avisos todo iraacute bien [5] Recuerde que la imagen de un ejecutable exe cargado en memoria es distinta de su imagen en disco Solo en los ejecutables com la imagen en disco es una imagen exacta de su disposicioacuten en memoria [6] Es evidente que un pequentildeo error de nuacutemero en este paraacutemetro puede acarrear consecuencias nefastas Por ejemplo si cree que estaacute jugando con el disquete e inadvertidamente se dirige al disco duro (relea la nota [4])

Page 23: El Comando DEBUG

En este programa la interrupcioacuten 21h manda al monitor la cadena localizada en la direccioacuten a la que apunta el registro DX El valor que se le da a AH determina cual de las opciones de la interrupcioacuten 21h seraacute utilizada ya que esta interrupcioacuten cuenta con varias opciones El manejo directo de interrupciones es una de las partes maacutes fuertes del lenguaje ensamblador ya que con ellas es posible controlar eficientemente todos los dispositivos internos y externos de una computadora gracias al completo control que se tiene sobre operaciones de entrada y salida Maacutes del DEBUG Una caracteriacutestica poco conocida es que DEBUG puede aceptar entradas desde un archivo Script que puede ser un simple archivo de texto ASCII en el que cada comando esteacute separado del anterior por un INTRO Despueacutes del uacuteltimo que debe ser una Q para salir de DEBUG es conveniente dejar una liacutenea en blanco pulsando INTRO dos veces Las liacuteneas pueden contener comentarios Cualquier cosa a partir del caracter punto y coma () hasta el final de la liacutenea seraacute ignorado esto es un comentario D aquiacute se mostraraacute algo Suponiendo que tengamos un archivo Script de nombre Ordenestxt puede ser utilizado como entrada para DEBUG mediante un comando de redireccioacuten en la siguiente forma DEBUG lt ordenestxt Tambieacuten puede conseguirse que el programa redireccione la salida hacia un archivo que puede ser inspeccionado maacutes 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 podriacutea obtenerse un archivo Resulttxt con el siguiente comando DEBUG lt ordenestxt gt Resulttxt Errores Cuando DEBUG no sabe interpretar un comando muestra un mensaje de error y un indicador ^ debajo del sitio del comando donde estaacute el error Entradas y Salidas DEBUG asume que los datos numeacutericos proporcionados son hexadecimales y cuando se trate de direcciones de memoria deben introducirse en forma segmentada A su vez los resultados son mostrados tambieacuten 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

Cada fila muestra 16 posiciones de memoria a partir de la posicioacuten sentildealada por las columnas de la izquierda que las muestran como segmentodesplazamiento El bloque central muestra el contenido hexadecimal de cada byte mientras que el bloque derecho contiene la representacioacuten ASCII Por ejemplo la 3ra fila muestra el contenido de las posiciones 0B770120 a 0B77012F (ambas inclusive) Sus tres uacuteltimos bytes contienen respectivamente los caracteres r 9 y 2 que corresponden a las cantidades 72h 39h y 32h del bloque central Que como sabemos equivalen a los decimales 114 57 y 50 que son precisamente los valores ASCII de los caracteres ldquorrdquo ldquo9rdquo y ldquo2rdquo anteriormente mencionados

Nota Por razoacuten de que eacuteste tipo de salida pueda ser listado a impresora el bloque derecho no contiene en realidad la representacioacuten ASCII de todos los caracteres (algunos ni siquiera tienen una representacioacuten imprimible) En realidad solo se muestran los caracteres imprimibles del primer bloque (US-ASCII) El resto estaacute 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 caraacutecter imprimible Esto no significa que dichas posiciones representen efectivamente tales valores para la aplicacioacuten que las utiliza Por ejemplo puede que en realidad las dos posiciones de memoria mencionadas (dos octetos o bytes) en vez de los caracteres ldquo5rdquo y ldquoardquo representen una palabra de 16 bits en formato Little Endian que a su vez representan una cantidad entera (un nuacutemero) Comandos Aunque su descripcioacuten completa llenariacutea todo un capiacutetulo a continuacioacuten comentamos algunas de las opciones maacutes interesantes relativas a inspeccioacuten del coacutedigo y de contenidos de memoria La opcioacuten D (Dump) permite obtener un volcado del contenido de la memoria (de DEBUG) La sintaxis acepta dos formas D [direccioacuten-inicial] [L posiciones-desde-direccioacuten-inicial ] D [direccioacuten-inicial][direccioacuten-final] Naturalmente para que exista algo en el buacutefer de memoria (al principio quizaacutes solo contiene basura) es preciso indicarle que lea algo Este algo puede ser un rango de direcciones de memoria RAM una direccioacuten absoluta de disco (sector) un archivo o el contenido de los registros del procesador Para empezar puede indicaacutersele que cargue un archivo xxxxyz que tenemos en el directorio actual o en el PATH cuyo contenido queremos ver Cgt DEBUG xxxxyz -D aquiacute se obtendriacutea una salida anaacuteloga a la comentada

Hemos visto un ejemplo al tratar de los servicios de interrupciones del PC aquiacute mostraremos otro Sabemos que el punto de inicio de la BIOS es la direccioacuten F000FFF0 y que desde eacutesta posicioacuten hasta el final de la memoria DOS hay 16 bytes Puede obtenerse un volcado de estas posiciones con el siguiente comando -D F000FFF0 La salida en un equipo puede ser F000FFF0 CD 19 E0 00 F0 30 36 2F-33 30 2F 39 37 00 FC 38 0630978 En este caso el comando solo muestra una liacutenea porque ha alcanzado el final de la memoria Puede verse que la fecha de la BIOS del sistema ocupa las uacuteltimas posiciones Si se ordena el volcado de una direccioacuten suficientemente alejada del final de la memoria sin indicar ninguacuten nuacutemero de posiciones por defecto se toma el valor 128 (8 filas de 16 posiciones) Si desea una cantidad distinta hay que antildeadir una L (Long) y el nuacutemero de posiciones hasta un maacuteximo de 64 KB (FFFF) Todos los nuacutemeros deben ser expresados en hexadecimal Por consiguiente los dos comandos que siguen son equivalentes (recuerde que 80 es el equivalente hexadecimal de 128) D FE000000 D FE000000 L 80 He aquiacute el resultado

Sabemos que esta zona corresponde al aacuterea de la BIOS del Sistema Otra opcioacuten muy interesante nos permite buscar determinados contenidos a traveacutes de la memoria utilizando el prefijo S (Search) Existen dos sintaxis alternativas S direccioacuten-de-inicio L longitud-a-explorar contenido-a-buscar S direccioacuten-de-inicio direccioacuten-final L contenido-a-buscar El contenido debe ser proporcionado en hexadecimal (tal como apareceriacutea en la columna central del ejemplo anterior) o entre comillas si es un texto ASCII Por ejemplo en un equipo IBM deseo ver algunas caracteriacutesticas de la BIOS Seacute que estos datos se alojan a partir de la posicioacuten F0000000 hasta el final de la memoria Es decir una longitud de 64 Kbytes (FFFF) a partir de la posicioacuten de inicio y que seguramente los datos buscados estaraacuten cerca de la identificacioacuten de la propia BIOS (la cadena IBM) Por lo que se utiliza la siguiente sintaxis [3] -s f0000000 L ffff IBM

y se obtiene la siguiente salida F000E00E F000E111 con las direcciones donde se ha encontrado la ocurrencia buscada A continuacioacuten puedo explorar las proximidades de cada posicioacuten Por ejemplo para la primera -D f000e000

Si lo que se busca estaacute en un archivo primero hay que cargarlo Lo que se puede hacer de dos formas en la propia invocacioacuten de DEBUG o mediante los comandos N y L Por ejemplo si queremos inspeccionar el contenido del archivo morecom podemos utilizar dos formas CWINDOWSgtDEBUG cwindowscommandmorecom CWINDOWSgtDEBUG - N cwindowscommandmorecom - L La sintaxis para el prefijo N es N [path-name]nombre-de-archivo En ambos casos el contenido del archivo seraacute cargado en memoria y podraacute ser utilizado Atencioacuten despueacutes de la orden L (Load) DEBUG le avisaraacute si no encuentra el archivo pero seguiraacute su funcionamiento En tal caso simplemente piensa que N sentildeala el nombre de un nuevo archivo que crearaacute con el contenido de la memoria -de DEBUG- cuando posteriormente seleccione la opcioacuten escribir W (Write)[4]

Nota Como ya habraacute deducido DEBUG permite leer un archivo realizar modificaciones en eacutel (con la opcioacuten E) y escribir el archivo modificado bajo otro nombre con NW

A continuacioacuten podemos comprobar el tamantildeo del archivo cargado Para ello usamos la opcioacuten 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 17A70100 E8CD0F CALL 10D0 -

Aquiacute nos interesa especialmente el contenido del registro CX cuyo valor 2917h (1519d) en este caso sentildeala el tamantildeo del archivo en bytes Tambieacuten podiacuteamos haber utilizado directamente el comando R CX que nos proporciona el valor de dicho registro -R CX CX 2917 -

Nota A continuacioacuten del valor correspondiente DEBUG muestra dos puntos () sentildealando que puede cambiar el valor del registro introduciendo un nuevo nuacutemero Pulse INTRO para dejar las cosas como estaacuten y volver al prompt (-) de DEBUG

Al llegar a este punto es importante sentildealar que a excepcioacuten de los archivos exe DEBUG carga los archivos a partir de la direccioacuten 100h (256d) de su memoria De forma que el primer octeto del archivo se carga en la direccioacuten 100 el segundo en 101 etc En nuestro caso el archivo se extenderaacute desde la posicioacuten 100h hasta 2A17h (100h + 2917h) A continuacioacuten para buscar la cadena Microsoft en el archivo utilizamos cualquiera de los siguientes comandos - S 100 L 2917 Microsoft - S 100 2a17 Microsoft El primer comando sentildeala el punto de inicio y el tamantildeo de la zona a buscar el segundo utiliza los puntos inicial y final de la exploracioacuten Con ambos se obtiene la misma respuesta 17A71083 17A710B2

Truco Debido a la forma especial en que se cargan los ejecutables exe si quiere inspeccionar la forma nativa de uno de estos archivos (como es su imagen en el disco) debe hacer una copia del archivo renombrarlo con cualquier otra terminacioacuten (o sin ella) y cargar esta copia En caso contrario DEBUG se prepararaacute para funcionar como un verdadero depurador de tiempo de ejecucioacuten (run-time) para lo que cargaraacute el archivo y lo acomodaraacute en memoria de forma que pueda ejecutarse [5]

Como ejercicio compruebe las distintas longitudes y aspecto (especialmente al principio) de un mismo archivo exe cargaacutendolo con DEBUG de las dos formas (busque en su sistema un exe lo maacutes pequentildeo posible) Ademaacutes de la capacidad de leer archivos antes mencionada quizaacutes una de las opciones maacutes interesantes (y peligrosas) de DEBUG es la posibilidad de leerescribir el contenido de disco a bajo nivel mediante los prefijos L (Load) y W (Write) Se utiliza la siguiente sintaxis L [Direccioacuten] [Unidad] [Primer_sector] [Nuacutemero] W [Direccioacuten] [Unidad] [Primer_sector] [Nuacutemero] El significado de los paraacutemetros es como sigue

Direccioacuten Posicioacuten de la memoria de DEBUG a partir de la cual se instalaraacuten los datos leiacutedos del disco o se tomaraacuten para el proceso de escritura (aquiacute se utiliza generalmente el valor 100h)

Unidad Valor numeacuterico que indica la loacutegica a utilizar 0 = A 1 = B 2 = C 3 = D etc [6]

Primer sector A partir del que se realizaraacute la lectura o se comenzaraacute a escribir

Nuacutemero Nuacutemero de sectores que se desea cargarescribir Como DEBUG no puede leerescribir maacutes de 64 Kbytes (2

16 = 65536) y los sectores de disco son de 512 bytes

el maacuteximo nuacutemero de sectores es 128 (80h) Asiacute pues el valor maacuteximo aquiacute es 80 Ejemplo Para obtener el contenido del sector de arranque (Master boot sector MBR) de un disquete en A utilizaremos el comando CWINDOWSgtDEBUG - L 100 0 0 1 - D 100 L 200 Como el resultado no cabe en una pantalla ingeniaremos un procedimiento para conservarlo en un archivo (maacutes adelante nos serviraacute para otro propoacutesito) Para ello creamos un archivo scripttxt con el siguiente contenido (dos INTRO despueacutes de la Q) L 100 0 0 1 D 100 L 200 Q A continuacioacuten invocamos DEBUG con el comando CWINDOWSgtDEBUG lt Dbuzonscripttxt gt Dbuzonresultadtxt Despueacutes de un breve parpadeo del disco y del disquete vuelve el prompt del DOS La operacioacuten ha concluido y en el directorio correspondiente de la unidad D tenemos el archivo resultadtxt con el volcado del sector de arranque del disquete ademaacutes de los ecos de los comandos introducidos (los hemos mantenido para orientacioacuten del lector) Otra forma de poder visualizar el contenido del Sector de Arranque del disco es utilizando el DEBUG Por ejemplo dentro del DEBUG tecleamos lo siguiente -L 100 0 0 1

-D 100 L 200

177C0100 EB 3E 90 2B 79 73 57 29-49 48 43 00 02 01 01 00 gt+ysW)IHC

177C0110 02 E0 00 40 0B F0 09 00-12 00 02 00 00 00 00 00

177C0120 00 00 00 00 00 00 29 5D-3B DD 10 4E 4F 20 4E 41 )]NO NA

177C0130 4D 45 20 20 20 20 46 41-54 31 32 20 20 20 F1 7D ME FAT12

177C0140 FA 33 C9 8E D1 BC FC 7B-16 07 BD 78 00 C5 76 00 3xv

177C0150 1E 56 16 55 BF 22 05 89-7E 00 89 4E 02 B1 0B FC VU~N

177C0160 F3 A4 06 1F BD 00 7C C6-45 FE 0F 8B 46 18 88 45 |EFE

177C0170 F9 FB 38 66 24 7C 04 CD-13 72 3C 8A 46 10 98 F7 8f$|rltF

177C0180 66 16 03 46 1C 13 56 1E-03 46 0E 13 D1 50 52 89 fFVFPR

177C0190 46 FC 89 56 FE B8 20 00-8B 76 11 F7 E6 8B 5E 0B FV v^

177C01A0 03 C3 48 F7 F3 01 46 FC-11 4E FE 5A 58 BB 00 07 HFNZX

177C01B0 8B FB B1 01 E8 94 00 72-47 38 2D 74 19 B1 0B 56 rG8-tV

177C01C0 8B 76 3E F3 A6 5E 74 4A-4E 74 0B 03 F9 83 C7 15 vgt^tJNt

177C01D0 3B FB 72 E5 EB D7 2B C9-B8 D8 7D 87 46 3E 3C D8 r+Fgtlt

177C01E0 75 99 BE 80 7D AC 98 03-F0 AC 84 C0 74 17 3C FF utlt

177C01F0 74 09 B4 0E BB 07 00 CD-10 EB EE BE 83 7D EB E5 t

177C0200 BE 81 7D EB E0 33 C0 CD-16 5E 1F 8F 04 8F 44 02 3^D

177C0210 CD 19 BE 82 7D 8B 7D 0F-83 FF 02 72 C8 8B C7 48 rH

177C0220 48 8A 4E 0D F7 E1 03 46-FC 13 56 FE BB 00 07 53 HNFVS

177C0230 B1 04 E8 16 00 5B 72 C8-81 3F 4D 5A 75 A7 81 BF [rMZu

177C0240 00 02 42 4A 75 9F EA 00-02 70 00 50 52 51 91 92 BJupPRQ

177C0250 33 D2 F7 76 18 91 F7 76-18 42 87 CA F7 76 1A 8A 3vvBv

177C0260 F2 8A 56 24 8A E8 D0 CC-D0 CC 0A CC B8 01 02 CD V$

177C0270 13 59 5A 58 72 09 40 75-01 42 03 5E 0B E2 CC C3 YZXruB^

177C0280 03 18 01 27 0D 0A 44 69-73 63 6F 20 69 6E 63 6F Disco inco

177C0290 72 72 65 63 74 6F 20 20-20 FF 0D 0A 45 72 72 6F rrecto Erro

177C02A0 72 20 45 2F 53 20 20 20-20 20 FF 0D 0A 43 61 6D r ES Cam

177C02B0 62 69 65 20 65 6C 20 64-69 73 63 6F 20 79 20 70 bie el disco y p

177C02C0 72 65 73 69 6F 6E 65 20-75 6E 61 20 74 65 63 6C resione una tecl

177C02D0 61 20 20 20 20 0D 0A 00-49 4F 20 20 20 20 20 20 a IO

177C02E0 53 59 53 4D 53 44 4F 53-20 20 20 53 59 53 80 01 SYSMSDOS SYS

177C02F0 00 57 49 4E 42 4F 4F 54-20 53 59 53 00 00 55 AA WINBOOT SYSU

-

-Q

FIN [1] En las primeras versiones de MS-DOS era un modesto programita DEBUGCOM de apenas 16 KB La versioacuten que acompantildea a Windows98 es ya un ejecutable en formato EXE de 21 KB [2] En realidad DEBUG es una utilidad de enorme potencia que requeririacutea todo un libro para ella sola Puede encontrarse una amplia descripcioacuten de esta herramienta en el libro de Paul Somerson PC Magazine DOS Powers Tools [3] Desgraciadamente no hay una convencioacuten estaacutendar sobre la colocacioacuten de los datos en la BIOS de forma que cada fabricante sigue sus propias reglas y es imposible por tanto utilizarla para cualquier tipo de identificacioacuten del sistema [4] En palabras del mencionado Paul Somerson Desgraciadamente debido a que DEBUG es un programa tan increiacuteblemente potente tambieacuten es increiacuteblemente peligroso Hay un dicho que afirma que El software no puede destruir el hardware Desgraciadamente esto no es cierto Ademaacutes de enviar mecanismos sensibles de la unidad de disco a tierra de nadie es posible hacer saltar monitores o transformadores Repito si sigue al pie de la letra las instrucciones y hace caso a todos los avisos todo iraacute bien [5] Recuerde que la imagen de un ejecutable exe cargado en memoria es distinta de su imagen en disco Solo en los ejecutables com la imagen en disco es una imagen exacta de su disposicioacuten en memoria [6] Es evidente que un pequentildeo error de nuacutemero en este paraacutemetro puede acarrear consecuencias nefastas Por ejemplo si cree que estaacute jugando con el disquete e inadvertidamente se dirige al disco duro (relea la nota [4])

Page 24: El Comando DEBUG

Cada fila muestra 16 posiciones de memoria a partir de la posicioacuten sentildealada por las columnas de la izquierda que las muestran como segmentodesplazamiento El bloque central muestra el contenido hexadecimal de cada byte mientras que el bloque derecho contiene la representacioacuten ASCII Por ejemplo la 3ra fila muestra el contenido de las posiciones 0B770120 a 0B77012F (ambas inclusive) Sus tres uacuteltimos bytes contienen respectivamente los caracteres r 9 y 2 que corresponden a las cantidades 72h 39h y 32h del bloque central Que como sabemos equivalen a los decimales 114 57 y 50 que son precisamente los valores ASCII de los caracteres ldquorrdquo ldquo9rdquo y ldquo2rdquo anteriormente mencionados

Nota Por razoacuten de que eacuteste tipo de salida pueda ser listado a impresora el bloque derecho no contiene en realidad la representacioacuten ASCII de todos los caracteres (algunos ni siquiera tienen una representacioacuten imprimible) En realidad solo se muestran los caracteres imprimibles del primer bloque (US-ASCII) El resto estaacute 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 caraacutecter imprimible Esto no significa que dichas posiciones representen efectivamente tales valores para la aplicacioacuten que las utiliza Por ejemplo puede que en realidad las dos posiciones de memoria mencionadas (dos octetos o bytes) en vez de los caracteres ldquo5rdquo y ldquoardquo representen una palabra de 16 bits en formato Little Endian que a su vez representan una cantidad entera (un nuacutemero) Comandos Aunque su descripcioacuten completa llenariacutea todo un capiacutetulo a continuacioacuten comentamos algunas de las opciones maacutes interesantes relativas a inspeccioacuten del coacutedigo y de contenidos de memoria La opcioacuten D (Dump) permite obtener un volcado del contenido de la memoria (de DEBUG) La sintaxis acepta dos formas D [direccioacuten-inicial] [L posiciones-desde-direccioacuten-inicial ] D [direccioacuten-inicial][direccioacuten-final] Naturalmente para que exista algo en el buacutefer de memoria (al principio quizaacutes solo contiene basura) es preciso indicarle que lea algo Este algo puede ser un rango de direcciones de memoria RAM una direccioacuten absoluta de disco (sector) un archivo o el contenido de los registros del procesador Para empezar puede indicaacutersele que cargue un archivo xxxxyz que tenemos en el directorio actual o en el PATH cuyo contenido queremos ver Cgt DEBUG xxxxyz -D aquiacute se obtendriacutea una salida anaacuteloga a la comentada

Hemos visto un ejemplo al tratar de los servicios de interrupciones del PC aquiacute mostraremos otro Sabemos que el punto de inicio de la BIOS es la direccioacuten F000FFF0 y que desde eacutesta posicioacuten hasta el final de la memoria DOS hay 16 bytes Puede obtenerse un volcado de estas posiciones con el siguiente comando -D F000FFF0 La salida en un equipo puede ser F000FFF0 CD 19 E0 00 F0 30 36 2F-33 30 2F 39 37 00 FC 38 0630978 En este caso el comando solo muestra una liacutenea porque ha alcanzado el final de la memoria Puede verse que la fecha de la BIOS del sistema ocupa las uacuteltimas posiciones Si se ordena el volcado de una direccioacuten suficientemente alejada del final de la memoria sin indicar ninguacuten nuacutemero de posiciones por defecto se toma el valor 128 (8 filas de 16 posiciones) Si desea una cantidad distinta hay que antildeadir una L (Long) y el nuacutemero de posiciones hasta un maacuteximo de 64 KB (FFFF) Todos los nuacutemeros deben ser expresados en hexadecimal Por consiguiente los dos comandos que siguen son equivalentes (recuerde que 80 es el equivalente hexadecimal de 128) D FE000000 D FE000000 L 80 He aquiacute el resultado

Sabemos que esta zona corresponde al aacuterea de la BIOS del Sistema Otra opcioacuten muy interesante nos permite buscar determinados contenidos a traveacutes de la memoria utilizando el prefijo S (Search) Existen dos sintaxis alternativas S direccioacuten-de-inicio L longitud-a-explorar contenido-a-buscar S direccioacuten-de-inicio direccioacuten-final L contenido-a-buscar El contenido debe ser proporcionado en hexadecimal (tal como apareceriacutea en la columna central del ejemplo anterior) o entre comillas si es un texto ASCII Por ejemplo en un equipo IBM deseo ver algunas caracteriacutesticas de la BIOS Seacute que estos datos se alojan a partir de la posicioacuten F0000000 hasta el final de la memoria Es decir una longitud de 64 Kbytes (FFFF) a partir de la posicioacuten de inicio y que seguramente los datos buscados estaraacuten cerca de la identificacioacuten de la propia BIOS (la cadena IBM) Por lo que se utiliza la siguiente sintaxis [3] -s f0000000 L ffff IBM

y se obtiene la siguiente salida F000E00E F000E111 con las direcciones donde se ha encontrado la ocurrencia buscada A continuacioacuten puedo explorar las proximidades de cada posicioacuten Por ejemplo para la primera -D f000e000

Si lo que se busca estaacute en un archivo primero hay que cargarlo Lo que se puede hacer de dos formas en la propia invocacioacuten de DEBUG o mediante los comandos N y L Por ejemplo si queremos inspeccionar el contenido del archivo morecom podemos utilizar dos formas CWINDOWSgtDEBUG cwindowscommandmorecom CWINDOWSgtDEBUG - N cwindowscommandmorecom - L La sintaxis para el prefijo N es N [path-name]nombre-de-archivo En ambos casos el contenido del archivo seraacute cargado en memoria y podraacute ser utilizado Atencioacuten despueacutes de la orden L (Load) DEBUG le avisaraacute si no encuentra el archivo pero seguiraacute su funcionamiento En tal caso simplemente piensa que N sentildeala el nombre de un nuevo archivo que crearaacute con el contenido de la memoria -de DEBUG- cuando posteriormente seleccione la opcioacuten escribir W (Write)[4]

Nota Como ya habraacute deducido DEBUG permite leer un archivo realizar modificaciones en eacutel (con la opcioacuten E) y escribir el archivo modificado bajo otro nombre con NW

A continuacioacuten podemos comprobar el tamantildeo del archivo cargado Para ello usamos la opcioacuten 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 17A70100 E8CD0F CALL 10D0 -

Aquiacute nos interesa especialmente el contenido del registro CX cuyo valor 2917h (1519d) en este caso sentildeala el tamantildeo del archivo en bytes Tambieacuten podiacuteamos haber utilizado directamente el comando R CX que nos proporciona el valor de dicho registro -R CX CX 2917 -

Nota A continuacioacuten del valor correspondiente DEBUG muestra dos puntos () sentildealando que puede cambiar el valor del registro introduciendo un nuevo nuacutemero Pulse INTRO para dejar las cosas como estaacuten y volver al prompt (-) de DEBUG

Al llegar a este punto es importante sentildealar que a excepcioacuten de los archivos exe DEBUG carga los archivos a partir de la direccioacuten 100h (256d) de su memoria De forma que el primer octeto del archivo se carga en la direccioacuten 100 el segundo en 101 etc En nuestro caso el archivo se extenderaacute desde la posicioacuten 100h hasta 2A17h (100h + 2917h) A continuacioacuten para buscar la cadena Microsoft en el archivo utilizamos cualquiera de los siguientes comandos - S 100 L 2917 Microsoft - S 100 2a17 Microsoft El primer comando sentildeala el punto de inicio y el tamantildeo de la zona a buscar el segundo utiliza los puntos inicial y final de la exploracioacuten Con ambos se obtiene la misma respuesta 17A71083 17A710B2

Truco Debido a la forma especial en que se cargan los ejecutables exe si quiere inspeccionar la forma nativa de uno de estos archivos (como es su imagen en el disco) debe hacer una copia del archivo renombrarlo con cualquier otra terminacioacuten (o sin ella) y cargar esta copia En caso contrario DEBUG se prepararaacute para funcionar como un verdadero depurador de tiempo de ejecucioacuten (run-time) para lo que cargaraacute el archivo y lo acomodaraacute en memoria de forma que pueda ejecutarse [5]

Como ejercicio compruebe las distintas longitudes y aspecto (especialmente al principio) de un mismo archivo exe cargaacutendolo con DEBUG de las dos formas (busque en su sistema un exe lo maacutes pequentildeo posible) Ademaacutes de la capacidad de leer archivos antes mencionada quizaacutes una de las opciones maacutes interesantes (y peligrosas) de DEBUG es la posibilidad de leerescribir el contenido de disco a bajo nivel mediante los prefijos L (Load) y W (Write) Se utiliza la siguiente sintaxis L [Direccioacuten] [Unidad] [Primer_sector] [Nuacutemero] W [Direccioacuten] [Unidad] [Primer_sector] [Nuacutemero] El significado de los paraacutemetros es como sigue

Direccioacuten Posicioacuten de la memoria de DEBUG a partir de la cual se instalaraacuten los datos leiacutedos del disco o se tomaraacuten para el proceso de escritura (aquiacute se utiliza generalmente el valor 100h)

Unidad Valor numeacuterico que indica la loacutegica a utilizar 0 = A 1 = B 2 = C 3 = D etc [6]

Primer sector A partir del que se realizaraacute la lectura o se comenzaraacute a escribir

Nuacutemero Nuacutemero de sectores que se desea cargarescribir Como DEBUG no puede leerescribir maacutes de 64 Kbytes (2

16 = 65536) y los sectores de disco son de 512 bytes

el maacuteximo nuacutemero de sectores es 128 (80h) Asiacute pues el valor maacuteximo aquiacute es 80 Ejemplo Para obtener el contenido del sector de arranque (Master boot sector MBR) de un disquete en A utilizaremos el comando CWINDOWSgtDEBUG - L 100 0 0 1 - D 100 L 200 Como el resultado no cabe en una pantalla ingeniaremos un procedimiento para conservarlo en un archivo (maacutes adelante nos serviraacute para otro propoacutesito) Para ello creamos un archivo scripttxt con el siguiente contenido (dos INTRO despueacutes de la Q) L 100 0 0 1 D 100 L 200 Q A continuacioacuten invocamos DEBUG con el comando CWINDOWSgtDEBUG lt Dbuzonscripttxt gt Dbuzonresultadtxt Despueacutes de un breve parpadeo del disco y del disquete vuelve el prompt del DOS La operacioacuten ha concluido y en el directorio correspondiente de la unidad D tenemos el archivo resultadtxt con el volcado del sector de arranque del disquete ademaacutes de los ecos de los comandos introducidos (los hemos mantenido para orientacioacuten del lector) Otra forma de poder visualizar el contenido del Sector de Arranque del disco es utilizando el DEBUG Por ejemplo dentro del DEBUG tecleamos lo siguiente -L 100 0 0 1

-D 100 L 200

177C0100 EB 3E 90 2B 79 73 57 29-49 48 43 00 02 01 01 00 gt+ysW)IHC

177C0110 02 E0 00 40 0B F0 09 00-12 00 02 00 00 00 00 00

177C0120 00 00 00 00 00 00 29 5D-3B DD 10 4E 4F 20 4E 41 )]NO NA

177C0130 4D 45 20 20 20 20 46 41-54 31 32 20 20 20 F1 7D ME FAT12

177C0140 FA 33 C9 8E D1 BC FC 7B-16 07 BD 78 00 C5 76 00 3xv

177C0150 1E 56 16 55 BF 22 05 89-7E 00 89 4E 02 B1 0B FC VU~N

177C0160 F3 A4 06 1F BD 00 7C C6-45 FE 0F 8B 46 18 88 45 |EFE

177C0170 F9 FB 38 66 24 7C 04 CD-13 72 3C 8A 46 10 98 F7 8f$|rltF

177C0180 66 16 03 46 1C 13 56 1E-03 46 0E 13 D1 50 52 89 fFVFPR

177C0190 46 FC 89 56 FE B8 20 00-8B 76 11 F7 E6 8B 5E 0B FV v^

177C01A0 03 C3 48 F7 F3 01 46 FC-11 4E FE 5A 58 BB 00 07 HFNZX

177C01B0 8B FB B1 01 E8 94 00 72-47 38 2D 74 19 B1 0B 56 rG8-tV

177C01C0 8B 76 3E F3 A6 5E 74 4A-4E 74 0B 03 F9 83 C7 15 vgt^tJNt

177C01D0 3B FB 72 E5 EB D7 2B C9-B8 D8 7D 87 46 3E 3C D8 r+Fgtlt

177C01E0 75 99 BE 80 7D AC 98 03-F0 AC 84 C0 74 17 3C FF utlt

177C01F0 74 09 B4 0E BB 07 00 CD-10 EB EE BE 83 7D EB E5 t

177C0200 BE 81 7D EB E0 33 C0 CD-16 5E 1F 8F 04 8F 44 02 3^D

177C0210 CD 19 BE 82 7D 8B 7D 0F-83 FF 02 72 C8 8B C7 48 rH

177C0220 48 8A 4E 0D F7 E1 03 46-FC 13 56 FE BB 00 07 53 HNFVS

177C0230 B1 04 E8 16 00 5B 72 C8-81 3F 4D 5A 75 A7 81 BF [rMZu

177C0240 00 02 42 4A 75 9F EA 00-02 70 00 50 52 51 91 92 BJupPRQ

177C0250 33 D2 F7 76 18 91 F7 76-18 42 87 CA F7 76 1A 8A 3vvBv

177C0260 F2 8A 56 24 8A E8 D0 CC-D0 CC 0A CC B8 01 02 CD V$

177C0270 13 59 5A 58 72 09 40 75-01 42 03 5E 0B E2 CC C3 YZXruB^

177C0280 03 18 01 27 0D 0A 44 69-73 63 6F 20 69 6E 63 6F Disco inco

177C0290 72 72 65 63 74 6F 20 20-20 FF 0D 0A 45 72 72 6F rrecto Erro

177C02A0 72 20 45 2F 53 20 20 20-20 20 FF 0D 0A 43 61 6D r ES Cam

177C02B0 62 69 65 20 65 6C 20 64-69 73 63 6F 20 79 20 70 bie el disco y p

177C02C0 72 65 73 69 6F 6E 65 20-75 6E 61 20 74 65 63 6C resione una tecl

177C02D0 61 20 20 20 20 0D 0A 00-49 4F 20 20 20 20 20 20 a IO

177C02E0 53 59 53 4D 53 44 4F 53-20 20 20 53 59 53 80 01 SYSMSDOS SYS

177C02F0 00 57 49 4E 42 4F 4F 54-20 53 59 53 00 00 55 AA WINBOOT SYSU

-

-Q

FIN [1] En las primeras versiones de MS-DOS era un modesto programita DEBUGCOM de apenas 16 KB La versioacuten que acompantildea a Windows98 es ya un ejecutable en formato EXE de 21 KB [2] En realidad DEBUG es una utilidad de enorme potencia que requeririacutea todo un libro para ella sola Puede encontrarse una amplia descripcioacuten de esta herramienta en el libro de Paul Somerson PC Magazine DOS Powers Tools [3] Desgraciadamente no hay una convencioacuten estaacutendar sobre la colocacioacuten de los datos en la BIOS de forma que cada fabricante sigue sus propias reglas y es imposible por tanto utilizarla para cualquier tipo de identificacioacuten del sistema [4] En palabras del mencionado Paul Somerson Desgraciadamente debido a que DEBUG es un programa tan increiacuteblemente potente tambieacuten es increiacuteblemente peligroso Hay un dicho que afirma que El software no puede destruir el hardware Desgraciadamente esto no es cierto Ademaacutes de enviar mecanismos sensibles de la unidad de disco a tierra de nadie es posible hacer saltar monitores o transformadores Repito si sigue al pie de la letra las instrucciones y hace caso a todos los avisos todo iraacute bien [5] Recuerde que la imagen de un ejecutable exe cargado en memoria es distinta de su imagen en disco Solo en los ejecutables com la imagen en disco es una imagen exacta de su disposicioacuten en memoria [6] Es evidente que un pequentildeo error de nuacutemero en este paraacutemetro puede acarrear consecuencias nefastas Por ejemplo si cree que estaacute jugando con el disquete e inadvertidamente se dirige al disco duro (relea la nota [4])

Page 25: El Comando DEBUG

Hemos visto un ejemplo al tratar de los servicios de interrupciones del PC aquiacute mostraremos otro Sabemos que el punto de inicio de la BIOS es la direccioacuten F000FFF0 y que desde eacutesta posicioacuten hasta el final de la memoria DOS hay 16 bytes Puede obtenerse un volcado de estas posiciones con el siguiente comando -D F000FFF0 La salida en un equipo puede ser F000FFF0 CD 19 E0 00 F0 30 36 2F-33 30 2F 39 37 00 FC 38 0630978 En este caso el comando solo muestra una liacutenea porque ha alcanzado el final de la memoria Puede verse que la fecha de la BIOS del sistema ocupa las uacuteltimas posiciones Si se ordena el volcado de una direccioacuten suficientemente alejada del final de la memoria sin indicar ninguacuten nuacutemero de posiciones por defecto se toma el valor 128 (8 filas de 16 posiciones) Si desea una cantidad distinta hay que antildeadir una L (Long) y el nuacutemero de posiciones hasta un maacuteximo de 64 KB (FFFF) Todos los nuacutemeros deben ser expresados en hexadecimal Por consiguiente los dos comandos que siguen son equivalentes (recuerde que 80 es el equivalente hexadecimal de 128) D FE000000 D FE000000 L 80 He aquiacute el resultado

Sabemos que esta zona corresponde al aacuterea de la BIOS del Sistema Otra opcioacuten muy interesante nos permite buscar determinados contenidos a traveacutes de la memoria utilizando el prefijo S (Search) Existen dos sintaxis alternativas S direccioacuten-de-inicio L longitud-a-explorar contenido-a-buscar S direccioacuten-de-inicio direccioacuten-final L contenido-a-buscar El contenido debe ser proporcionado en hexadecimal (tal como apareceriacutea en la columna central del ejemplo anterior) o entre comillas si es un texto ASCII Por ejemplo en un equipo IBM deseo ver algunas caracteriacutesticas de la BIOS Seacute que estos datos se alojan a partir de la posicioacuten F0000000 hasta el final de la memoria Es decir una longitud de 64 Kbytes (FFFF) a partir de la posicioacuten de inicio y que seguramente los datos buscados estaraacuten cerca de la identificacioacuten de la propia BIOS (la cadena IBM) Por lo que se utiliza la siguiente sintaxis [3] -s f0000000 L ffff IBM

y se obtiene la siguiente salida F000E00E F000E111 con las direcciones donde se ha encontrado la ocurrencia buscada A continuacioacuten puedo explorar las proximidades de cada posicioacuten Por ejemplo para la primera -D f000e000

Si lo que se busca estaacute en un archivo primero hay que cargarlo Lo que se puede hacer de dos formas en la propia invocacioacuten de DEBUG o mediante los comandos N y L Por ejemplo si queremos inspeccionar el contenido del archivo morecom podemos utilizar dos formas CWINDOWSgtDEBUG cwindowscommandmorecom CWINDOWSgtDEBUG - N cwindowscommandmorecom - L La sintaxis para el prefijo N es N [path-name]nombre-de-archivo En ambos casos el contenido del archivo seraacute cargado en memoria y podraacute ser utilizado Atencioacuten despueacutes de la orden L (Load) DEBUG le avisaraacute si no encuentra el archivo pero seguiraacute su funcionamiento En tal caso simplemente piensa que N sentildeala el nombre de un nuevo archivo que crearaacute con el contenido de la memoria -de DEBUG- cuando posteriormente seleccione la opcioacuten escribir W (Write)[4]

Nota Como ya habraacute deducido DEBUG permite leer un archivo realizar modificaciones en eacutel (con la opcioacuten E) y escribir el archivo modificado bajo otro nombre con NW

A continuacioacuten podemos comprobar el tamantildeo del archivo cargado Para ello usamos la opcioacuten 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 17A70100 E8CD0F CALL 10D0 -

Aquiacute nos interesa especialmente el contenido del registro CX cuyo valor 2917h (1519d) en este caso sentildeala el tamantildeo del archivo en bytes Tambieacuten podiacuteamos haber utilizado directamente el comando R CX que nos proporciona el valor de dicho registro -R CX CX 2917 -

Nota A continuacioacuten del valor correspondiente DEBUG muestra dos puntos () sentildealando que puede cambiar el valor del registro introduciendo un nuevo nuacutemero Pulse INTRO para dejar las cosas como estaacuten y volver al prompt (-) de DEBUG

Al llegar a este punto es importante sentildealar que a excepcioacuten de los archivos exe DEBUG carga los archivos a partir de la direccioacuten 100h (256d) de su memoria De forma que el primer octeto del archivo se carga en la direccioacuten 100 el segundo en 101 etc En nuestro caso el archivo se extenderaacute desde la posicioacuten 100h hasta 2A17h (100h + 2917h) A continuacioacuten para buscar la cadena Microsoft en el archivo utilizamos cualquiera de los siguientes comandos - S 100 L 2917 Microsoft - S 100 2a17 Microsoft El primer comando sentildeala el punto de inicio y el tamantildeo de la zona a buscar el segundo utiliza los puntos inicial y final de la exploracioacuten Con ambos se obtiene la misma respuesta 17A71083 17A710B2

Truco Debido a la forma especial en que se cargan los ejecutables exe si quiere inspeccionar la forma nativa de uno de estos archivos (como es su imagen en el disco) debe hacer una copia del archivo renombrarlo con cualquier otra terminacioacuten (o sin ella) y cargar esta copia En caso contrario DEBUG se prepararaacute para funcionar como un verdadero depurador de tiempo de ejecucioacuten (run-time) para lo que cargaraacute el archivo y lo acomodaraacute en memoria de forma que pueda ejecutarse [5]

Como ejercicio compruebe las distintas longitudes y aspecto (especialmente al principio) de un mismo archivo exe cargaacutendolo con DEBUG de las dos formas (busque en su sistema un exe lo maacutes pequentildeo posible) Ademaacutes de la capacidad de leer archivos antes mencionada quizaacutes una de las opciones maacutes interesantes (y peligrosas) de DEBUG es la posibilidad de leerescribir el contenido de disco a bajo nivel mediante los prefijos L (Load) y W (Write) Se utiliza la siguiente sintaxis L [Direccioacuten] [Unidad] [Primer_sector] [Nuacutemero] W [Direccioacuten] [Unidad] [Primer_sector] [Nuacutemero] El significado de los paraacutemetros es como sigue

Direccioacuten Posicioacuten de la memoria de DEBUG a partir de la cual se instalaraacuten los datos leiacutedos del disco o se tomaraacuten para el proceso de escritura (aquiacute se utiliza generalmente el valor 100h)

Unidad Valor numeacuterico que indica la loacutegica a utilizar 0 = A 1 = B 2 = C 3 = D etc [6]

Primer sector A partir del que se realizaraacute la lectura o se comenzaraacute a escribir

Nuacutemero Nuacutemero de sectores que se desea cargarescribir Como DEBUG no puede leerescribir maacutes de 64 Kbytes (2

16 = 65536) y los sectores de disco son de 512 bytes

el maacuteximo nuacutemero de sectores es 128 (80h) Asiacute pues el valor maacuteximo aquiacute es 80 Ejemplo Para obtener el contenido del sector de arranque (Master boot sector MBR) de un disquete en A utilizaremos el comando CWINDOWSgtDEBUG - L 100 0 0 1 - D 100 L 200 Como el resultado no cabe en una pantalla ingeniaremos un procedimiento para conservarlo en un archivo (maacutes adelante nos serviraacute para otro propoacutesito) Para ello creamos un archivo scripttxt con el siguiente contenido (dos INTRO despueacutes de la Q) L 100 0 0 1 D 100 L 200 Q A continuacioacuten invocamos DEBUG con el comando CWINDOWSgtDEBUG lt Dbuzonscripttxt gt Dbuzonresultadtxt Despueacutes de un breve parpadeo del disco y del disquete vuelve el prompt del DOS La operacioacuten ha concluido y en el directorio correspondiente de la unidad D tenemos el archivo resultadtxt con el volcado del sector de arranque del disquete ademaacutes de los ecos de los comandos introducidos (los hemos mantenido para orientacioacuten del lector) Otra forma de poder visualizar el contenido del Sector de Arranque del disco es utilizando el DEBUG Por ejemplo dentro del DEBUG tecleamos lo siguiente -L 100 0 0 1

-D 100 L 200

177C0100 EB 3E 90 2B 79 73 57 29-49 48 43 00 02 01 01 00 gt+ysW)IHC

177C0110 02 E0 00 40 0B F0 09 00-12 00 02 00 00 00 00 00

177C0120 00 00 00 00 00 00 29 5D-3B DD 10 4E 4F 20 4E 41 )]NO NA

177C0130 4D 45 20 20 20 20 46 41-54 31 32 20 20 20 F1 7D ME FAT12

177C0140 FA 33 C9 8E D1 BC FC 7B-16 07 BD 78 00 C5 76 00 3xv

177C0150 1E 56 16 55 BF 22 05 89-7E 00 89 4E 02 B1 0B FC VU~N

177C0160 F3 A4 06 1F BD 00 7C C6-45 FE 0F 8B 46 18 88 45 |EFE

177C0170 F9 FB 38 66 24 7C 04 CD-13 72 3C 8A 46 10 98 F7 8f$|rltF

177C0180 66 16 03 46 1C 13 56 1E-03 46 0E 13 D1 50 52 89 fFVFPR

177C0190 46 FC 89 56 FE B8 20 00-8B 76 11 F7 E6 8B 5E 0B FV v^

177C01A0 03 C3 48 F7 F3 01 46 FC-11 4E FE 5A 58 BB 00 07 HFNZX

177C01B0 8B FB B1 01 E8 94 00 72-47 38 2D 74 19 B1 0B 56 rG8-tV

177C01C0 8B 76 3E F3 A6 5E 74 4A-4E 74 0B 03 F9 83 C7 15 vgt^tJNt

177C01D0 3B FB 72 E5 EB D7 2B C9-B8 D8 7D 87 46 3E 3C D8 r+Fgtlt

177C01E0 75 99 BE 80 7D AC 98 03-F0 AC 84 C0 74 17 3C FF utlt

177C01F0 74 09 B4 0E BB 07 00 CD-10 EB EE BE 83 7D EB E5 t

177C0200 BE 81 7D EB E0 33 C0 CD-16 5E 1F 8F 04 8F 44 02 3^D

177C0210 CD 19 BE 82 7D 8B 7D 0F-83 FF 02 72 C8 8B C7 48 rH

177C0220 48 8A 4E 0D F7 E1 03 46-FC 13 56 FE BB 00 07 53 HNFVS

177C0230 B1 04 E8 16 00 5B 72 C8-81 3F 4D 5A 75 A7 81 BF [rMZu

177C0240 00 02 42 4A 75 9F EA 00-02 70 00 50 52 51 91 92 BJupPRQ

177C0250 33 D2 F7 76 18 91 F7 76-18 42 87 CA F7 76 1A 8A 3vvBv

177C0260 F2 8A 56 24 8A E8 D0 CC-D0 CC 0A CC B8 01 02 CD V$

177C0270 13 59 5A 58 72 09 40 75-01 42 03 5E 0B E2 CC C3 YZXruB^

177C0280 03 18 01 27 0D 0A 44 69-73 63 6F 20 69 6E 63 6F Disco inco

177C0290 72 72 65 63 74 6F 20 20-20 FF 0D 0A 45 72 72 6F rrecto Erro

177C02A0 72 20 45 2F 53 20 20 20-20 20 FF 0D 0A 43 61 6D r ES Cam

177C02B0 62 69 65 20 65 6C 20 64-69 73 63 6F 20 79 20 70 bie el disco y p

177C02C0 72 65 73 69 6F 6E 65 20-75 6E 61 20 74 65 63 6C resione una tecl

177C02D0 61 20 20 20 20 0D 0A 00-49 4F 20 20 20 20 20 20 a IO

177C02E0 53 59 53 4D 53 44 4F 53-20 20 20 53 59 53 80 01 SYSMSDOS SYS

177C02F0 00 57 49 4E 42 4F 4F 54-20 53 59 53 00 00 55 AA WINBOOT SYSU

-

-Q

FIN [1] En las primeras versiones de MS-DOS era un modesto programita DEBUGCOM de apenas 16 KB La versioacuten que acompantildea a Windows98 es ya un ejecutable en formato EXE de 21 KB [2] En realidad DEBUG es una utilidad de enorme potencia que requeririacutea todo un libro para ella sola Puede encontrarse una amplia descripcioacuten de esta herramienta en el libro de Paul Somerson PC Magazine DOS Powers Tools [3] Desgraciadamente no hay una convencioacuten estaacutendar sobre la colocacioacuten de los datos en la BIOS de forma que cada fabricante sigue sus propias reglas y es imposible por tanto utilizarla para cualquier tipo de identificacioacuten del sistema [4] En palabras del mencionado Paul Somerson Desgraciadamente debido a que DEBUG es un programa tan increiacuteblemente potente tambieacuten es increiacuteblemente peligroso Hay un dicho que afirma que El software no puede destruir el hardware Desgraciadamente esto no es cierto Ademaacutes de enviar mecanismos sensibles de la unidad de disco a tierra de nadie es posible hacer saltar monitores o transformadores Repito si sigue al pie de la letra las instrucciones y hace caso a todos los avisos todo iraacute bien [5] Recuerde que la imagen de un ejecutable exe cargado en memoria es distinta de su imagen en disco Solo en los ejecutables com la imagen en disco es una imagen exacta de su disposicioacuten en memoria [6] Es evidente que un pequentildeo error de nuacutemero en este paraacutemetro puede acarrear consecuencias nefastas Por ejemplo si cree que estaacute jugando con el disquete e inadvertidamente se dirige al disco duro (relea la nota [4])

Page 26: El Comando DEBUG

y se obtiene la siguiente salida F000E00E F000E111 con las direcciones donde se ha encontrado la ocurrencia buscada A continuacioacuten puedo explorar las proximidades de cada posicioacuten Por ejemplo para la primera -D f000e000

Si lo que se busca estaacute en un archivo primero hay que cargarlo Lo que se puede hacer de dos formas en la propia invocacioacuten de DEBUG o mediante los comandos N y L Por ejemplo si queremos inspeccionar el contenido del archivo morecom podemos utilizar dos formas CWINDOWSgtDEBUG cwindowscommandmorecom CWINDOWSgtDEBUG - N cwindowscommandmorecom - L La sintaxis para el prefijo N es N [path-name]nombre-de-archivo En ambos casos el contenido del archivo seraacute cargado en memoria y podraacute ser utilizado Atencioacuten despueacutes de la orden L (Load) DEBUG le avisaraacute si no encuentra el archivo pero seguiraacute su funcionamiento En tal caso simplemente piensa que N sentildeala el nombre de un nuevo archivo que crearaacute con el contenido de la memoria -de DEBUG- cuando posteriormente seleccione la opcioacuten escribir W (Write)[4]

Nota Como ya habraacute deducido DEBUG permite leer un archivo realizar modificaciones en eacutel (con la opcioacuten E) y escribir el archivo modificado bajo otro nombre con NW

A continuacioacuten podemos comprobar el tamantildeo del archivo cargado Para ello usamos la opcioacuten 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 17A70100 E8CD0F CALL 10D0 -

Aquiacute nos interesa especialmente el contenido del registro CX cuyo valor 2917h (1519d) en este caso sentildeala el tamantildeo del archivo en bytes Tambieacuten podiacuteamos haber utilizado directamente el comando R CX que nos proporciona el valor de dicho registro -R CX CX 2917 -

Nota A continuacioacuten del valor correspondiente DEBUG muestra dos puntos () sentildealando que puede cambiar el valor del registro introduciendo un nuevo nuacutemero Pulse INTRO para dejar las cosas como estaacuten y volver al prompt (-) de DEBUG

Al llegar a este punto es importante sentildealar que a excepcioacuten de los archivos exe DEBUG carga los archivos a partir de la direccioacuten 100h (256d) de su memoria De forma que el primer octeto del archivo se carga en la direccioacuten 100 el segundo en 101 etc En nuestro caso el archivo se extenderaacute desde la posicioacuten 100h hasta 2A17h (100h + 2917h) A continuacioacuten para buscar la cadena Microsoft en el archivo utilizamos cualquiera de los siguientes comandos - S 100 L 2917 Microsoft - S 100 2a17 Microsoft El primer comando sentildeala el punto de inicio y el tamantildeo de la zona a buscar el segundo utiliza los puntos inicial y final de la exploracioacuten Con ambos se obtiene la misma respuesta 17A71083 17A710B2

Truco Debido a la forma especial en que se cargan los ejecutables exe si quiere inspeccionar la forma nativa de uno de estos archivos (como es su imagen en el disco) debe hacer una copia del archivo renombrarlo con cualquier otra terminacioacuten (o sin ella) y cargar esta copia En caso contrario DEBUG se prepararaacute para funcionar como un verdadero depurador de tiempo de ejecucioacuten (run-time) para lo que cargaraacute el archivo y lo acomodaraacute en memoria de forma que pueda ejecutarse [5]

Como ejercicio compruebe las distintas longitudes y aspecto (especialmente al principio) de un mismo archivo exe cargaacutendolo con DEBUG de las dos formas (busque en su sistema un exe lo maacutes pequentildeo posible) Ademaacutes de la capacidad de leer archivos antes mencionada quizaacutes una de las opciones maacutes interesantes (y peligrosas) de DEBUG es la posibilidad de leerescribir el contenido de disco a bajo nivel mediante los prefijos L (Load) y W (Write) Se utiliza la siguiente sintaxis L [Direccioacuten] [Unidad] [Primer_sector] [Nuacutemero] W [Direccioacuten] [Unidad] [Primer_sector] [Nuacutemero] El significado de los paraacutemetros es como sigue

Direccioacuten Posicioacuten de la memoria de DEBUG a partir de la cual se instalaraacuten los datos leiacutedos del disco o se tomaraacuten para el proceso de escritura (aquiacute se utiliza generalmente el valor 100h)

Unidad Valor numeacuterico que indica la loacutegica a utilizar 0 = A 1 = B 2 = C 3 = D etc [6]

Primer sector A partir del que se realizaraacute la lectura o se comenzaraacute a escribir

Nuacutemero Nuacutemero de sectores que se desea cargarescribir Como DEBUG no puede leerescribir maacutes de 64 Kbytes (2

16 = 65536) y los sectores de disco son de 512 bytes

el maacuteximo nuacutemero de sectores es 128 (80h) Asiacute pues el valor maacuteximo aquiacute es 80 Ejemplo Para obtener el contenido del sector de arranque (Master boot sector MBR) de un disquete en A utilizaremos el comando CWINDOWSgtDEBUG - L 100 0 0 1 - D 100 L 200 Como el resultado no cabe en una pantalla ingeniaremos un procedimiento para conservarlo en un archivo (maacutes adelante nos serviraacute para otro propoacutesito) Para ello creamos un archivo scripttxt con el siguiente contenido (dos INTRO despueacutes de la Q) L 100 0 0 1 D 100 L 200 Q A continuacioacuten invocamos DEBUG con el comando CWINDOWSgtDEBUG lt Dbuzonscripttxt gt Dbuzonresultadtxt Despueacutes de un breve parpadeo del disco y del disquete vuelve el prompt del DOS La operacioacuten ha concluido y en el directorio correspondiente de la unidad D tenemos el archivo resultadtxt con el volcado del sector de arranque del disquete ademaacutes de los ecos de los comandos introducidos (los hemos mantenido para orientacioacuten del lector) Otra forma de poder visualizar el contenido del Sector de Arranque del disco es utilizando el DEBUG Por ejemplo dentro del DEBUG tecleamos lo siguiente -L 100 0 0 1

-D 100 L 200

177C0100 EB 3E 90 2B 79 73 57 29-49 48 43 00 02 01 01 00 gt+ysW)IHC

177C0110 02 E0 00 40 0B F0 09 00-12 00 02 00 00 00 00 00

177C0120 00 00 00 00 00 00 29 5D-3B DD 10 4E 4F 20 4E 41 )]NO NA

177C0130 4D 45 20 20 20 20 46 41-54 31 32 20 20 20 F1 7D ME FAT12

177C0140 FA 33 C9 8E D1 BC FC 7B-16 07 BD 78 00 C5 76 00 3xv

177C0150 1E 56 16 55 BF 22 05 89-7E 00 89 4E 02 B1 0B FC VU~N

177C0160 F3 A4 06 1F BD 00 7C C6-45 FE 0F 8B 46 18 88 45 |EFE

177C0170 F9 FB 38 66 24 7C 04 CD-13 72 3C 8A 46 10 98 F7 8f$|rltF

177C0180 66 16 03 46 1C 13 56 1E-03 46 0E 13 D1 50 52 89 fFVFPR

177C0190 46 FC 89 56 FE B8 20 00-8B 76 11 F7 E6 8B 5E 0B FV v^

177C01A0 03 C3 48 F7 F3 01 46 FC-11 4E FE 5A 58 BB 00 07 HFNZX

177C01B0 8B FB B1 01 E8 94 00 72-47 38 2D 74 19 B1 0B 56 rG8-tV

177C01C0 8B 76 3E F3 A6 5E 74 4A-4E 74 0B 03 F9 83 C7 15 vgt^tJNt

177C01D0 3B FB 72 E5 EB D7 2B C9-B8 D8 7D 87 46 3E 3C D8 r+Fgtlt

177C01E0 75 99 BE 80 7D AC 98 03-F0 AC 84 C0 74 17 3C FF utlt

177C01F0 74 09 B4 0E BB 07 00 CD-10 EB EE BE 83 7D EB E5 t

177C0200 BE 81 7D EB E0 33 C0 CD-16 5E 1F 8F 04 8F 44 02 3^D

177C0210 CD 19 BE 82 7D 8B 7D 0F-83 FF 02 72 C8 8B C7 48 rH

177C0220 48 8A 4E 0D F7 E1 03 46-FC 13 56 FE BB 00 07 53 HNFVS

177C0230 B1 04 E8 16 00 5B 72 C8-81 3F 4D 5A 75 A7 81 BF [rMZu

177C0240 00 02 42 4A 75 9F EA 00-02 70 00 50 52 51 91 92 BJupPRQ

177C0250 33 D2 F7 76 18 91 F7 76-18 42 87 CA F7 76 1A 8A 3vvBv

177C0260 F2 8A 56 24 8A E8 D0 CC-D0 CC 0A CC B8 01 02 CD V$

177C0270 13 59 5A 58 72 09 40 75-01 42 03 5E 0B E2 CC C3 YZXruB^

177C0280 03 18 01 27 0D 0A 44 69-73 63 6F 20 69 6E 63 6F Disco inco

177C0290 72 72 65 63 74 6F 20 20-20 FF 0D 0A 45 72 72 6F rrecto Erro

177C02A0 72 20 45 2F 53 20 20 20-20 20 FF 0D 0A 43 61 6D r ES Cam

177C02B0 62 69 65 20 65 6C 20 64-69 73 63 6F 20 79 20 70 bie el disco y p

177C02C0 72 65 73 69 6F 6E 65 20-75 6E 61 20 74 65 63 6C resione una tecl

177C02D0 61 20 20 20 20 0D 0A 00-49 4F 20 20 20 20 20 20 a IO

177C02E0 53 59 53 4D 53 44 4F 53-20 20 20 53 59 53 80 01 SYSMSDOS SYS

177C02F0 00 57 49 4E 42 4F 4F 54-20 53 59 53 00 00 55 AA WINBOOT SYSU

-

-Q

FIN [1] En las primeras versiones de MS-DOS era un modesto programita DEBUGCOM de apenas 16 KB La versioacuten que acompantildea a Windows98 es ya un ejecutable en formato EXE de 21 KB [2] En realidad DEBUG es una utilidad de enorme potencia que requeririacutea todo un libro para ella sola Puede encontrarse una amplia descripcioacuten de esta herramienta en el libro de Paul Somerson PC Magazine DOS Powers Tools [3] Desgraciadamente no hay una convencioacuten estaacutendar sobre la colocacioacuten de los datos en la BIOS de forma que cada fabricante sigue sus propias reglas y es imposible por tanto utilizarla para cualquier tipo de identificacioacuten del sistema [4] En palabras del mencionado Paul Somerson Desgraciadamente debido a que DEBUG es un programa tan increiacuteblemente potente tambieacuten es increiacuteblemente peligroso Hay un dicho que afirma que El software no puede destruir el hardware Desgraciadamente esto no es cierto Ademaacutes de enviar mecanismos sensibles de la unidad de disco a tierra de nadie es posible hacer saltar monitores o transformadores Repito si sigue al pie de la letra las instrucciones y hace caso a todos los avisos todo iraacute bien [5] Recuerde que la imagen de un ejecutable exe cargado en memoria es distinta de su imagen en disco Solo en los ejecutables com la imagen en disco es una imagen exacta de su disposicioacuten en memoria [6] Es evidente que un pequentildeo error de nuacutemero en este paraacutemetro puede acarrear consecuencias nefastas Por ejemplo si cree que estaacute jugando con el disquete e inadvertidamente se dirige al disco duro (relea la nota [4])

Page 27: El Comando DEBUG

Aquiacute nos interesa especialmente el contenido del registro CX cuyo valor 2917h (1519d) en este caso sentildeala el tamantildeo del archivo en bytes Tambieacuten podiacuteamos haber utilizado directamente el comando R CX que nos proporciona el valor de dicho registro -R CX CX 2917 -

Nota A continuacioacuten del valor correspondiente DEBUG muestra dos puntos () sentildealando que puede cambiar el valor del registro introduciendo un nuevo nuacutemero Pulse INTRO para dejar las cosas como estaacuten y volver al prompt (-) de DEBUG

Al llegar a este punto es importante sentildealar que a excepcioacuten de los archivos exe DEBUG carga los archivos a partir de la direccioacuten 100h (256d) de su memoria De forma que el primer octeto del archivo se carga en la direccioacuten 100 el segundo en 101 etc En nuestro caso el archivo se extenderaacute desde la posicioacuten 100h hasta 2A17h (100h + 2917h) A continuacioacuten para buscar la cadena Microsoft en el archivo utilizamos cualquiera de los siguientes comandos - S 100 L 2917 Microsoft - S 100 2a17 Microsoft El primer comando sentildeala el punto de inicio y el tamantildeo de la zona a buscar el segundo utiliza los puntos inicial y final de la exploracioacuten Con ambos se obtiene la misma respuesta 17A71083 17A710B2

Truco Debido a la forma especial en que se cargan los ejecutables exe si quiere inspeccionar la forma nativa de uno de estos archivos (como es su imagen en el disco) debe hacer una copia del archivo renombrarlo con cualquier otra terminacioacuten (o sin ella) y cargar esta copia En caso contrario DEBUG se prepararaacute para funcionar como un verdadero depurador de tiempo de ejecucioacuten (run-time) para lo que cargaraacute el archivo y lo acomodaraacute en memoria de forma que pueda ejecutarse [5]

Como ejercicio compruebe las distintas longitudes y aspecto (especialmente al principio) de un mismo archivo exe cargaacutendolo con DEBUG de las dos formas (busque en su sistema un exe lo maacutes pequentildeo posible) Ademaacutes de la capacidad de leer archivos antes mencionada quizaacutes una de las opciones maacutes interesantes (y peligrosas) de DEBUG es la posibilidad de leerescribir el contenido de disco a bajo nivel mediante los prefijos L (Load) y W (Write) Se utiliza la siguiente sintaxis L [Direccioacuten] [Unidad] [Primer_sector] [Nuacutemero] W [Direccioacuten] [Unidad] [Primer_sector] [Nuacutemero] El significado de los paraacutemetros es como sigue

Direccioacuten Posicioacuten de la memoria de DEBUG a partir de la cual se instalaraacuten los datos leiacutedos del disco o se tomaraacuten para el proceso de escritura (aquiacute se utiliza generalmente el valor 100h)

Unidad Valor numeacuterico que indica la loacutegica a utilizar 0 = A 1 = B 2 = C 3 = D etc [6]

Primer sector A partir del que se realizaraacute la lectura o se comenzaraacute a escribir

Nuacutemero Nuacutemero de sectores que se desea cargarescribir Como DEBUG no puede leerescribir maacutes de 64 Kbytes (2

16 = 65536) y los sectores de disco son de 512 bytes

el maacuteximo nuacutemero de sectores es 128 (80h) Asiacute pues el valor maacuteximo aquiacute es 80 Ejemplo Para obtener el contenido del sector de arranque (Master boot sector MBR) de un disquete en A utilizaremos el comando CWINDOWSgtDEBUG - L 100 0 0 1 - D 100 L 200 Como el resultado no cabe en una pantalla ingeniaremos un procedimiento para conservarlo en un archivo (maacutes adelante nos serviraacute para otro propoacutesito) Para ello creamos un archivo scripttxt con el siguiente contenido (dos INTRO despueacutes de la Q) L 100 0 0 1 D 100 L 200 Q A continuacioacuten invocamos DEBUG con el comando CWINDOWSgtDEBUG lt Dbuzonscripttxt gt Dbuzonresultadtxt Despueacutes de un breve parpadeo del disco y del disquete vuelve el prompt del DOS La operacioacuten ha concluido y en el directorio correspondiente de la unidad D tenemos el archivo resultadtxt con el volcado del sector de arranque del disquete ademaacutes de los ecos de los comandos introducidos (los hemos mantenido para orientacioacuten del lector) Otra forma de poder visualizar el contenido del Sector de Arranque del disco es utilizando el DEBUG Por ejemplo dentro del DEBUG tecleamos lo siguiente -L 100 0 0 1

-D 100 L 200

177C0100 EB 3E 90 2B 79 73 57 29-49 48 43 00 02 01 01 00 gt+ysW)IHC

177C0110 02 E0 00 40 0B F0 09 00-12 00 02 00 00 00 00 00

177C0120 00 00 00 00 00 00 29 5D-3B DD 10 4E 4F 20 4E 41 )]NO NA

177C0130 4D 45 20 20 20 20 46 41-54 31 32 20 20 20 F1 7D ME FAT12

177C0140 FA 33 C9 8E D1 BC FC 7B-16 07 BD 78 00 C5 76 00 3xv

177C0150 1E 56 16 55 BF 22 05 89-7E 00 89 4E 02 B1 0B FC VU~N

177C0160 F3 A4 06 1F BD 00 7C C6-45 FE 0F 8B 46 18 88 45 |EFE

177C0170 F9 FB 38 66 24 7C 04 CD-13 72 3C 8A 46 10 98 F7 8f$|rltF

177C0180 66 16 03 46 1C 13 56 1E-03 46 0E 13 D1 50 52 89 fFVFPR

177C0190 46 FC 89 56 FE B8 20 00-8B 76 11 F7 E6 8B 5E 0B FV v^

177C01A0 03 C3 48 F7 F3 01 46 FC-11 4E FE 5A 58 BB 00 07 HFNZX

177C01B0 8B FB B1 01 E8 94 00 72-47 38 2D 74 19 B1 0B 56 rG8-tV

177C01C0 8B 76 3E F3 A6 5E 74 4A-4E 74 0B 03 F9 83 C7 15 vgt^tJNt

177C01D0 3B FB 72 E5 EB D7 2B C9-B8 D8 7D 87 46 3E 3C D8 r+Fgtlt

177C01E0 75 99 BE 80 7D AC 98 03-F0 AC 84 C0 74 17 3C FF utlt

177C01F0 74 09 B4 0E BB 07 00 CD-10 EB EE BE 83 7D EB E5 t

177C0200 BE 81 7D EB E0 33 C0 CD-16 5E 1F 8F 04 8F 44 02 3^D

177C0210 CD 19 BE 82 7D 8B 7D 0F-83 FF 02 72 C8 8B C7 48 rH

177C0220 48 8A 4E 0D F7 E1 03 46-FC 13 56 FE BB 00 07 53 HNFVS

177C0230 B1 04 E8 16 00 5B 72 C8-81 3F 4D 5A 75 A7 81 BF [rMZu

177C0240 00 02 42 4A 75 9F EA 00-02 70 00 50 52 51 91 92 BJupPRQ

177C0250 33 D2 F7 76 18 91 F7 76-18 42 87 CA F7 76 1A 8A 3vvBv

177C0260 F2 8A 56 24 8A E8 D0 CC-D0 CC 0A CC B8 01 02 CD V$

177C0270 13 59 5A 58 72 09 40 75-01 42 03 5E 0B E2 CC C3 YZXruB^

177C0280 03 18 01 27 0D 0A 44 69-73 63 6F 20 69 6E 63 6F Disco inco

177C0290 72 72 65 63 74 6F 20 20-20 FF 0D 0A 45 72 72 6F rrecto Erro

177C02A0 72 20 45 2F 53 20 20 20-20 20 FF 0D 0A 43 61 6D r ES Cam

177C02B0 62 69 65 20 65 6C 20 64-69 73 63 6F 20 79 20 70 bie el disco y p

177C02C0 72 65 73 69 6F 6E 65 20-75 6E 61 20 74 65 63 6C resione una tecl

177C02D0 61 20 20 20 20 0D 0A 00-49 4F 20 20 20 20 20 20 a IO

177C02E0 53 59 53 4D 53 44 4F 53-20 20 20 53 59 53 80 01 SYSMSDOS SYS

177C02F0 00 57 49 4E 42 4F 4F 54-20 53 59 53 00 00 55 AA WINBOOT SYSU

-

-Q

FIN [1] En las primeras versiones de MS-DOS era un modesto programita DEBUGCOM de apenas 16 KB La versioacuten que acompantildea a Windows98 es ya un ejecutable en formato EXE de 21 KB [2] En realidad DEBUG es una utilidad de enorme potencia que requeririacutea todo un libro para ella sola Puede encontrarse una amplia descripcioacuten de esta herramienta en el libro de Paul Somerson PC Magazine DOS Powers Tools [3] Desgraciadamente no hay una convencioacuten estaacutendar sobre la colocacioacuten de los datos en la BIOS de forma que cada fabricante sigue sus propias reglas y es imposible por tanto utilizarla para cualquier tipo de identificacioacuten del sistema [4] En palabras del mencionado Paul Somerson Desgraciadamente debido a que DEBUG es un programa tan increiacuteblemente potente tambieacuten es increiacuteblemente peligroso Hay un dicho que afirma que El software no puede destruir el hardware Desgraciadamente esto no es cierto Ademaacutes de enviar mecanismos sensibles de la unidad de disco a tierra de nadie es posible hacer saltar monitores o transformadores Repito si sigue al pie de la letra las instrucciones y hace caso a todos los avisos todo iraacute bien [5] Recuerde que la imagen de un ejecutable exe cargado en memoria es distinta de su imagen en disco Solo en los ejecutables com la imagen en disco es una imagen exacta de su disposicioacuten en memoria [6] Es evidente que un pequentildeo error de nuacutemero en este paraacutemetro puede acarrear consecuencias nefastas Por ejemplo si cree que estaacute jugando con el disquete e inadvertidamente se dirige al disco duro (relea la nota [4])

Page 28: El Comando DEBUG

Direccioacuten Posicioacuten de la memoria de DEBUG a partir de la cual se instalaraacuten los datos leiacutedos del disco o se tomaraacuten para el proceso de escritura (aquiacute se utiliza generalmente el valor 100h)

Unidad Valor numeacuterico que indica la loacutegica a utilizar 0 = A 1 = B 2 = C 3 = D etc [6]

Primer sector A partir del que se realizaraacute la lectura o se comenzaraacute a escribir

Nuacutemero Nuacutemero de sectores que se desea cargarescribir Como DEBUG no puede leerescribir maacutes de 64 Kbytes (2

16 = 65536) y los sectores de disco son de 512 bytes

el maacuteximo nuacutemero de sectores es 128 (80h) Asiacute pues el valor maacuteximo aquiacute es 80 Ejemplo Para obtener el contenido del sector de arranque (Master boot sector MBR) de un disquete en A utilizaremos el comando CWINDOWSgtDEBUG - L 100 0 0 1 - D 100 L 200 Como el resultado no cabe en una pantalla ingeniaremos un procedimiento para conservarlo en un archivo (maacutes adelante nos serviraacute para otro propoacutesito) Para ello creamos un archivo scripttxt con el siguiente contenido (dos INTRO despueacutes de la Q) L 100 0 0 1 D 100 L 200 Q A continuacioacuten invocamos DEBUG con el comando CWINDOWSgtDEBUG lt Dbuzonscripttxt gt Dbuzonresultadtxt Despueacutes de un breve parpadeo del disco y del disquete vuelve el prompt del DOS La operacioacuten ha concluido y en el directorio correspondiente de la unidad D tenemos el archivo resultadtxt con el volcado del sector de arranque del disquete ademaacutes de los ecos de los comandos introducidos (los hemos mantenido para orientacioacuten del lector) Otra forma de poder visualizar el contenido del Sector de Arranque del disco es utilizando el DEBUG Por ejemplo dentro del DEBUG tecleamos lo siguiente -L 100 0 0 1

-D 100 L 200

177C0100 EB 3E 90 2B 79 73 57 29-49 48 43 00 02 01 01 00 gt+ysW)IHC

177C0110 02 E0 00 40 0B F0 09 00-12 00 02 00 00 00 00 00

177C0120 00 00 00 00 00 00 29 5D-3B DD 10 4E 4F 20 4E 41 )]NO NA

177C0130 4D 45 20 20 20 20 46 41-54 31 32 20 20 20 F1 7D ME FAT12

177C0140 FA 33 C9 8E D1 BC FC 7B-16 07 BD 78 00 C5 76 00 3xv

177C0150 1E 56 16 55 BF 22 05 89-7E 00 89 4E 02 B1 0B FC VU~N

177C0160 F3 A4 06 1F BD 00 7C C6-45 FE 0F 8B 46 18 88 45 |EFE

177C0170 F9 FB 38 66 24 7C 04 CD-13 72 3C 8A 46 10 98 F7 8f$|rltF

177C0180 66 16 03 46 1C 13 56 1E-03 46 0E 13 D1 50 52 89 fFVFPR

177C0190 46 FC 89 56 FE B8 20 00-8B 76 11 F7 E6 8B 5E 0B FV v^

177C01A0 03 C3 48 F7 F3 01 46 FC-11 4E FE 5A 58 BB 00 07 HFNZX

177C01B0 8B FB B1 01 E8 94 00 72-47 38 2D 74 19 B1 0B 56 rG8-tV

177C01C0 8B 76 3E F3 A6 5E 74 4A-4E 74 0B 03 F9 83 C7 15 vgt^tJNt

177C01D0 3B FB 72 E5 EB D7 2B C9-B8 D8 7D 87 46 3E 3C D8 r+Fgtlt

177C01E0 75 99 BE 80 7D AC 98 03-F0 AC 84 C0 74 17 3C FF utlt

177C01F0 74 09 B4 0E BB 07 00 CD-10 EB EE BE 83 7D EB E5 t

177C0200 BE 81 7D EB E0 33 C0 CD-16 5E 1F 8F 04 8F 44 02 3^D

177C0210 CD 19 BE 82 7D 8B 7D 0F-83 FF 02 72 C8 8B C7 48 rH

177C0220 48 8A 4E 0D F7 E1 03 46-FC 13 56 FE BB 00 07 53 HNFVS

177C0230 B1 04 E8 16 00 5B 72 C8-81 3F 4D 5A 75 A7 81 BF [rMZu

177C0240 00 02 42 4A 75 9F EA 00-02 70 00 50 52 51 91 92 BJupPRQ

177C0250 33 D2 F7 76 18 91 F7 76-18 42 87 CA F7 76 1A 8A 3vvBv

177C0260 F2 8A 56 24 8A E8 D0 CC-D0 CC 0A CC B8 01 02 CD V$

177C0270 13 59 5A 58 72 09 40 75-01 42 03 5E 0B E2 CC C3 YZXruB^

177C0280 03 18 01 27 0D 0A 44 69-73 63 6F 20 69 6E 63 6F Disco inco

177C0290 72 72 65 63 74 6F 20 20-20 FF 0D 0A 45 72 72 6F rrecto Erro

177C02A0 72 20 45 2F 53 20 20 20-20 20 FF 0D 0A 43 61 6D r ES Cam

177C02B0 62 69 65 20 65 6C 20 64-69 73 63 6F 20 79 20 70 bie el disco y p

177C02C0 72 65 73 69 6F 6E 65 20-75 6E 61 20 74 65 63 6C resione una tecl

177C02D0 61 20 20 20 20 0D 0A 00-49 4F 20 20 20 20 20 20 a IO

177C02E0 53 59 53 4D 53 44 4F 53-20 20 20 53 59 53 80 01 SYSMSDOS SYS

177C02F0 00 57 49 4E 42 4F 4F 54-20 53 59 53 00 00 55 AA WINBOOT SYSU

-

-Q

FIN [1] En las primeras versiones de MS-DOS era un modesto programita DEBUGCOM de apenas 16 KB La versioacuten que acompantildea a Windows98 es ya un ejecutable en formato EXE de 21 KB [2] En realidad DEBUG es una utilidad de enorme potencia que requeririacutea todo un libro para ella sola Puede encontrarse una amplia descripcioacuten de esta herramienta en el libro de Paul Somerson PC Magazine DOS Powers Tools [3] Desgraciadamente no hay una convencioacuten estaacutendar sobre la colocacioacuten de los datos en la BIOS de forma que cada fabricante sigue sus propias reglas y es imposible por tanto utilizarla para cualquier tipo de identificacioacuten del sistema [4] En palabras del mencionado Paul Somerson Desgraciadamente debido a que DEBUG es un programa tan increiacuteblemente potente tambieacuten es increiacuteblemente peligroso Hay un dicho que afirma que El software no puede destruir el hardware Desgraciadamente esto no es cierto Ademaacutes de enviar mecanismos sensibles de la unidad de disco a tierra de nadie es posible hacer saltar monitores o transformadores Repito si sigue al pie de la letra las instrucciones y hace caso a todos los avisos todo iraacute bien [5] Recuerde que la imagen de un ejecutable exe cargado en memoria es distinta de su imagen en disco Solo en los ejecutables com la imagen en disco es una imagen exacta de su disposicioacuten en memoria [6] Es evidente que un pequentildeo error de nuacutemero en este paraacutemetro puede acarrear consecuencias nefastas Por ejemplo si cree que estaacute jugando con el disquete e inadvertidamente se dirige al disco duro (relea la nota [4])

Page 29: El Comando DEBUG

177C01D0 3B FB 72 E5 EB D7 2B C9-B8 D8 7D 87 46 3E 3C D8 r+Fgtlt

177C01E0 75 99 BE 80 7D AC 98 03-F0 AC 84 C0 74 17 3C FF utlt

177C01F0 74 09 B4 0E BB 07 00 CD-10 EB EE BE 83 7D EB E5 t

177C0200 BE 81 7D EB E0 33 C0 CD-16 5E 1F 8F 04 8F 44 02 3^D

177C0210 CD 19 BE 82 7D 8B 7D 0F-83 FF 02 72 C8 8B C7 48 rH

177C0220 48 8A 4E 0D F7 E1 03 46-FC 13 56 FE BB 00 07 53 HNFVS

177C0230 B1 04 E8 16 00 5B 72 C8-81 3F 4D 5A 75 A7 81 BF [rMZu

177C0240 00 02 42 4A 75 9F EA 00-02 70 00 50 52 51 91 92 BJupPRQ

177C0250 33 D2 F7 76 18 91 F7 76-18 42 87 CA F7 76 1A 8A 3vvBv

177C0260 F2 8A 56 24 8A E8 D0 CC-D0 CC 0A CC B8 01 02 CD V$

177C0270 13 59 5A 58 72 09 40 75-01 42 03 5E 0B E2 CC C3 YZXruB^

177C0280 03 18 01 27 0D 0A 44 69-73 63 6F 20 69 6E 63 6F Disco inco

177C0290 72 72 65 63 74 6F 20 20-20 FF 0D 0A 45 72 72 6F rrecto Erro

177C02A0 72 20 45 2F 53 20 20 20-20 20 FF 0D 0A 43 61 6D r ES Cam

177C02B0 62 69 65 20 65 6C 20 64-69 73 63 6F 20 79 20 70 bie el disco y p

177C02C0 72 65 73 69 6F 6E 65 20-75 6E 61 20 74 65 63 6C resione una tecl

177C02D0 61 20 20 20 20 0D 0A 00-49 4F 20 20 20 20 20 20 a IO

177C02E0 53 59 53 4D 53 44 4F 53-20 20 20 53 59 53 80 01 SYSMSDOS SYS

177C02F0 00 57 49 4E 42 4F 4F 54-20 53 59 53 00 00 55 AA WINBOOT SYSU

-

-Q

FIN [1] En las primeras versiones de MS-DOS era un modesto programita DEBUGCOM de apenas 16 KB La versioacuten que acompantildea a Windows98 es ya un ejecutable en formato EXE de 21 KB [2] En realidad DEBUG es una utilidad de enorme potencia que requeririacutea todo un libro para ella sola Puede encontrarse una amplia descripcioacuten de esta herramienta en el libro de Paul Somerson PC Magazine DOS Powers Tools [3] Desgraciadamente no hay una convencioacuten estaacutendar sobre la colocacioacuten de los datos en la BIOS de forma que cada fabricante sigue sus propias reglas y es imposible por tanto utilizarla para cualquier tipo de identificacioacuten del sistema [4] En palabras del mencionado Paul Somerson Desgraciadamente debido a que DEBUG es un programa tan increiacuteblemente potente tambieacuten es increiacuteblemente peligroso Hay un dicho que afirma que El software no puede destruir el hardware Desgraciadamente esto no es cierto Ademaacutes de enviar mecanismos sensibles de la unidad de disco a tierra de nadie es posible hacer saltar monitores o transformadores Repito si sigue al pie de la letra las instrucciones y hace caso a todos los avisos todo iraacute bien [5] Recuerde que la imagen de un ejecutable exe cargado en memoria es distinta de su imagen en disco Solo en los ejecutables com la imagen en disco es una imagen exacta de su disposicioacuten en memoria [6] Es evidente que un pequentildeo error de nuacutemero en este paraacutemetro puede acarrear consecuencias nefastas Por ejemplo si cree que estaacute jugando con el disquete e inadvertidamente se dirige al disco duro (relea la nota [4])

Page 30: El Comando DEBUG

FIN [1] En las primeras versiones de MS-DOS era un modesto programita DEBUGCOM de apenas 16 KB La versioacuten que acompantildea a Windows98 es ya un ejecutable en formato EXE de 21 KB [2] En realidad DEBUG es una utilidad de enorme potencia que requeririacutea todo un libro para ella sola Puede encontrarse una amplia descripcioacuten de esta herramienta en el libro de Paul Somerson PC Magazine DOS Powers Tools [3] Desgraciadamente no hay una convencioacuten estaacutendar sobre la colocacioacuten de los datos en la BIOS de forma que cada fabricante sigue sus propias reglas y es imposible por tanto utilizarla para cualquier tipo de identificacioacuten del sistema [4] En palabras del mencionado Paul Somerson Desgraciadamente debido a que DEBUG es un programa tan increiacuteblemente potente tambieacuten es increiacuteblemente peligroso Hay un dicho que afirma que El software no puede destruir el hardware Desgraciadamente esto no es cierto Ademaacutes de enviar mecanismos sensibles de la unidad de disco a tierra de nadie es posible hacer saltar monitores o transformadores Repito si sigue al pie de la letra las instrucciones y hace caso a todos los avisos todo iraacute bien [5] Recuerde que la imagen de un ejecutable exe cargado en memoria es distinta de su imagen en disco Solo en los ejecutables com la imagen en disco es una imagen exacta de su disposicioacuten en memoria [6] Es evidente que un pequentildeo error de nuacutemero en este paraacutemetro puede acarrear consecuencias nefastas Por ejemplo si cree que estaacute jugando con el disquete e inadvertidamente se dirige al disco duro (relea la nota [4])