UNEFA Excelencia Educativa Resumen y ejercicios del DEBUG Uso del DEBUG. Ingreso: Tipeamos la instrucción que se menciona seguidamente desde el prompt. C: \ > DEBUG Después de dar enter aparecerá un guión C:\>debug Ya estamos posicionados en el DEBUG y éste está preparado para recibir instrucciones en ASSEMBLER. Ejemplo 1: Ver las instrucciones permitidas en el ASSEMBLER básico. Tipeamos lo siguiente: -?? Y nos mostrará la información que sigue. Tipee y compruebe ensamblar comparar volcar escribir llenar A [dirección] C dirección de intervalo D [intervalo] E dirección [lista] F lista de intervalos G [=dirección] [direcciones] H valor1 valor2 I puerto L [dirección] [unidad] [primer_sector] [número] M dirección de intervalo N [nombre_ruta] [lista_argumentos] O byte de puerto P [=dirección] [número] Q R [registrar] S lista de intervalos T [=dirección] [valor] ir hex entrada cargar mover nombre salida proceder salir registrar buscar seguimiento desensamblar U [intervalo] W [dirección] [unidad] [primer_sector] [número] escribir asignar expandida desasignar expandida asignar páginas de expandida mostrar estado memoria expandida - memoria memoria memoria de la XA [#páginas] XD [identificador] XM [Lpágina] [Ppágina] [identificador] XS Note que al terminar aparece el guión que nos indica que el DEBUG tiene nuevamente el control de las operaciones, con lo cual Uds. podrán ingresar más comandos Cada una de la instrucciones que se mostraron anteriormente se irán explicando a lo largo de este apunte, donde aplicaremos un ejercicio específico para cada una de ellas incrementando las posibilidades, desde las más simples hasta las más complejas, para perfeccionar nuestro dominio de la programación. Ejemplo 2: Ver los registros. Este ejercicio nos permite que miremos el valor de varios registros y del registro de estado de la ALU (STATUS REGISTER). Para eso tipeamos: -r Y no muestra lo que sigue: AX=0000 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=1987 ES=1987 SS=1987 CS=1987 IP=0100 NV UP EI PL NZ NA PO NC 1987:0100 8936C7DE MOV [DEC7],SI DS:DEC7=0000 El significado de los diferentes registros se da en la tabla siguiente. REF AX Nombre Acumulador BX Registro Base CX Registro Contador DX Registro de Datos DS Registro de segmento de datos Segmento extra para datos Registro de segmento de pila Registro de segmento código Puntero del STACK ES SS CS BP SI DI Registro de Indice segmento Indice destino de SP Puntero de Pila IP Apuntador de la siguiente instrucción Que es lo que hace Almacena el resultado de operaciones matemáticas; lectura / escritura (I/O) dede/hacia los puertos que están conectados con los periféricos; almacena también un área de memoria temporal. Alacena direcciones o valores y puede interactuar con el Acumulador. Utilizados para la ejecución de LOOPS y puede ser incrementado o decrementado según la instrucción que sea necesaria De acuerdo a la estructura de computadores analizada por nosotros corresponde al MDR (MEMORY DATA RGISTER) y es el paso intermedio para el ingreso de datos. Es un puntero que nos indica la dirección donde se encuentran los datos. Igual que el anterior pero apuntando a una dirección mayor. Indica donde se encuentra el STACK. Indica donde esta almacenado el código para la ejecución del programa. Registro complementario para no modificar el SS. Alacena una dirección que nos indica donde se encuentra el vector de datos. Contiene una dirección donde se copiara el vector de datos indicado por SI. (STACK POINTER) Permite saber donde se encuentra el último dato almacenado en el STACK. Siempre debe ser mayor o igual al SS o BP (INSTRUCTION POINTER) También llamado PROGRAM COUNTER. Tiene almacenada la dirección de la próxima instrucción a ser ejecutada. Ahora pasemos al registro bandera o STATUS REGISTER, que nos da el resultado de la actuación de la ALU Señal Overflow Direction Interrupts Sign Zero Auxiliary Carry Parity Carry REF NV UP DI PL NZ NA Función No hay Hacia adelante Desactivadas Valor positivo No es cero No hay acarreo REF OV DN EI NG ZR AC Función Hay Hacia atrás Desactivadas Valor negativo Es cero Hay acarreo PO NC Paridad impar No hay acarreo PE CY Paridad Par Se produjo acarreo El comando r (registro) nos permite interactuar con los registros de la CPU, posibilitando modificar sus contenidos. Cuando tipeamos r sin ningún otro parámetro nos muestra todos los registros con sus respectivos contenidos, pero si agregamos un parámetro nos va a mostrar solo el contenido del registro que nosotros mencionamos: -r bx BX 0000 : Como podemos observar no nos devuelve el signo – sino que ahora nos muestra : para que ingresemos el valor que queremos que sea almacenado en el registro BX. En el ejemplo vemos que BX tiene un valor 0000. Si ingresamos 5555 en : tendremos: -r bx BX 0000 :5555 -r AX=0000 BX=5555 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=1987 ES=1987 SS=1987 CS=1987 IP=0100 NV UP EI PL NZ NA PO NC 1987:0100 8936C7DE MOV [DEC7],SI DS:DEC7=0000 En negrilla vemos que el registro BX quedó modificado con el nuevo valor tipeado. Suma y Resta. Ejemplo S1: Se pide sumar dos valores (200 y FFF) . Vamos a ingresar las siguientes instrucciones en el orden como se dan. Los números indicados - a 100 XXXX: 0100 XXXX: 0103 XXXX: 0106 XXXX: 0108 XXXX: 010A - Indica que se debe comenzar a ingresar datos a partir de la posición 100 MOV AX, 200 Mover 200 al acumulador (AX) MOV BX, FFF Mover FFF al Registro Base (BX) ADD AX, BX Sumar BX a AX INT 20 Dar enter Aparece el signo del DEBUG que tiene el control. -a 1987:0100 mov ax,200 1987:0103 mov bx,FFF 1987:0106 add ax,bx 1987:0108 int 20 1987:010A Ingresemos ahora el comando –r -u Este comando nos muestra nuestro programa compilado y muchas otras instrucciones que se encuentran en máquina pero que a nosotros no os interesan y que solo sirven para ensuciar nuestro razonamiento, por ello es preferible el comando –u XXXX XXXX (desde-hasta). 1987:0100 B80002 1987:0103 BBFF0F 1987:0106 01D8 1987:0108 CD20 1987:010A B2E8 1987:010C 7421 1987:010E A0C9DE 1987:0111 0AC9 1987:0113 7505 1987:0115 3A45FF 1987:0118 7401 1987:011A AA 1987:011B 8B34 1987:011D 007619 MOV MOV ADD INT MOV JZ MOV OR JNZ CMP JZ STOSB MOV ADD AX,0200 BX,0FFF AX,BX 20 DL,E8 01,2F AL,[DEC9] CL,CL 011A AL,[DI-01] 011B SI,[SI] [BP+19],DH - por ello es preferible el comando –u XXXX XXXX (desde-hasta). Si ingresamos el comando –u0100 0108 nos muestra el programa compilado. No tipeamos hasta 010A porque esta posición de memoria no la utilizamos y aparece instruccines que nosotros no hemos introducido en el sistema. -u 0100 0108 1987:0100 B80002 1987:0103 BBFF0F 1987:0106 01D8 1987:0108 CD20 - MOV AX,0200 MOV BX,0FFF ADD AX,BX INT 20 Hagamos un alto y veamos como queda nuestro programa. En la primer columna tenemos las posición de nuestras instrucciones comenzando desde la posición 0100 (las 4 primeras indican también la posición pero a ellas no nos referiremos por el momento). En la segunda aparece la compilación. Aquí hay algo realmente curioso: B80002 – El primer byte es el código de operación. Fácil de entender. El segundo corresponde a los dos últimos dígitos del número que nosotros queremos cargar en el acumulador. El tercer byte tiene los dos primeros número del número que nosotros ingresamos. Es decir que 0200 se representa en memoria como 0020. Complicado pero así funciona el INTEL y no vamos ahora a entrar en detalle. En la tercera y cuarta las instrucciones que nosotros ingresamos en lenguaje simbólico. Llegó el momento de analizar los diferentes tamaños de las instrucciones que utilizamos: La primera y segunda corresponden a la sentencia MOV (mover) y tienen un longitud de 3 (tres ) bytes. La tercera corresponde a una instrucción de suma y tiene solo dos. La cuarta también tiene dos. Ejemplo S2: Como queda en memoria almacenado nuestro programa. Para ver nuestro programa almacenado debemos tipear el comando: -d (DISPLAY) que nos muestra la memoria. Esta está dividida en dos partes: a) La comprendida por caracteres hexadecimales que nos permiten ver todo el contenido de la memoria porque la combinación de bits en un nibble (4 bits) siempre tiene representación en hexadecimal. b) En caracteres, en castellano o ingles, pero noten que es inentendible porque normalmente la configuración de memoria no tiene una estructura semántica y sintáctica que podamos comprender. En otros ejercicios veremos que si podemos leer desde la memoria caracteres comprensibles. c) El guión que separa en dos partes la memoria expresada en hexadecimal no indica el cambio de palabra. Hasta donde llega nuestro programa está subrayado. 1987:0100 1987:0110 1987:0120 1987:0130 1987:0140 1987:0150 1987:0160 1987:0170 B8 00 02 BB FF 0F 01 D8 - CD 20 B2 E8 74 21 A0 C9 DE 0A C9 75 05 3A 45 FF - 74 01 AA 8B 34 00 76 19 C0 75 FA BA B2 E8 C7 06 - 19 DF CA 83 E8 10 00 0A DB 74 04 9D F8 EB 02 9D - F9 5E 5F 5A 59 5B C3 51 52 57 56 9C 8B FA 8B F2 - E8 6B F4 A2 DB E2 BF 98 DE 0A C0 74 03 BF F3 E5 - B9 13 00 E8 1E F5 72 65 C7 06 CA DE 00 00 C6 06 - CC DE 00 80 3E DB E2 00 74 07 81 C6 04 01 E8 A8 - F5 E8 52 00 3B 06 CA DE ......... ..t!.. ...u.:E.t...4.v. .u.............. .t.......^_ZY[.Q RWV......k...... ...t..........re ...........>... t.........R.;... - El resto es basura que no nos pertenece. Si nosotros podemos leer esa basura, se pueden imaginar que importante puede ser todo esta que queda en la memoria para un HACKER. Ejercicio 5: Se pide sumar dos direcciones. Para este ejercicio nos falta conocer como se informan las direcciones. La manera es simple, entre corchetes [ ]. Ingrese las instrucciones que se dan a continuación. -a 1987:0100 mov ax,[0200] 1987:0103 mov cx,[0FFF] 1987:0107 add ax,cx 1987:0109 int 20 1987:010B Ahora vamos a ejecutar el programa. Partimos del comando r para que nos muestre el estado de los registros y la primera instrucción del programa. -r AX=0000 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=1987 ES=1987 SS=1987 CS=1987 IP=0100 NV UP EI PL NZ NA PO NC 1987:0100 A10002 MOV AX,[0200] DS:0200=A708 Vemos que AX = 0000 que CX= 0000 y que la dirección [0200] = A708 que está indicada por el registro DS que se encuentra en la parte inferior derecha del ejemplo y en negrilla. Ahora vamos a usar el comando TRACE que se representa por la letra t. Este nos permite ver paso a paso que sucede en nuestro computador. -t AX=A708 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=1987 ES=1987 SS=1987 CS=1987 IP=0103 NV UP EI PL NZ NA PO NC 1987:0103 8B0EFF0F MOV CX,[0FFF] DS:0FFF=DB52 Vemos que la primera instrucción modificó el contenido del registro AX con el valor de DS. Esto está bien, porque es lo que nosotros pedimos. Si volvemos a tipear t ejecutaremos la segunda instrucción. -t AX=A708 BX=0000 CX=DB52 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=1987 ES=1987 SS=1987 CS=1987 IP=0107 NV UP EI PL NZ NA PO NC 1987:0107 01C8 ADD AX,CX Vemos que ahora no aparece el registro DS porque en la instrucción que se va a ejecutar no mencionamos direcciones. -t AX=825A BX=0000 CX=DB52 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=1987 ES=1987 SS=1987 CS=1987 IP=0109 NV UP EI NG NZ NA PE CY 1987:0109 CD20 INT 20 Se ha realizado la suma de los dos registros y algunas cosas se han modificado. a) El registro AX se ha modificado pero notemos que el nuevo valor es inferior al que ya teníamos almacenado. ¿Porqué? La respuesta es simple porque se ha producido un acarreo. Se recomienda realizar la suma manualmente para comprobar que lo sucedido es cierto. b) Veamos que el STATUS REGISTER ha modificado su valor indicándonos que eso ha sucedido, para mayor claridad lo marcamos en negrilla y en color. c) Compárelo con el DISPLAY anterior. Por último ejecutemos INT 20. -t AX=825A BX=0000 CX=DB52 DX=0000 SP=FFE8 BP=0000 SI=0000 DI=0000 DS=1987 ES=1987 SS=1987 CS=00CA IP=0FA8 NV UP DI NG NZ NA PE CY 00CA:0FA8 90 NOP Observemos que la nueva instrucción que aparece es un NOP (NO OPERATION) indicándonos que el programa ha terminado. NOTA: Podemos ejecutar directamente (t) pero nos mostrará la segunda instrucción a ejecutarse y la primera ya ejecutada. Tipee q en la línea de comando, vuelva a tipear DEBUG y cargue nuevamente el programa, posteriormente empiece directamente con el TRACE. Resolver e informar. Utilice el comando TRACE (t) para ejecutar el programa. Ejercicio 1. Sumar el contenido de una dirección y de una constante. Ejercicio 2: Reste dos números utilizando registros. El primero menor que el segundo. La instrucción para restar es SUB. Verifique el valor de los bits del STATUS REGISTER Ejercicio 3: Suma y resta. Sume dos números y reste otro. Utilice constantes, no direcciones. Verifique el valor de los bits del STATUS REGISTER Ejercicio 4: Sume dos números y reste una dirección. División del acumulador en dos partes. Si ejecutamos el comando r podemos ver el contenido del acumulador. -r AX=0000 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=1987 ES=1987 SS=1987 CS=1987 IP=0100 NV UP EI PL NZ NA PO NC 1987:0100 A10002 MOV AX,[0200] DS:0200=A708 Como vemos AX = 0000 si tipeamos el comando r ax nos permite modificar el el acumulador, como muestra el ejemplo. -rax AX 0000 :faf7 -r AX=FAF7 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=1987 ES=1987 SS=1987 CS=1987 IP=0100 NV UP EI PL NZ NA PO NC 1987:0100 A10002 MOV AX,[0200] DS:0200=A708 Comprobamos que está modificado. Pero también podríamos hacerlo de otra manera. Como dice el título el registro AX lo podemos dividir en parte alta y parte baja siendo sus códigos de reconocimiento AH (ACUMULATOR HIGH) y AL (ACUMULATOR LOW). Entones podemos escribir lo siguiente: -a 0100 1987:0100 mov ah,03 1987:0102 int 20 1987:0104 y ejecutarlo como lo hacemos hasta el presente (con el TRACE). -r AX=FAF7 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=1987 ES=1987 SS=1987 CS=1987 IP=0100 NV UP EI PL NZ NA PO NC 1987:0100 B403 MOV AH,03 Observemos que cuando se ejecutó la instrucción MOV AH,03 el registro AX quedo modificado en su parte superior por el valor (03) que ingresamos. -t AX=03F7 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=1987 ES=1987 SS=1987 CS=1987 IP=0102 NV UP EI PL NZ NA PO NC 1987:0102 CD20 INT 20 -t AX=03F7 BX=0000 CX=0000 DX=0000 SP=FFE8 BP=0000 SI=0000 DI=0000 DS=1987 ES=1987 SS=1987 CS=00CA IP=0FA8 NV UP DI PL NZ NA PO NC 00CA:0FA8 90 NOP Así terminamos de ejecutar esta parte. Hagamos lo mismo con la parte inferior. -a100 1987:0100 mov al,bb 1987:0102 int 20 1987:0104 -r AX=03FF BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=1987 ES=1987 SS=1987 CS=1987 IP=0100 NV UP EI PL NZ NA PO NC 1987:0100 B0BB MOV AL,BB -t AX=03BB BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=1987 ES=1987 SS=1987 CS=1987 IP=0102 NV UP EI PL NZ NA PO NC 1987:0102 CD20 INT 20 -t AX=03BB BX=0000 CX=0000 DX=0000 SP=FFE8 BP=0000 SI=0000 DI=0000 DS=1987 ES=1987 SS=1987 CS=00CA IP=0FA8 NV UP DI PL NZ NA PO NC 00CA:0FA8 90 NOP Ahora vamos a sumar las dos partes que componen el acumulador (AX). Para eso hacemos el siguiente programa. -a100 00CA:0100 add ah,al 00CA:0102 int 20 00CA:0104 y lo ejecutamos. -r AX=03BB BX=0000 CX=0000 DX=0000 SP=FFE8 BP=0000 SI=0000 DI=0000 DS=1987 ES=1987 SS=1987 CS=00CA IP=0100 NV UP DI PL NZ NA PO NC 00CA:0100 00C4 ADD AH,AL -t AX=BEBB BX=0000 CX=0000 DX=0000 SP=FFE8 BP=0000 SI=0000 DI=0000 DS=1987 ES=1987 SS=1987 CS=00CA IP=0102 NV UP DI NG NZ NA PE NC 00CA:0102 CD20 INT 20 Podemos realizar la comprobación del resultado muy fácilmente. Multiplicación y división. En lo referente a la multiplicación podemos determinar dos tipos de instrucciones: MUL multiplica valores sin signo. IMUL multiplica valores con signo. Aquí tenemos algunas variantes que no se observaron el la suma y en la resta. Podemos multiplicar entidades de 8 bites y de 16 bits (una palabra) o 16 y 32 o... dependiendo del tamaño de la palabra y del procesador que estamos utilizando. Independientemente si queremos multiplicar por media palabra el valor debe estar en la parte baja del registro que vamo a utilizar, por ejemplo en AL y si queremos multiplicar por la palabra deberá ocupar todo el registro, es decir que deberá estar en AX por ejemplo. Ejemplo M1: Multiplicar valores de 8 bits sin signo Ingresamos el programa: C:\>debug -a 1987:0100 mov al,4 1987:0102 mov cl,5 1987:0104 mul al,cl 1987:0106 int 20 1987:0108 -g106 AX=0010 BX=0000 CX=0005 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=1987 ES=1987 SS=1987 CS=1987 IP=0106 NV UP EI PL NZ NA PO NC 1987:0106 CD20 INT 20 Dos cosas importantes. La primera es que el programa se ha ejecutado y vemos el resultado en AX y podemos comprobar que está correcto y la segunda es que estamos usando un nuevo comando que es g que nos permite ejecutar completamente el programa que nosotros cargamos y nos muestra el resultado. Este tiene dos opciones: En el ejemplo M1 hemos ejecutado el programa parcialmente puesto que apuntamos hasta la instrucción almacenada en 0106 que es int 20, pero podemos ejecutar el programa hasta la 108 o 0108 ysucedería esto: -g108 El programa ha finalizado con normalidad -r AX=0000 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=1987 ES=1987 SS=1987 CS=1987 IP=0100 NV UP EI PL NZ NA PO NC 1987:0100 B004 MOV AL,04 Se ejecutó el programa totalmente y nos informa su correcta terminación pero no se muestran las variaciones de los registros. Ejecicio M2: Multiplicación de valores que provoquen un desbordamiento. En este caso vamos a utilizar dos valores que multiplicados superen la capacidad de almacenamiento de la parte baja del registro. -a 1987:0100 mov al,bb 1987:0102 mov cl,aa 1987:0104 mul al,cl 1987:0106 int 20 1987:0108 -g108 El programa ha finalizado con normalidad -r AX=0000 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=1987 ES=1987 SS=1987 CS=1987 IP=0100 NV UP EI PL NZ NA PO NC 1987:0100 B0BB MOV AL,BB En este caso no nos sirve de mucho, porque no nos deja ver nada, no muestra los resultados y solo podemos saber que el programa hace algo y que no da error, pero nada más. Por lo tanto siempres es preferible ingresar por el TRACE (t) para ver paso a paso que sucede. -r AX=0000 BX=0000 DS=1987 ES=1987 1987:0100 B0BB -t AX=00BB BX=0000 DS=1987 ES=1987 1987:0102 B1AA -t AX=00BB BX=0000 DS=1987 ES=1987 1987:0104 F6E0 -t AX=8899 BX=0000 DS=1987 ES=1987 1987:0106 CD20 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 SS=1987 CS=1987 IP=0100 NV UP EI PL NZ NA PO NC MOV AL,BB CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 SS=1987 CS=1987 IP=0102 NV UP EI PL NZ NA PO NC MOV CL,AA CX=00AA DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 SS=1987 CS=1987 IP=0104 NV UP EI PL NZ NA PO NC MUL AL CX=00AA DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 SS=1987 CS=1987 IP=0106 OV UP EI PL NZ NA PO CY INT 20 Realicen el cálculo de la multiplicación manualmente y observen que es lo que sucedió y porduzcan un informe con ello. Ejercicio M3: Multiplicación de valores con signo. -a 1987:0100 mov al,8 1987:0102 mov cl,-2 1987:0104 imul cl 1987:0106 int 20 1987:0108 -u 0100 0108 1987:0100 B008 MOV AL,08 1987:0102 B1FE 1987:0104 F6E9 1987:0106 CD20 1987:0108 CC MOV CL,FE IMUL CL es igual que decir mul ax,cl INT 20 INT 3 Observemos que ya hay modificaciones . ¿Determine cuales y que es lo que sucedió y porqué? Ejecutamos el programa paso a paso. -r AX=0000 BX=0000 CX=0000 DX=0000 SP=FFE2 BP=0000 SI=0000 DI=0000 DS=1987 ES=1987 SS=1987 CS=1987 IP=0100 NV UP DI PL NZ NA PO NC 1987:0100 B008 MOV AL,08 -t AX=0008 BX=0000 CX=0000 DX=0000 SP=FFE2 BP=0000 SI=0000 DI=0000 DS=1987 ES=1987 SS=1987 CS=1987 IP=0102 NV UP DI PL NZ NA PO NC 1987:0102 B1FE MOV CL,FE -t AX=0008 BX=0000 CX=00FE DX=0000 SP=FFE2 BP=0000 SI=0000 DI=0000 DS=1987 ES=1987 SS=1987 CS=1987 IP=0104 NV UP DI PL NZ NA PO NC 1987:0104 F6E9 IMUL CL -t AX=FFF0 BX=0000 CX=00FE DX=0000 SP=FFE2 BP=0000 SI=0000 DI=0000 DS=1987 ES=1987 SS=1987 CS=1987 IP=0106 NV UP DI PL NZ NA PO NC 1987:0106 CD20 INT 20 Analicen que sucedió. ¿Qué pasa si tomamos AX en lugar de AL? ¿Qué sucedió con los bits de bandera? ¿Están correctos o hay errores en ellos? Realicen el informe correspondiente. Realice el mismo programa con la diferencia de la siguiente instrucción Mov cl,-1 e informe el análisis particular y comparativo Realizados los ejemplos anteriores y convenientemente analizados podemos pasar a realizar ejercicios con registros completos. Informe cada uno de los ejercicios. Ejercicio M1: Multiplique dos números. Ejercicio M2: Multiplique un número positivo por un número negativo a) Con valores pequeños. b) Con valores grandes. Ejercicio M3: Multiplique dos números con signo negativo. Ejercicio M4: Ingrese el siguiente programa y analice los resultados -a 100 1987:0100 mov bx,ffff 1987:0103 mov cx,-1 1987:0106 imul cx 1987:0108 imul bx 1987:010A int 20 1987:010C - División. También está compuesta por dos instrucciones: DIV que divide dos valores sin signo. IDIV que divide dos valores con signo. En una división de valores enteros vamos a suponer que el dividendo siempre será mayor que el divisor, por lo menos para esta primera parte de nuestro estudio. De acuerdo a lo expresado pasemos a realizar nuestro primer ejemplo. Ejemplo D1: Dividir dos número enteros. Aclaraciones: Para un divisor de 8 bits el dividendo será de 16 bits, por lo tanto el dividendo lo ubicaremos en AX (16 bits) y el divisor en CL (8bits) El programa es: -a 1987:0100 mov ax,8 1987:0103 mov cl,4 1987:0105 div cl Daría lo mismo escribir div ax,cl 1987:0107 int 20 1987:0109 -t AX=0008 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=1987 ES=1987 SS=1987 CS=1987 IP=0103 NV UP EI PL NZ NA PO NC 1987:0103 B104 MOV CL,04 -t AX=0008 BX=0000 CX=0004 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=1987 ES=1987 SS=1987 CS=1987 IP=0105 NV UP EI PL NZ NA PO NC 1987:0105 F6F1 -t DIV CL AX=0002 BX=0000 CX=0004 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=1987 ES=1987 SS=1987 CS=1987 IP=0107 NV UP EI NG NZ AC PE CY 1987:0107 CD20 INT 20 Ejercicio D1: Realicen un programa utilizando dos números que no sean múltiplos y analaice el registro AX. Ejercicio D2: Realice un programa cuyo divisor sea cero e informe que sucede y porqué. Ejercicio D3: Realice un programa que permita dividir los siguientes valores FFFF y 2, pero en ste caso el divisor será BX. Observe todos los registros e informe. Ejercicio D4: Realice un programa que permita la diviidr FFFF por –1 y analice. Bifurcaciones condicionales, incondicionales y repeticiones. Cuando hacemos un programa seguramente tendremos ue realizar en algún momento una pregunta que nos permita testear un registro, variable, archivo, etc., y optar por realizar tal o cual cosa dependiendo de que resultado nos devuelva el dato consultado. Por otro lado también existe la psibilidad de que después de ejecutar una serie de instrucciones debamos continuar el programa por otro lado saltando un montón de instrucciones, en este caso estamos utilizando un salto inconsicional , no hay ninguna condición previa , y por último podemos realizar una serie de repeticiones o iteraciones o LOOPS dentro de nuestro programa. Esto sucede enla mayoría de los programas y es por eso que esta nueva sección investiga las tres posibilidades. Ejemplo B1: Realizar un programa con un salto condicional. Para visualizar mejor las posibilidades de Verdadero y Falso que se pueden presentar utilizaremos dos variables alfabéticas. El programa -a 1987:0100 jmp 0113 1987:0102 -e 102 "Saltamos varias instrucciones verdad " 0d 0a "$" -a 113 1987:0113 mov dx,102 1987:0116 mov ah,9 1987:0118 int 21 1987:011A int 20 1987:011C -g Saltamos varias instrucciones verdad El programa ha finalizado con normalidad Para analizar las instrucciones que saltamos debemos hacer: -u 100 011a 1987:0100 EB11 JMP 0113 1987:0102 53 PUSH BX 1987:0103 61 DB 61 1987:0104 6C DB 6C 1987:0105 7461 JZ 0168 1987:0107 6D DB 6D 1987:0108 6F DB 6F 1987:0109 7320 JNB 012B 1987:010B 7661 JBE 016E 1987:010D 7269 JB 0178 1987:010F 61 DB 61 1987:0110 7320 JNB 0132 1987:0112 69 DB 69 1987:0113 BA0201 MOV DX,0102 1987:0116 B409 MOV AH,09 1987:0118 CD21 INT 21 1987:011A CD20 INT 20 En negrilla todas las instrucciones que saltamos, que por supuesto no son de nuestro programa. Otra manera de v er la ejecución de nuestro programa es utilizando el comando p. En este caso aconsejamos hacerlo indicando además la instrucción desde donde debe comenzar como en la secuencia que sigue. -p 100 AX=0000 BX=0000 CX=0000 DX=0102 SP=FFEE BP=0000 SI=0000 DI=0000 DS=1987 ES=1987 SS=1987 CS=1987 IP=0116 NV UP EI PL NZ NA PO NC 1987:0116 B409 MOV AH,09 AX=0900 BX=0000 CX=0000 DX=0102 SP=FFEE BP=0000 SI=0000 DI=0000 DS=1987 ES=1987 SS=1987 CS=1987 IP=0118 NV UP EI PL NZ NA PO NC 1987:0118 CD21 INT 21 HEMOS SALTADO VAR¦[1]¦ -!¦ UCCIONES VERDAD AX=0924 BX=0000 CX=0000 DX=0102 SP=FFEE BP=0000 SI=0000 DI=0000 DS=1987 ES=1987 SS=1987 CS=1987 IP=011A NV UP EI PL NZ NA PO NC 1987:011A CD20 INT 20 El programa ha finalizado con normalidad - Pasaje de datos entre registros. Para realizar este ejercicio vamos a utilizar una nueva intrucción que es XCHG, que realiza el pasaje del contenido entre dos registros. No importa la manera en que de especifiquen los registros en la instrucción. Para ello damos el siguiente ejemplo: C:\>debug -a 100 1987:0100 mov ax,333 1987:0103 mov bx,222 1987:0106 xchg bx,ax 1987:0107 int 20 1987:0109 -t 3 AX=0333 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=1987 ES=1987 SS=1987 CS=1987 IP=0103 NV UP EI PL NZ NA PO NC 1987:0103 BB2202 MOV BX,0222 AX=0333 BX=0222 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=1987 ES=1987 SS=1987 CS=1987 IP=0106 NV UP EI PL NZ NA PO NC 1987:0106 93 XCHG BX,AX AX=0222 BX=0333 CX=0000 DX=0000 DS=1987 ES=1987 SS=1987 CS=1987 1987:0107 CD20 INT 20 o bien IP 0108 :100 -u100 108 1987:0100 B83303 MOV AX,0333 1987:0103 BB2202 MOV BX,0222 1987:0106 87C3 XCHG AX,BX 1987:0108 CD20 INT 20 -r AX=0222 BX=0333 CX=0000 DX=0000 DS=1987 ES=1987 SS=1987 CS=1987 1987:0100 B83303 MOV AX,0333 -t3 SP=FFEE BP=0000 SI=0000 DI=0000 IP=0107 NV UP EI PL NZ NA PO NC SP=FFEE BP=0000 SI=0000 DI=0000 IP=0100 NV UP EI PL NZ NA PO NC AX=0333 BX=0333 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=1987 ES=1987 SS=1987 CS=1987 IP=0103 NV UP EI PL NZ NA PO NC 1987:0103 BB2202 MOV BX,0222 AX=0333 BX=0222 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=1987 ES=1987 SS=1987 CS=1987 IP=0106 NV UP EI PL NZ NA PO NC 1987:0106 87C3 XCHG AX,BX AX=0222 BX=0333 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=1987 ES=1987 SS=1987 CS=1987 IP=0108 NV UP EI PL NZ NA PO NC 1987:0108 CD20 INT 20 Como podemos observar lo dicho anteriormente se cumple. Manejo de Disco con el DEBUGER Para comenzar vamos a formatear un diskette de la manera tradicional. El comando para realizar el formateo, para los que no lo recuerdan, es: FORMAT A:/S. C:\>format a:/s Inserte un nuevo disco en la unidad A: y presione Entrar cuando esté listo... Comprobando el formato del disco. Comprobando 1,44 MB Formato completado. Sistema transferido ¿Nombre del volumen? (11 caracteres, Entrar para ninguno)? PRUEBA1 1.457.664 bytes de espacio total en disco 389.632 bytes utilizados por el sistema 1.068.032 bytes disponibles en disco 512 bytes en cada unidad de asignación. 2.086 unidades de asignación libres en disco. El número de serie del volumen es 0A1B-1ED8 ¿Desea formatear otro disco (S/N)?N Bueno ya lo tenemos formateado. Ahora vamos a verificar la información que tenemos en el diskette. Para ello entramos en el DEBUG Como lo hacemos habitualmente. Una vez en el DEBUG vamos a utilizar el comando D (DUMP) indicándole la dirección desde la cual queremos empezar. Y mostrará lo siguiente. Comando Significado ?? Permite ver el set de instrucciones básico del Assembler a Abre el DEBUG sentencias g Permite la ejecutar un programa en forma completa o parcial r Permite ver el estados de los registros t Muestra paso a paso la ejecución. Corresponde al comando TRACE. para ingresar