      ASM POR AESOFT. (leccin 8).
      --------------------------------------------------------------------
     - DUDAS DE LECCIONES ANTERIORES
     - SOLUCION AL EJERCICIO DE LA LECCION ANTERIOR
     - CONJUNTO DE INSTRUCCIONES DEL 8086(II):
       * Operaciones lgicas  booleanas
         (Continuacin del apartado Operaciones de manejo de bits, leccin 7).
       * Operaciones de manejo de hileras o cadenas de caracteres.
      --------------------------------------------------------------------

      Saludos, mis queridos programadores. :-))

      En la leccin de hoy, vamos a seguir con la relacin de las instrucciones
      del 8086.

      Tambin veremos en primer lugar la respuesta que le doy a un usuario
      acerca de unas dudas que me plantea. Dicho mensaje me parece de inters
      general, por eso lo incluyo en la leccin de hoy.

      Por ltimo, aunque no en ltimo lugar, dar la solucin al sencillo
      ejercicio que os propuse en la leccin anterior, ya que parece que
      nadie me ha dicho cmo resolverlo.



     - DUDAS DE LECCIONES ANTERIORES
     -------------------------------
     A continuacin os muestro un mensaje que considero de inters para
     todas las personas que siguen el curso:

--- -----------------------------------   inicio del mensaje.

 >       Cada uno de estos registros tiene funciones
 > especiales que es interesante
 >       conocer. Por ejemplo el registro AX es el
 > llamado acumulador, hace que
 >       muchas operaciones tengan una forma ms corta,
 > ya que lo especifican
 >       implcitamente. Es decir, que hay operaciones
 > que actan sobre el
 >       registro AX en particular.

 AJ> Con esto te refieres por ejemplo a cuando se llama a una
 AJ> interrupcion con un valor en AX sin que tengamos que indicarle para
 AJ> nada donde tiene que encontrar ese valor, puesto que ya sabe que lo va
 AJ> a encontrar en AX :-?

     Me refera ms bien a ciertas instrucciones aritmticas, que presuponen
     que un operando se encuentra almacenado en AX, y el otro operando puede
     estar en cualquiera de los otros registros.
     Cuando leas la leccin 7 (que debes tener ya en tus manos) comprenders
     esto mejor.

     El registro AX (como acumulador que es), se utiliza en otras muchas
     instrucciones de forma implcita (esto es, que no es necesario indicarlo
     expresamente). Entre estas otras instrucciones podemos encontrar ciertas
     instrucciones de transferencia de cadenas de caracteres: LODS y STOS,
     que utilizan el registro AL (en el caso de las instruccin LODSB y STOSB)
      el registro AX (en el caso de las instruccin LODSW y STOSW).
     La diferencia entre estas instrucciones estriba en el hecho de trabajar
     con bytes (registros de 8 bits)  trabajar con palabras (registros de 16
     bits).
     Pero bueno, no me enrollo aqu ms, ya que estas instrucciones se
     desarrollan en la leccin 8.

     En cuanto a lo que me dices acerca de las interrupciones, no sera el
     ejemplo ms acertado, pero es vlido, ya que cuando llamas a una
     interrupcin (DOS, BIOS, etc.), sta sabe qu funcin de la interrupcin
     ejecutar gracias al registro AX, que contiene el nmero de dicha funcin.

     Entonces podemos decir que la instruccin INT (llamada a interrupcin),
     utiliza el registro AX implcitamente al no aludir en la sintaxis de dicha
     instruccin a tal registro, y utilizar la instruccin dicho registro
     para conocer el nmero de funcin que ejecutar.
     Obviamente antes de la instruccin INT, hemos tenido que cargar en AX
     (mediante la instruccin MOV, por ejemplo) el valor adecuado (nmero de
     la funcin a ejecutar).


 >       Af: Bit de carry auxiliar, se activa si una
 > operacin aritmtica produce
 >           acarreo de peso 16.

 AJ> que es eso de acarreo de peso 16?

     El peso (al hablar de los bits de un registro) es la posicin que ocupa
     un bit determinado dentro de un registro.
     Por decirlo de alguna manera, es la importancia de ese bit dentro del
     registro. Al igual que ocurre en la base decimal, en la que el dgito
     de ms a la derecha de un nmero es el menos importante (de menor peso),
     as ocurre en la base binaria (bits) y en el resto de las bases, por
     supuesto.

     Entonces cuando hablamos de acarreo de peso 16, nos referimos al acarreo
     que surge fruto de trabajar con los bits de mayor peso (peso 16), los
     de ms a la izquierda.

---  Una cosa que no dije en su momento:
     El flag Af (bit de carry auxiliar) se utiliza en operaciones decimales.
     No debe tenerse en cuenta en operaciones aritmticas con enteros.
     De cualquier modo, no es necesario prestarle demasiada atencin a este
     flag. Cuando uno empieza, nunca lo utiliza. Y cuando ya lleva mucho
     tiempo programando, tiene experiencia y hace cosas muy tcnicas que
     requieran de dicho flag... Entonces, evidentemente ya sabreis todo lo
     necesario acerca de l. :-))) O sea, que pasando de l.

 >     Venga, ahora quiero que me conteis dudas que
 > teneis, aclaraciones, etc.

 AJ> Como ves te he hecho caso y aqui tienes un par de dudillas ;-)

     Pues ah queda mi respuesta. Espero haberte ayudado.

--- ---------------------- fin del mensaje

     Espero que os haya parecido interesante.




     - SOLUCION AL EJERCICIO DE LA LECCION ANTERIOR
     ----------------------------------------------
     Esto es lo que os propona en la leccin anterior:

---
     A ver si alguien me dice cmo podemos modificar el flag Tf, por ejemplo.
     Os dar una pista: Recordais las instrucciones PUSHF y POPF?
     Espero vuestros mensajes. Si a nadie se le ocurre, ya dejar yo la
     solucin en una prxima leccin.
---

     Y aqu est la solucin:

     Debido a que no podemos acceder directamente a determinados bits del
     registro de estado (FLAGS), debemos realizar una serie de operaciones
     para que de esta forma nos sea posible la modificacin de los bits
     a los que no podemos acceder directamente.

     Si lo que queremos es poner el flag Tf con valor (1), entonces basta
     con realizar la siguiente operacin:

     MOV AX,0000000100000000b
     PUSH AX
     POPF

     La primera instruccin prepara un nuevo registro de estado (FLAGS) en el
     que como slo nos interesa el flag Tf, lo ponemos a 1 (que es lo que
     queremos), y los otros bits (flags) los dejamos a Cero, los podriamos
     haber dejado a 1 tambin. Para el caso que nos ocupa, da igual.

     La segunda instruccin deja este nuevo registro de estado en la pila.
     Esto se hace as, ya que tenemos una instruccin que sacar ese
     nuevo registro de estado de la pila, y lo pondr como nuevo registro
     de estado o FLAGS.
     La tercera lnea hace que el nuevo registro de estado sea la palabra
     introducida en la pila por la orden (PUSH AX).

     Es decir, se trata de utilizar la instruccin POPF para poder coger
     de la pila un nuevo registro de estado a gusto del programador,
     que previamente ha sido depositado en la pila (mediante PUSH registro).

     Si queremos poner el flag Tf con valor (0), basta con:

     MOV AX,0
     PUSH AX
     POPF


     Con lo expuesto hasta ahora se resolva el ejercicio que os ped, pero
     esto en la prctica no es nada til, ya que estamos 'machacando' el
     valor del resto de los flags, cuando slo queremos modificar uno
     en concreto. para evitar eso, nos valemos de las operaciones lgicas
     que vamos a ver a continuacin. Estas operaciones lgicas las utilizaremos
     (en este caso) para aislar el resto de los bits, y as mantener su valor
     original.

~~~  Una vez que hayais estudiado las operaciones lgicas que se desarrollan
     ms abajo, estareis en condiciones de solucionar el siguiente ejercicio:

...  Se trata de modificar el flag Tf, pero (y esto es muy importante) sin
     cambiar el valor del resto de flags.
     Espero que alguien me d la solucin (si lo haceis todos, mejor) :-)).



     - CONJUNTO DE INSTRUCCIONES DEL 8086 (II)
     -----------------------------------------

     Continuamos en este apartado con la relacin y explicacin de las
     instrucciones del 8086:

     * Operaciones lgicas  booleanas *
     (Continuacin de Operaciones de manejo de bits).
     Todos habreis visto que en las buenas calculadoras (os recuerdo que la
     mejor es SB-CALCU del programa SANBIT :-)) aparecen una serie de
     operaciones como son: NOT, AND, OR, etc... Pues bien, esas son las
     llamadas operaciones lgicas.
     En serio, os recomiendo que utiliceis el programa SANBIT para realizar
     todo tipo de operaciones booleanas (Un poco de publicidad :-)))

     Estas operaciones trabajan a nivel de bits, con un tamao de operando dado.
     Esto es, no es lo mismo un NOT (7) con un tipo de datos byte, que
     originara como resultado 248, que hacer un NOT (7) con un tipo de datos
     word, que originara como resultado 65528.
     Vemos pues, que el tipo de datos sobre el que se realiza una operacin
     lgica, condiciona el resultado de la operacin.

     La finalidad de estas instrucciones es modificar uno o varios bits
     concretos de un registro o una posicin de memoria. Son tiles para
     aislar ciertos bits, y trabajar con ellos como si fueran variables
     independientes. Es decir, usando adecuadamente estas operaciones lgicas,
     podemos tener hasta 16 variables de tipo lgico (valor 0  1) en un
     registro de tipo word.
     Como veremos a continuacin, estas operaciones se utilizan muchas veces
     para realizar con mayor rapidez y menor cdigo de ejecucin ciertas
     acciones, que por mtodos ms comunes acarrearan ms tiempo y cdigo.



     - NOT lgico.
     La operacin lgica NOT, consiste en sustituir los unos por ceros y
     viceversa en un operando dado.
     Sintaxis: NOT registro/posicin_de_memoria.
     Ejemplo: NOT AL.
     Supongamos que AL tiene el valor 99h. En binario tendramos:
     AL = 10011001.
     La instruccin lo que hace es invertir el valor de cada bit. Si antes
     de la instruccin vala 1, ahora valdr 0, y viceversa. Siguiendo este
     criterio, despus de realizar la operacin, AL valdr 01100110,
     que en base 16 (hexadecimal) es: AL = 66H.
     Si ejecutamos de nuevo la instruccin NOT AL, con el nuevo valor de AL,
     parece evidente lo que vamos a obtener, no?
     Por supuesto obtendremos el mismo valor que al principio: AL = 99h.

     Ejemplo: Veamos ahora qu sucede con la operacin NOT AX, suponiendo
     que AX = 99H.
     Ahora estamos trbajando sobre un operando de tamao word  palabra, por
     lo tanto, tenemos 16 bits a los que cambiar su valor.
     Antes de la instruccin, AX tena el valor 0000000010011001.
     Despus de la instruccin, AX = 1111111101100110.
     En base 16, AX = 0FF66H.

---  El primer 0 de 0FF66H se pone para que el ensamblador sepa que estamos
---  refirindonos a un nmero, y no a una variable llamada FF66H.


     - AND lgico.
     La operacin lgica AND, al igual que las restantes -y al contrario que
     la operacin NOT- opera sobre dos operandos.
     El resultado de la operacin se almacena en el primer operando, que puede
     ser un registro o una posicin de memoria.

     Este resultado se obtiene de la siguiente manera:
     Se compara cada uno de los bits del primer operando con sus
     correspondientes bits del segundo operando. Si ambos tienen el valor (1),
     el bit correspondiente del operando resultado se pone a valor (1). Por
     el contrario, si alguno de los dos bits (o los dos bits) tiene valor (0),
     el bit correspondiente del operando resultado valdr (0).
     De ah viene el nombre de la instruccin: AND ... Uno y (AND) otro,
     los dos bits deben tener valor (1) para que el bit correspondiente del
     resultado tenga valor (1).
     Esta operacin se utiliza para poner a (0) determinados bits.

     Sintaxis: AND registro,registro
               AND registro,posicin_de_memoria
               AND registro,valor_inmediato
               AND posicin_de_memoria,registro
               AND posicin_de_memoria,valor_inmediato


     Ejemplo: Supongamos que AX = 1717H  y VAR1 (Variable con la que accedemos
     a una posicin de memoria de tipo Word) tiene el valor 9876H.
     En binario tendramos:

                           AX = 0001011100010111
                         VAR1 = 1001100001110110

     Veamos cmo se realizara la operacin lgica (AND AX,VAR1)...
     Se trata de operandos de tipo word (16 bits), por tanto hay que realizar
     16 operaciones (1 para cada posicin de bit) con los bits.
     Ya hemos visto ms arriba la forma en que opera esta instruccin.
     Veamos qu resultado nos dara:

                           AX = 0001011100010111
                         VAR1 = 1001100001110110
                         -----------------------
     Tras la instruccin:  AX = 0001000000010110, que pasado a base 16 nos
     queda AX = 1016h.

     - OR lgico.
     La operacin lgica OR se utiliza al contrario que la operacin AND, para
     poner a (1) determinados bits de un registro o posicin de memoria.
     La operacin lgica OR, opera sobre dos operandos, almacenando el
     resultado de dicha operacin en el primer operando, que puede ser un
     registro o una posicin de memoria.

     Este resultado se obtiene de la siguiente manera:
     Se compara cada uno de los bits del primer operando con sus
     correspondientes bits del segundo operando. Si alguno tiene el valor (1),
     el bit correspondiente del operando resultado se pone a valor (1). Por
     el contrario, si los dos bits tiene valor (0), el bit correspondiente del
     operando resultado valdr (0).
     De ah viene el nombre de la instruccin: OR ... Uno u (OR) otro,
     con que uno slo de los dos bits tenga valor (1), el bit correspondiente
     del resultado tendr valor (1).

     Sintaxis: OR registro,registro
               OR registro,posicin_de_memoria
               OR registro,valor_inmediato
               OR posicin_de_memoria,registro
               OR posicin_de_memoria,valor_inmediato


     Ejemplo: Supongamos que CL = 25H  y COLUM (Variable con la que accedemos
     a una posicin de memoria de tipo Byte) tiene el valor 0AEH.
     En binario tendramos:

                        COLUM = 10101110
                           CL = 00100101

     Veamos cmo se realizara la operacin lgica (OR COLUM,CL)...
     Se trata de operandos de tipo byte (8 bits), por tanto hay que realizar
     8 operaciones (1 para cada posicin de bit) con los bits.
     Veamos qu resultado nos dara:

                           COLUM = 10101110
                           CL    = 00100101
                         -----------------------
     Tras la instruccin:  COLUM = 10101111, que pasado a base 16,
     nos queda la variable COLUM = 0AFH.

   - XOR (OR Exclusivo).
     La instruccin XOR opera en modo parecido a OR, pero con una
     diferencia muy importante, que le hace tener el sobrenombre de
     OR Exclusivo:

     Se compara cada uno de los bits del primer operando con sus
     correspondientes bits del segundo operando. Si uno y slo uno de ambos
     bits comparados tiene valor (1) -obviamente el otro bit debe ser (0),
     es decir, ambos bits tienen diferente valor-, entonces el bit
     correspondiente del resultado tendr valor (0)

     He aqu la diferencia con la instruccin OR:
     Mientras que la operacin OR admita que uno o los dos bits fuera (1) para
     poner a (1) el bit resultante, la instruccin XOR exige que slo uno de
     esos bits tenga valor (1), es decir, que ambos bits tengan diferente valor.

     Sintaxis: XOR registro,registro
               XOR registro,posicin_de_memoria
               XOR registro,valor_inmediato
               XOR posicin_de_memoria,registro
               XOR posicin_de_memoria,valor_inmediato

     Esta instruccin se utiliza normalmente para poner a Cero un registro.
     Es la manera ms rpida de poner a cero un registro.
     Vemoslo con un ejemplo:

     Supongamos que queremos poner a cero el registro AX.
     Da igual el valor que tenga AX para obtener el resultado final de la
     siguiente operacin, pero le damos por ejemplo el valor AX = 2637h.
     En binario tendramos: AX = 0010011000110111

     Si realizamos la operacin (XOR AX,AX), cul podra ser el resultado a
     almacenar en AX?
     Parece evidente, no? Hemos quedado en que el bit resultante tiene
     valor (1) si los dos bits comparados son diferentes, entonces llegamos
     a la conclusin que todos los bits del resultado van a tener valor (0),
     ya que al comparar un registro consigo mismo, todos y cada uno de los
     bits de ambos registros (que en realidad es el mismo registro) son
     iguales de uno a otro registro.

     Veamos cmo se realizara la operacin lgica (XOR AX,AX)...
     Se trata de operandos de tipo word (16 bits), por tanto hay que realizar
     16 operaciones (1 para cada posicin de bit) con los bits.
     Veamos qu resultado nos dara:

                           AX = 0010011000110111
                           AX = 0010011000110111
                         -----------------------
     Tras la instruccin:  AX = 0000000000000000, ya que todas las parejas de
     bits comparados tienen el mismo valor.

     Esta forma de borrar un registro es muy rpida, y gener muy poco cdigo
     ejecutable.
     Vamos a comparar este mtodo con el 'tradicional' (MOV AX,0):

     La instruccin (MOV AX,0) tiene un cdigo ejecutable de 3 bytes, y tarda
     en realizarse 4 pulsos de reloj.
     Mientras que la instruccin (XOR AX,AX) tiene un cdigo de 2 bytes, y
     tarda en realizarse 3 pulsos de reloj.

     Puede parecer que la diferencia no es muy grande, pero cuando se ejecutan
     miles o millones de estas instrucciones en un programa, se nota la
     diferencia.


     - TEST.
     Esta operacin es similar a AND, pero con una diferencia muy importante:
     La instruccin TEST no modifica el valor de los operandos, sino slo
     el registro de estado (FLAGS).
     Para realizar la operacin utiliza registros internos del procesador, de
     esta manera, los operandos pasados a la instruccin TEST, no se ven
     alterados.
     Esta instruccin se realiza para comprobar el valor de un cierto bit 
     ciertos bits dentro de un registro.

     Sintaxis: TEST registro,registro
               TEST registro,posicin_de_memoria
               TEST registro,valor_inmediato
               TEST posicin_de_memoria,registro
               TEST posicin_de_memoria,valor_inmediato

     Veamos un ejemplo:

     Existen dos posiciones de memoria de tipo byte consecutivas que utiliza
     la ROM BIOS para mantener y actualizar el estado de ciertas teclas
     especiales.
     Para este ejemplo, nos interesa slo la primera posicin 0000:0417H.
     Es decir, la posicin 0417h dentro del segmento 0000h.

     Esta posicin de memoria contiene las siguientes informaciones lgicas en
     cada uno de sus bits:

bit 7   6   5   4   3   2   1   0
  +-------------------------------+   Estado de teclas cuando el bit
                             correspondiente tiene valor (1).
  +-------------------------------+   ---------------------------------
                         
                         +---->  Tecla Mays. derecha pulsada.
                      +-------->  Tecla Mays. izquierda pulsada.
                   +------------>  Tecla Control pulsada.
                +---------------->  Tecla Alt pulsada.
             +-------------------->  Scroll Lock activado.
          +------------------------>  Num Lock activado.
       +---------------------------->  Caps Lock (Bloq Mays) activado.
    +-------------------------------->  Insert activado.


  Evidentemente, cuando el bit correspondiente a una informacin lgica
  en particular (Tecla ALT, p.e.) tiene valor (0), esto indica todo lo
  contrario a lo mostrado arriba. En el caso del bit 3 (tecla ALT),
  si estuviera con valor (0), querra decir que no est pulsada en estos
  momentos.


     El bit 7 (bit de mayor peso, o de ms a la izquierda) del byte
     direccionado por esa posicin de memoria, contiene informacin booleana
      lgica (valor verdadero  falso) acerca del modo de insercin de
     teclado.
     Es decir, mediante este bit podremos saber si el modo de insercin est
     activado o no.

     Debido a que hay otra serie de variables lgicas  booleanas dentro de
     este byte, no podemos realizar una comparacin a nivel de byte para
     conocer el estado de insertar.
     Esto es, no podemos escribir algo as como:
     CMP BYTE PTR ES:[DI],10000000b, ya que el resto de bits tienen un valor
     variable dependiente de ciertas circunstancias (mayscula izquierda
     pulsada, tecla ALT pulsada, etc).

     Debemos entonces usar la instruccin TEST, con la que podemos 'TESTar'
      examinar el valor de un determinado bit concreto.
     En el caso que nos ocupa (examinar el estado del modo de insercin),
     debemos examinar el valor del bit 7 de la posicin de memoria
     0000:0417h.

     Veamos todo el proceso:

;******** trozo de programa.

     XOR AX,AX ;
     MOV ES,AX ; Mediante estas dos instrucciones, hago que la base del
               ; segmento direccionado mediante el registro ES, se
               ; encuentre en la posicin 0000h (Al principio de la memoria
               ; del PC).
               ; Observaciones:
               ; - No es posible introducir un valor_inmediato en un
               ;   registro de segmento. Es decir, no podemos escribir algo
               ;   como: MOV ES,8394h. El procesador no lo permite.
               ;   Debemos, pues, valernos de otro registro, como AX, DX,
               ;   etc, para introducir el valor deseado en el registro de
               ;   segmento.
               ; - Utilizacin de la operacin lgica (XOR AX,AX) para poner
               ;   a Cero el registro AX, ganando en rapidez, y menor tamao
               ;   del programa ejecutable, en comparacin con (MOV AX,0).
               ; - Tenemos el registro ES apuntando ya al segmento adecuado.
               ;   Sigamos:

     TEST BYTE PTR ES:[0417H],10000000b ; Examinemos esta instruccin tan
               ;                          compleja en profundidad...
               ; - Vemos que su sintaxis es del tipo:
               ;   TEST posicin_de_memoria,valor_inmediato.
               ; - Debemos indicar que vamos a comparar una posicin de tipo
               ;   byte, para evitar errores. Eso lo hacemos mediante:
               ;   BYTE PTR.
               ; - Debemos indicar a continuacin el segmento y desplazamiento
               ;   donde se encuentra ese byte al que vamos a acceder:
               ;   ES:[0417H]
               ; - Utilizamos el nmero 10000000b como valor_inmediato. De
               ;   esta forma es como vamos a examinar el bit 7  de estado
               ;   de insertar.
               ;   Hemos visto que la instruccin TEST es un AND que no
               ;   modifica el valor de los operandos, sino slo los flags.
               ;   Por tanto, slo podemos saber el valor de ese bit 7,
               ;   comprobando el valor de los flags tras la operacin.
               ;   El flag que hay que 'mirar' es el flag Zf (flag Cero).
               ;   Si tras la operacin el flag Zf est con valor (1), esto
               ;   quiere decir que el bit 7 de ES:[0417H] est desactivado,
               ;   es decir, que estamos en estado de NO_INSERCION.
 ; Veamos grficamente el proceso de esta instruccin TEST para comprenderlo
 ; mejor:
 ;
 ; Vamos a suponer que el byte ES:[417H] tiene el siguiente valor: 10101110b.
 ; Es un valor que he puesto al azar para poder operar con algo concreto.
 ;
 ; Tenemos entonces los dos valores siguientes para hacer el TEST:
 ;
 ;                   ES:[0417H] = 10101110
 ;              valor_inmediato = 10000000
 ;             ---------------------------
 ; Tras la ejecucin, un registro interno del procesador (no accesible por
 ; el programador) tendr el siguiente valor: 10000000b
 ; Y el flag Zf que indica si el resultado tiene un valor Cero, estar puesto
 ; a (0), ya que el resultado tiene un valor distinto de cero.
 ; Por tanto, comprobando el valor del flag Zf tras la operacin, sabremos
 ; que insertar est en modo activo.

     JZ no_insertando ; Si el flag Zf tiene valor (1):
                      ; Hacemos un salto condicional a una posicin del
                      ; programa, en la que se realizan las acciones
                      ; pertinentes en el caso de que no est el teclado en
                      ; modo insercin.

     [....]           ; se realizan las instrucciones adecuadas para el caso
                      ; en que el teclado est en modo de insercin.


    JMP fin_insercion ; salto el trozo siguiente, reservado para cuando el
                      ; teclado est en modo de NO_INSERCION.

no_insertando:        ; indica el inicio del cdigo preparado para utilizar
                      ; en caso de NO_INSERCION.

     [....]           ; se realizan las instrucciones adecuadas para el caso
                      ; en que el teclado NO est en modo de insercin.


fin_insercion:        ; Hemos terminado de trabajar por ahora con el tema de
                      ; la insercin, pasamos a otra cosa dentro del programa.

        [....]        ; sigue el programa.




;****** fin del trozo de programa.

  Veamos cmo quedara sin tantas explicaciones:

;********* trozo de programa:

     XOR AX,AX
     MOV ES,AX
     TEST BYTE PTR ES:[0417H],10000000b
     JZ no_insertando
     [....] ;acciones para cuando INSERTANDO.
     JMP fin_insercion
no_insertando:
     [....] ;acciones para cuando NO_INSERTANDO.
fin_insercion:
     [....] ;sigue el programa.

;**********fin del trozo de programa.


     Supongamos ahora que el byte ES:[417H] tiene el siguiente valor:
     00100010b.
     Con este nuevo valor, el estado de insertar es falso (NO_INSERTAR).

     Tenemos entonces los dos valores siguientes para hacer el TEST:
                   ES:[0417H] = 00100010
              valor_inmediato = 10000000
             ---------------------------
     Tras la ejecucin, un registro interno del procesador tendr el siguiente
     valor: 00000000b
     Y el flag Zf que indica si el resultado tiene un valor Cero, estar puesto
     a (1), ya que el resultado tiene un valor de cero.
     En este caso, al comprobar el valor del flag Zf, sabremos que insertar
     est en modo inactivo (es decir, el teclado est en modo SOBREESCRIBIR).

     - NEG.
     Esta operacin, por su forma de trabajar(equivale a un NOT seguido de
     un INC) podemos estudiarla aqu, pero la vamos a dejar para cuando
     tratemos los nmeros negativos, ya que se utiliza para eso, para convertir
     un nmero en negativo.

       NEG AX

          (Equivalentes)

       NOT AX
       INC AX




---  Operaciones para el manejo de hileras o cadenas de caracteres
     Este tipo de instrucciones nos permiten (a grandes rasgos) realizar
     movimientos de bloques de memoria de una posicin de la memoria a otra.

     Veamos cada una de ellas:

     - MOVS (MOV String, mover cadena de caracteres).
     Se utiliza para mover un byte (MOVSB) o una palabra (MOVSW) desde la
     posicin de memoria direccionada por DS:SI a la direccin ES:DI.
     Antes de introducir esta instruccin en el programa, debemos haber
     cargado debidamente los registros con sus valores apropiados.
     En caso de mover un byte, utilizamos la sintaxis: MOVSB.
     En caso de mover una palabra, utilizamos la sintaxis: MOVSW.

     En estos momentos puede parecer de poca utilidad esta instruccin, ya
     que el mismo resultado lo podemos obtener con la instruccin MOV que
     vimos en lecciones anteriores.
     Veremos la utilidad de esta instruccin y las siguientes, cuando veamos
     las partculas: REP (REPetir), REPZ  REPE, y REPNZ  REPNE.


     MOVSB ---> Mueve el byte direccionado por DS:SI a ES:DI.
     MOVSW ---> Mueve la palabra direccionada por DS:SI a ES:DI.


     - LODS (LOaD String, cargar cadena de caracteres en el acumulador).
     Se utiliza para introducir en el registro acumulador (AX si trabajamos
     con palabras; AL si trabajamos con bytes) la palabra o byte direccionado
     mediante DS:SI.

     LODSB ---> Introduce en el registro AL (tamao byte) el byte direccionado
                mediante DS:SI.
     LODSW ---> Introduce en el registro AX (tamao palabra  word) el byte
                direccionado mediante DS:SI.

     - STOS (STOre String, almacenar cadena de caracteres).
     Almacena el contenido del acumulador (AX si trabajamos con palabras;
     AL si trabajamos con bytes) en la posicin de memoria direccionada
     mediante ES:DI.

     STOSB ---> Almacena el contenido del registro AL (tamao byte) en la
                posicin de memoria ES:DI.
     STOSW ---> Almacena el contenido del registro AX (tamao palabra) en la
                posicin de memoria ES:DI.

     - CMPS (CoMPare String, comparar cadenas de caracteres).
     Se utiliza para comparar cadenas de caracteres. Compara las cadenas
     que empiezan en las direcciones DS:SI y ES:DI.
     Podemos comparar un byte (byte a byte, cuando usemos la partcula REP)
     o una palabra (palabra a palabra, cuando usemos la partcula REP).

     CMPSB ---> Compara el byte situado en DS:SI con el byte situado en
                ES:DI.
     CMPSW ---> Compara la palabra situada en DS:SI con la palabra situada en
                ES:DI.

     -SCAS (No_se_qu String :-)
     Compara el contenido del acumulador (AX si trabajamos con palabras;
     AL si trabajamos con bytes) con la palabra o byte situado en la posicin
     de memoria ES:DI.

     SCASB ---> Compara el contenido del registro AL (tamao byte) con el
                byte situado en la posicin ES:DI.
     SCASW ---> Compara el contenido del registro AX (tamao word) con la
                palabra situada en la posicin ES:DI.


     Bien... Hasta ahora hemos visto que estas instrucciones trabajan slo
     con un byte o palabra. Son raras las ocasiones en las que utilizamos
     estas instrucciones para mover slo un byte o palabra.
     Lo ms normal es utilizar estas instrucciones antecedidas de una de las
     siguientes partculas de repeticin:

     + REP (REPetir CX veces)
     Repite una de las operaciones de movimiento/comparacin de cadenas tantas
     veces como indique el registro CX. Tras cada una de estas repeticiones se
     decrementa el valor del registro CX, para saber cuando debe parar.
     Tambin se incrementa/decrementa el valor de los punteros usados
     (SI y/o DI). Dependiendo de la instruccin de que se trate, habr que
     actualizar uno slo de los punteros (STOS, LODS, SCAS)  los dos (MOVS,
     CMPS).

     Y por qu digo: incrementa/decrementa?
     Pues porque los movimientos o comparaciones se pueden hacer hacia atrs
     o hacia delante. Cuando hacemos un movimiento/comparacin hacia delante,
     a cada paso del bucle, se incrementan los registros SI y/o DI.
     Cuando hacemos un movimiento/comparacin hacia atrs, a cada paso del
     bucle, se decrementan los registros SI y/o DI.

     Dependiendo del tamao usado (byte o palabra), los incrementos o
     decrementos en los puneteros sern de 1  de 2 unidades, respectivamente.

     La forma en que el programador indica que los movimientos/comparaciones
     se realizarn hacia delante o hacia atrs, viene dada por la manipulacin
     del flag Df.
     Para indicar que queremos que los movimientos/comparaciones se realicen
     hacia delante, debemos poner el flag Df con valor (0).
     Para indicar que queremos que los movimientos/comparaciones se realicen
     hacia atrs, debemos poner el flag Df con valor (1).
     Ya vimos la manera de modificar el valor del flag Df:

         STD ---> Pone el flag Df con valor (1).
         CLD ---> Pone el flag Df con valor (0).

     Ejemplo: Queremos mover 77 palabras (hacia adelante) desde la posicin
     de memoria 7384h del segmento 8273h a la posicin de memoria 7263h:8293h.
     La cosa quedara as:

            MOV AX,7263H
            MOV ES,AX    ;Registro ES con valor adecuado (7263h).
            MOV DI,8293H ;Puntero destino (DI) con valor adecuado (8293h).
                         ;Direccin de destino en ES:DI (7263H:8293H).
            MOV AX,8273H
            MOV DS,AX    ;Registro DS con valor adecuado (8273h).
            MOV SI,7384H ;Puntero (SI) con valor adecuado (7384h).
                         ;Direcciones fuente y destino con su valor adecuado.

            MOV CX,77 ;Indicamos que queremos hacer 77 movimientos.
            CLD       ;Los movimientos los vamos a hacer hacia delante.

            REP MOVSW ;Realiza 77 veces la instruccin MOVSW, actualizando
                      ;debidamente los punteros fuente (SI) y destino (DI),
                      ;tras cada iteracin. As mismo, decrementa el registro
                      ;CX para saber cuando debe dejar de realizar repeticiones
                      ;de la instruccin MOVSW.
                      ;Cuando CX tenga valor Cero, dejar de realizar
                      ;movimientos.
                      ;En cada una de las 77 iteraciones, se coge la palabra
                      ;contenida en DS:SI y la copia en ES:DI.
                      ;Acto seguido, aade dos unidades a SI y a DI, para
                      ;procesar el resto de las 77 palabras que componen el
                      ;bloque que hemos indicado.



     + REPZ  REPE (Repetir mientras CX <> 0, y Zf = 1).
     Repite una de las operaciones de comparacin (operaciones de movimiento
     de cadenas no tienen sentido con REPZ) de cadenas tantas veces como
     indique el registro CX, siempre que el flag Zf sea 1.
     Es decir, se realizar la operacin de comparacin mientras CX sea
     distinto de Cero (an queden elementos por comparar), y los dos elementos
     (bytes o palabras) comparados sean iguales.
     O sea, mientras que los elementos comparados sean iguales, y queden
     elementos por comparar, se proceder a comparar los siguientes.

     Ejemplo: Queremos comparar la cadena situada en DS:SI con la cadena
     situada en ES:DI. La longitud de la cadena ser de 837 bytes.
     Supongamos que todos los registros de direccin tienen su valor adecuado.

           ;registros de direccin DS, SI, ES, DI con su valor adecuado.

           MOV CX,837 ;837 comparaciones de elementos de tipo byte.
           REPZ CMPSB ;Realiza la instruccin CMPSB mientras CX <> 0 y el
                      ;flag Zf tenga valor (1), es decir:
                      ;cada vez que se realiza una comparacin, comprueba si
                      ;los elementos comparados son iguales ('mirando' Zf),
                      ;si no son iguales, deja de realizar comparaciones.
                      ;Si son iguales entonces comprueba si quedan elementos
                      ;por comparar (CX <> 0), en caso de que no queden,
                      ;deja de realizar comparaciones.
                      ;Tras cada comparacin, actualiza debidamente los
                      ;punteros fuente (SI) y destino (DI).
                      ;En este caso se aade una unidad a cada uno de estos
                      ;dos registros (SI y DI).

           JNZ diferentes    ;Si tras la instruccin (REP CMPSB), el flag Zf
                             ;tiene valor (0), eso quiere decir, que algn
                             ;byte de la cadena fuente (DS:SI) no coincide con
                             ;su correspondiente en la cadena destino (ES:DI).
                             ;Es decir, las cadenas no son iguales.
                             ;Entonces, realizamos un salto condicional a un
                             ;trozo de cdigo utilizado para el caso de que las
                             ;cadenas sean diferentes.

           [...]             ;grupo de instrucciones que se ejecutan cuando
                             ;las cadenas son iguales.

           JMP fin_comparaciones ; salto el trozo de instrucciones que se
                                 ;ejecutan cuando las cadenas son diferentes.

diferentes:                  ;aqu empieza el grupo de instrucciones que se
                             ;ejecutan cuando las cadenas son diferentes.

           [...]             ;grupo de instrucciones que se ejecutan cuando
                             ;las cadenas son diferentes.

fin_comparaciones:           ;sigue el programa...



     La instruccin (REPZ CMPSB) ya veremos que es muy importante al tratar
     la programacin de utilidades residentes. Mediante esta instruccin
     sabremos si ya ha sido instalado en memoria el programa. Simplemente
     hay que buscar un trozo del programa desde el principio de la memoria
     hasta la posicin donde se encuentra el trozo a buscar.
     Si no se produce ninguna coincidencia, es porque el programa residente
     no est instalado. Si se produce una coincidencia, es porque el programa
     residente ya est instalado, con lo cual damos un mensaje al usuario
     (Programa ya instalado en memoria), y salimos a la linea de comandos
     otra vez.
     Pero bueno, ya veremos esto en profundidad al tratar los RESIDENTES.


     + REPNZ  REPNE (Repetir mientras CX <> 0, y Zf <> 1).
     Repite una de las operaciones de comparacin de cadenas tantas veces como
     indique el registro CX, siempre que el flag Zf sea 0.
     Es decir, se realizar la operacin de comparacin mientras CX sea
     distinto de Cero (an queden elementos por comparar), y los dos elementos
     (bytes o palabras) comparados sean DIFERENTES.
     O sea, mientras que los elementos comparados sean diferentes, y queden
     elementos por comparar, se proceder a comparar los siguientes.


Nota: Cuando realizamos comparaciones/movimientos de cadenas de longitud par,
      lo lgico sera hacerlo de palabra en palabra, mientras que si la
      longitud es impar, es imprescindible trabajar con bytes.
      Alguna duda al respecto?


      Un ltimo ejemplo de todo el tema de cadenas de caracteres:
      Queremos copiar la cadena origen (cadena_origen) al principio de
      Cadena_destino.


      ;******datos

          [...]

      Cadena_origen db 'SanBit V6.0 (Super Utilidades)'
     Cadena_destino db 'SanBit V5.6 (Utilidades residentes)'

          [...]
      ;******fin de datos.


      ;*****cdigo de programa
      PUSH DS
      POP ES ;Mediante estas dos instrucciones, lo que hago es darle al
             ;registro ES el mismo valor que tiene DS. Esto se hace ya que
             ;las dos cadenas estn dentro del mismo segmento.
             ;Suponemos que el registro DS estaba desde un principio apuntando
             ;al principio de los datos, como es normal.

      MOV SI,OFFSET Cadena_origen
---          ;Mediante OFFSET, lo que hacemos es
---          ;introducir en el registro SI, el desplazamiento (offset en
---          ;ingls) de la variable Cadena_origen. Es decir, hacemos que SI
             ;contenga la direccin de Cadena_origen. Utilizamos SI como
             ;puntero a Cadena_origen.
             ;Por el contrario con la instruccin (MOV SI,Cadena_origen), lo
             ;que haramos sera introducir la primera palabra contenida
             ;en Cadena_origen al registro SI.
      MOV DI,OFFSET Cadena_destino ;Hacemos que DI apunte a la variable
             ;Cadena_destino. Es decir, DI tendr la direccin de la variable
             ;Cadena_destino.

      CLD    ;Movimiento de datos hacia delante.

      MOV CX,15 ;15 es la mitad de 30 (longitud de Cadena_origen).

      REP MOVSW ;Realiza 15 movimientos de tipo palabra. Es decir, mueve 30
                ;bytes desde Cadena_origen a Cadena_destino.
                ;Al trabajar con palabras en lugar de bytes, se gana mucho
                ;en velocidad, ya que el procesador tiene que utilizar el
                ;BUS la mitad de veces.

      ;******fin de cdigo de programa.


      Tras la ejecucin de este trozo de programa, la variable Cadena_Destino
      tendr la siguiente cadena: 'SanBit V6.0 (Super Utilidades)entes)'
      Podemos observar que los ltimos 6 caracteres permanecen intactos,
      mientras que los primeros 30 han sido 'machacados' por la instruccin,
      introduciendo en su lugar el contenido de Cadena_origen.


      Esto es todo por ahora.
