      ASM POR AESOFT. (leccin 7).
      --------------------------------------------------------------------
     - DUDAS DE LECCIONES ANTERIORES
     - MAS INFORMACION Y EJEMPLOS ACERCA DEL REGISTRO DE ESTADO (FLAGS)
                                       (ampliacin de la leccin 1).
     - REPASO AL TEMA DE LOS SEGMENTOS (ampliacin de la leccin 2).
     - CONJUNTO DE INSTRUCCIONES DEL 8086 (I).
      --------------------------------------------------------------------

      Hola de nuevo, aplicados alumnos. :-)
      En esta leccin, aparte de repasar algunos temas anteriores, a peticin
      de algunos lectores, empezaremos a estudiar las instrucciones con que
      contamos en el 8086. Las dividiremos en grupos, y veremos sus
      caractersticas y funcionamiento.

      Que disfruteis la leccin de hoy, que mi trabajo me ha costado. :-)



     - DUDAS DE LECCIONES ANTERIORES
     -------------------------------
     En este apartado os dejo un mensaje que me parece de utilidad para el
     curso. En este mensaje se habla sobre la codificacin de ciertas
     instrucciones, y como os deca me parece til para todos los seguidores
     del curso. Ah va:

--- Inicio del mensaje

 FJR>         Veamos cmo se codifica esta instruccin:
 FJR>         MOV AX,5  --->  B8 05 00  (Cdigo mquina, siempre
 FJR> en hexadecimal).
 FJR>         En primer lugar tenemos el primer byte que contiene
 FJR> el cdigo de
 FJR>         operacin (B8).
 FJR>         Debido a que este cdigo de operacin(B8) tiene
 FJR> implcita la utilizacin
 FJR>         del registro AX como destino, no es necesario el
 FJR> byte EA  byte de
 FJR>         direccionamiento, que s sera necesario para
 FJR> transferencias con otros
 FJR>         registros.

 DT> Osea que cada mov que hagas tiene un 'cdigo' distinto si se hace a
 DT> ax, a cx, etc... ? y se ha seguido algn orden lgico a la hora de
 DT> asignarle nmeros a las intrucciones?, osea, por qu b8 -> mov ax,? 

     En efecto, ese B8 tiene su razn de ser.
     En primer lugar, todas las operaciones del tipo
     MOV registro,dato_inmediato tienen un cdigo de operacin cuyo primer
     dgito hexadecimal es B.
     Hay 16 cdigos de operacin diferentes (uno para cada registro, como t
     muy bien observabas) para el tipo de operacin
     MOV registro,dato_inmediato.

     Por supuesto estos cdigo siguen un orden:

      B0  --->  MOV AL,dato_inmediato_tamao_byte
      B1  --->  MOV CL,dato_inmediato_tamao_byte
      B2  --->  MOV DL,dato_inmediato_tamao_byte
      B3  --->  MOV BL,dato_inmediato_tamao_byte

      B4  --->  MOV AH,dato_inmediato_tamao_byte
      B5  --->  MOV CH,dato_inmediato_tamao_byte
      B6  --->  MOV DH,dato_inmediato_tamao_byte
      B7  --->  MOV BH,dato_inmediato_tamao_byte

      B8  --->  MOV AX,dato_inmediato_tamao_word
      B9  --->  MOV CX,dato_inmediato_tamao_word
      BA  --->  MOV DX,dato_inmediato_tamao_word
      BB  --->  MOV BX,dato_inmediato_tamao_word

      BC  --->  MOV SP,dato_inmediato_tamao_word
      BD  --->  MOV BP,dato_inmediato_tamao_word
      BE  --->  MOV SI,dato_inmediato_tamao_word
      BF  --->  MOV DI,dato_inmediato_tamao_word

      Podrs observar que el orden de los registros no es AL, BL, CL, DL...
      Sino AL, CL, DL, BL.
      Lo mismo para los registros de 8 bits de mayor peso (AH, CH, DH, BH),
      Y para los registros de 16 bits (AX, CX, DX, BX, SP, BP, SI, DI).


      Un saludo ---------------------------------
      Francisco Jesus Riquelme ------------------
      FidoNet 2:341/43.9  MasterNet 17:3468/301.3

--- Fin del mensaje

      Espero que os haya parecido interesante.



     - MAS INFORMACION Y EJEMPLOS ACERCA DEL REGISTRO DE ESTADO (FLAGS).
                                           (ampliacin de la leccin 1).
     --------------------------------------------------------------------
     Ya vimos algo acerca del registro de estado (FLAGS) en la leccin 1.
     En esta leccin, tratar de desarrollar un poco ms para los que no
     lo entendieron del todo en esa primera leccin.

     El registro de flags  palabra de estado est compuesto por una serie
     de banderas (flags en ingls) que no son ms que simples bits o dgitos
     binarios, los cuales pueden tener un valor de uno (bit activo) o un
     valor de cero (bit no activo).
     Cada uno de estos bits mantiene una informacin determinada.
     Ya dimos en la primera leccin una relacin de estos bits de estado 
     flags, agrupados en categoras segn su funcin.

     Veamos ms detenidamente uno de estos grupos de flags  banderas:
     * Flags de estado *
     Estos flags estn ntimamente ligados a las operaciones aritmticas,
     que son enumeradas y detalladas ms abajo.
     Estos flags nos ofrecen informacin acerca del resultado de la ltima
     operacin efectuada.

     Es decir, si tras realizar una multiplicacin se ha producido
     desbordamiento, el flag  bit de estado Of (flag de overflow) se pondr
     con valor 1.

     Si fruto de otra operacin, como una resta obtenemos un nmero negativo,
     el flag Sf (flag de signo), se pondr a 1, indicando que el resultado de
     la operacin ha dado un nmero negativo.

     Si tras una operacin, como puede ser una resta, el resultado obtenido
     es cero, se activar el flag Zf (flag Cero. Zero en ingls).

     Una operacin puede afectar a un slo flag, a ninguno, o a varios.
     Es decir, dependiendo del tipo de instruccin de que se trate, el
     procesador tendr que actualizar un nmero determinado de flags.
     Por ejemplo, las instrucciones de salto, tanto condicionales como
     incondicionales, no actualizan ningn flag.
     La instruccin MOV tampoco actualiza ningn flag.
     Mientras que las instrucciones aritmticas actualizan muchos de los
     flags, para as indicar el estado de la operacin.
     Tomemos las instrucciones SUB, ADD, ADC, etc. Todas estas instrucciones
     afectan a los siguientes flags: Of, Sf, Zf, Af, Pf, Cf.
     En realidad, la mayora de las instrucciones aritmticas afectan a esos
     flags.

     De esta forma, tras realizar cada operacin, mediante estos flags sabremos
     si el resultado es negativo, si es cero, si se ha producido overflow, etc.

     Como hemos visto, las operaciones modifican los flags para indicar el
     estado de tal operacin. Pero esa no es la nica forma de que los flags
     cambin su valor.
     En ensamblador disponemos de instrucciones para modificar el valor de
     un flag determinado.

     - CLC (Clear Cf. Borrar  poner a cero el flag de acarreo).
     Sintaxis: CLC.

     - STC (Set Cf. Activar  poner a uno el flag de acarreo).
     Sintaxis: STC.

     - CLI ((Clear If. Borrar  poner a cero el flag de interrupcin).
     Sintaxis: CLI.
     Esta instruccin la usamos cuando queremos que ninguna interrupcin
     enmascarable nos interrumpa el proceso en el que estamos.
     (Esto ya lo vimos en la leccin 4).

     - STI (Set If. Activar  poner a uno el flag de interrupcin).
     Sintaxis: STI.
     Mediante esta instruccin habilitamos de nuevo las interrupciones.
     (Visto en la leccin 4).

     - CLD (Clear Df. Borrar  poner a cero el flag Df).
     Sintaxis: CLD.
     Esta instruccin se usa cuando se est trabajando con hileras  cadenas
     de caracteres. Ya la estudiaremos entonces.

     - STD (Set Df. Activar  poner a uno el flag Df).
     Sintaxis: STD.
     Esta instruccin se usa cuando se est trabajando con hileras  cadenas
     de caracteres. Ya la estudiaremos entonces.


     El resto de los flags no puede modificarlos el programador mediante las
     instrucciones CLx y STx.
     Pero siempre hay otros mtodos.

~~~  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.


     - REPASO AL TEMA DE LOS SEGMENTOS (ampliacin de la leccin 2).
     --------------------------------------------------------------------
     Debido a que no qued claro para todos el tema de los segmentos,
     intentar complementar la informacin que ya d acerca del tema de la
     segmentacin con una exposicin ms coloquial de dicho tema.

     Tenemos 1 Mbyte de memoria para nuestro uso.
     1 Mbyte son 1024 Ks. Y 1024 Ks son a su vez, 1048576 bytes.
     O sea, que podemos manejar 1048576 bytes de memoria desde nuestro
     programa.
     Ahora debemos tener en cuenta que los registros del 8086 son de 16 bits,
     es decir, tienen capacidad para albergar 16 bits diferentes.
     Cada uno de estos bits puede tener un valor de 1 o de 0,
     independientemente del valor que tengan los bits contiguos. Por tanto,
     tenemos 2^16 combinaciones diferentes para ese registro, es decir, el
     registro puede tener 2^16 valores diferentes, o lo que es lo mismo,
     el registro puede representar 65536 valores diferentes.

     Hemos dicho que los registros en el 8086 son de tamao de 16 bits (como
     mucho). Entonces, en teora, slo podramos indicar 65536 posiciones
     de memoria. Pero slo en teora, ya que como vismos en la leccin 2,
     se puede acceder a todas las posiciones de ese Mbyte usando registros
     de 16 bits.

     Usamos entonces 2 registros de 16 bits.
     Por medio del primero, seleccionamos el trozo (segmento) de ese Mbyte
     donde se encuentra la direccin que nos interesa.
     Por medio del segundo registro, indicamos cul es la direccin que nos
     interesa dentro de ese trozo  segmento.

     El primer registro se llamar registro de segmento, y puede ser uno de
     los que ya conocemos: CS, DS, ES, SS.

     El segundo registro es lo que se llama offset  desplazamiento dentro de
     ese segmento  trozo de Mbyte.

     Ya vimos en la leccin 2 como se formaba la direccin final a partir de
     estos dos registros  direccionamiento segmentado.

     El valor depositado en el registro de segmento, se multiplica por 16
     a la hora de buscar el segmento (trozo de Mbyte actual), de esta forma
     se puede acceder a todo el Mbyte, ya que 65536*16 = 1048576 (1 Mbyte).
     Esto es algo que hace internamente el procesador con registros especiales
     para este propsito.
     Pero qu pasa con los 15 bytes que quedan entre una direccin y otra?
     Para eso tenemos el segundo registro:
     Una vez que ya se sabe dnde comienza el segmento, es decir, una vez que
     ya sabe el procesador con qu trozo de Mbyte va a trabajar a continuacin,
     lo que hace es sumar al principo de ste, el valor depositado en el
     segundo registro (offset  desplazamiento). De esta forma, se produce el
     acceso a la direccin deseada.

     Si a pesar de esta explicacin alguno no lo entiende, que sea ms
     concreto, y me diga exactamente qu es lo que no entiende.



     - CONJUNTO DE INSTRUCCIONES DEL 8086 (I).
     -----------------------------------------
     En este apartado vamos a estudiar las operaciones fundamentales para
     empezar a programar en ensamblador. Una lista completa del conjunto
     de instrucciones del 8086 se dar ms adelante, en otra leccin.
     Por ahora, tendremos suficiente con estudiar las instrucciones ms
     representativas dentro de cada grupo:

---   Movimiento de datos.
       Las instrucciones pertenecientes a este grupo, tienen como objetivo:
       - Actualizar un registro con un valor.
       - Copiar la informacin de un registro a una posicin de memoria.
       - Copiar la informacin de una posicin de memoria a un registro.
       - Mover la informacin de un registro a otro.
       - Intercambiar la informacin entre dos registros.
       En este grupo (Movimiento de datos) podamos incluir varias de las
       instrucciones que vamos a ver en grupos sucesivos, como por ejemplo
       cuando hablemos de las instrucciones para el manejo de hileras (cadenas
       de caracteres), entre otras, estudiaremos las instrucciones para
       transferir hileras, que bien se podan incluir en este grupo debido
       a su naturaleza de movimiento de datos.
       De cualquier modo, se enmarquen en un grupo o en otro, quedar
       suficientemente claro durante su exposicin sus caractersticas y
       finalidad.


       Como vimos en lecciones anteriores, la instruccin principal usada
       en movimientos de datos es la instruccin MOV.
       Con la instruccin MOV, podemos:
       - Mover el contenido de un registro fuente o una posicin de memoria
         a un registro destino.
         O bien, mover el contenido de un registro a una posicin de memoria.

         Su sintaxis es como sabemos: MOV destino,fuente.
         Ejemplo: MOV BX,SI ---> Mueve el contenido del registro SI al
                                 registro BX.

       - Mover un dato (valor inmediato) a un registro o posicin de memoria.
         Sintaxis: MOV destino,valor.
         Ejemplo: MOV BYTE PTR [SI],7 ---> Introduce el nmero 7 en la posicin
                  de memoria direccionada por SI.
         Ejemplo: MOV AX,25 ---> Mueve el nmero 25 al registro AX.

       Aparte de la instruccin tenemos varias ms para realizar movimientos
       de datos, como pueden ser:

       - XCHG
         Intercambia el contenido de dos registros, o bien el contenido de
         un registro y el de una posicin de memoria.
         Sintaxis: XCHG registro,registro/memoria
         XCHG viene del ingls EXCHANGE (Cambio). Por tanto es un cambio entre
         los dos valores dados tras el cdigo de operacin de la instruccin.
         Ejemplo: XCHG AX,WORD PTR [BX] ---> Tras ejecutarse esta instruccin,
                  AX contendr el valor que hubiera en la posicin de memoria
                  direccionada por BX, y viceversa.
         Ejemplo: CX,DX ---> Intercambia los contenidos de CX y DX.

       - Todas las relacionadas con la pila: PUSH, POP, PUSHF, POPF.
         Las cuales las estudiamos en la leccin 4.
         Ejemplo: PUSH AX ---> Introduce en la cima de la pila, el valor
                  contenido en AX.
    
       - Adems de las instrucciones enumeradas, y como ya hemos dicho arriba,
         en este grupo existen varias instrucciones ms que veremos ms
         adelante, conforme sea necesaria su utilizacin.

---   Transferencia de control.
       Son un conjunto de instrucciones que permiten al programador romper
       el flujo secuencial en un programa.
       Su funcin consiste en aadir un valor de desplazamiento al puntero
       de instruccin (IP), y en algunos casos variar tambin el valor de CS.
       La finalidad est en permitir ejecutar trozos de cdigo si se cumple
       una condicin, ejecutar trozos de cdigo repetidas veces (bucle),
       ejecutar trozos de cdigos desde diferentes puntos del programa
       (procedimientos), etc.

       Son 5 los tipos de instrucciones de transferencia de control.

       Podemos clasificar las instrucciones de transferencia de control en los
       siguientes subgrupos:
       - Saltos incondicionales (JMP).
       - Bucles (LOOP).
       - Saltos condicionales (Jnnn). Donde nnn indica la condicin.
       - Llamadas a procedimientos (CALL).
       - Llamadas a interrupciones o funciones (INT).


       Vamos a desarrollar cada uno de estos grupos:

...    - JMP (salto incondicional).
       Provoca la transferencia de control a la direccin que se especifica
       a continuacin del cdigo de operacin.
       Su sintaxis es: JMP direccin
       Donde direccin puede ser una etiqueta (La etiqueta es un nombre que
       asociamos a una lnea de instruccin en ensamblador. Es como una especie
       de apuntador a esa lnea), o una direccin contenida en un registro o
       variable.
       Los saltos pueden ser directos o indirectos.
       As como tambin pueden realizarse saltos dentro del mismo
       segmento (NEAR), y saltos intersegmento (FAR).

       Directo y NEAR: JMP etiqueta ---> Salto a la direccin etiqueta.
       Etiqueta puede encontrarse antes o despus de la instruccin de salto.
       Es decir, los saltos se pueden realizar hacia adelante o hacia detrs
       de la instruccin en curso.
       Incluso es posible tener una instruccin de salto a esa misma
       instruccin. Es decir:

       ;*** porcin de cdigo.
       Etiqueta:
                JMP etiqueta

       ;*** fin de la porcin de cdigo.

       Lo cual nos dara como resultado un bloqueo del ordenador, ya que el
       control no saldra de esa lnea. Sera algo as como un bucle sin fin.

       El salto directo y NEAR, es el salto ms comn.
       Raramente se utilizan los que aparecen a continuacin.


       Indirecto y NEAR: JMP [BX] ---> Salto a la direccin indicada por
       la variable direccionada mediante BX. Es un salto dentro del mismo
       segmento.

       Indirecto y FAR: JMP FAR PTR [BX] ---> Salto tipo FAR (a otro segmento)
       donde BX contiene la direccin de comienzo de una doble palabra con
       los nuevos valores de IP y CS.

       Ejemplo de salto directo y NEAR:

       ;***
       Inicio:
              JMP Sanbit
              MOV cx,7
       Sanbit:
              MOV cx,6
       ;***

       Al ejecutar este trozo de cdigo desde la etiqueta Inicio, la
       instruccin (MOV cx,7) nunca se ejecutar. Por tanto, al final de este
       trozo de cdigo, la variable CX tendr valor 6.

       Obsrvese que las etiquetas pueden tomar cualquier nombre, siempre que
       ste no pertenezca al lenguaje ensamblador.
       Al final de la etiqueta debe aparecer el carcter ':' (los dos puntos),
       el cual le indica al ensamblador que es una etiqueta de tipo NEAR, es
       decir, que va a ser utilizada para saltos dentro del mismo segmento.
       Si no apareciesen los dos puntos ':', se considerara de tipo FAR,
       utilizada para saltos entre segmentos.
       Lo ms comn es utilizar etiquetas tipo NEAR. Para saltos intersegmentos
       se suelen utilizar otro mtodo diferente al salto a una etiqueta
       tipo FAR. Yo nunca he usado una etiqueta tipo FAR en los aos que llevo
       con el ensamblador, y seguramente vosotros tampoco la useis nunca.

...    - LOOP  (Bucle)
       Esta instruccin sirve para ejecutar un trozo de cdigo un nmero de
       veces dado (indicado mediante el registro CX).
       En cada iteracin del bucle se decrementa el valor del registro CX.
       El bucle finalizar cuando CX tenga valor 0, es decir, cuando se hayan
       producido tantas iteraciones como indicaba CX antes de entrar al bucle.

       Veamos un ejemplo:

       ;***
                    MOV CX,7
       INICIO_BUCLE:
                    ADD WORD PTR [BX],CX
                    INC BX
                    LOOP INICIO_BUCLE
                    MOV SI,BX
       ;***

       En el ejemplo que estamos tratando, tenemos un bucle que se va a
       repetir 7 veces. En cada una de estas iteraciones se van a realizar
       dos operaciones aritmticas (echar un vistazo al apartado de operaciones
       aritmticas, para saber qu hace el cuerpo del bucle).
       Tras realizar las dos operaciones, llegamos a la instruccin
       LOOP inicio_bucle. Esta instruccin primero comprueba si CX vale 0,
       en caso afirmativo, no hace nada y sigue el flujo de control por la
       siguiente instruccin (en este caso: MOV SI,BX).
       En caso de que CX tenga un valor distinto de 0, se decrementa su valor,
       y se bifurca a la direccin inicio_bucle. O sea, que se realiza la
       siguiente iteracin.

       Del mismo modo que el utilizar variables nos evita tener que indicar
       posiciones de memoria concretas del modo: [2346h], [7283h], etc,
       siendo infintamente ms cmodo usar nombres como: coordenada_superior,
       valor_total, posicion_cursor, modo, etc... Del mismo modo, como os
       deca, usar etiquetas es la solucin que nos ofrece el ensamblador para
       poder dirigirnos a posiciones de memoria en nuestros saltos, bucles,
       etc. Tambin se pueden usar las etiquetas para indicar dnde empiezan
       determinadas estructuras de datos.

...    - Saltos condicionales (Jnnn).
       Los saltos condicionales se usan en ensamblador para ejecutar trozos
       de cdigo dependiendo del valor de determinado registro o variable.
       Llegamos a este punto que para realizar un salto condicional, antes
       hemos de hacer una comparacin. Aunque se pueden realizar saltos
       condicionales sin antes haber hecho una comparacin correspondiente,
       lo usual es hacer la comparacin.

       Por tanto, antes de seguir con la los saltos condicionales, tenemos
       que saber cmo se realizan las comparaciones en ensamblador, y qu
       finalidad tiene el que tras cada comparacin haya un salto condicional.

       * COMPARACIONES *
       Las comparaciones estn ntimamente relacionadas con los saltos
       condicionales. Es ms, es raro el programa ensamblador en el que se
       encuentre una comparacin y acto seguido no haya un salto condicional.
       La sintaxis de la instruccin de comparacin es:

       CMP registro,registro
       CMP registro,memoria
       CMP memoria,registro
       CMP registro,valor
       CMP valor,registro

       El orden de los operandos a comparar es muy importante:
       No es lo mismo la instruccin CMP AX,7 que CMP 7,AX.
       No es lo mismo, debido a que en la comparacin obetenemos ms informacin
       que un simple 'son iguales' o 'son diferentes'.
       Fruto de una comparacin sabemos qu operando es el mayor.

       Usaremos una de las 5 sintaxis de arriba dependiendo de lo que vamos a
       comparar. Si queremos comparar 2 registros, por ejemplo AX con CX,
       la instruccin apropiada ser CMP AX,CX.

       Los datos a comparar deben ser del mismo tamao. Es decir, se comparar
       un dato de tipo byte con otro de tipo byte; Un dato de tipo palabra
       con otro dato de tipo palabra. Pero nunca se comparar un dato de tipo
       byte con otro de tipo palabra.
       Ejemplo de mala utilizacin de CMP: CMP AX,CL ---> No podemos comparar
       un dato de tipo palabra (AX) con un dato de tipo byte (CL).

       Hemos visto que ntimamente ligado a los saltos condicionales estn las
       instrucciones de comparacin. Pues bien, el 'medio de comunicacin'
       (por decirlo de alguna manera) entre una comparacin y el salto
       condicional asociado, son las banderas de estado (FLAGS).
       Para aclarar esto, veamos cmo acta una instruccin de comparacin:
       Lo que hace la instruccin de comparacin es restar al primer operando
       el segundo, pero eso lo hace mediante unos registros internos del
       procesador, a los que no tiene acceso el programador.
       De esta forma, los operandos usados por el programador quedan
       inalterados.
       Al realizar esta resta, se actualiza el registro de estado (FLAGS).
       Es decir, si fruto de la comparacin, los dos datos eran iguales, la
       bandera o flag Zf tendr valor activo, indicando que fruto de esa resta
       interna que ha hecho el procesador el resultado es un cero. Es decir,
       los datos son iguales.
       Cuando un dato es menor que otro, son otros flags
       los que se activan, como el flag Cf (flag de acarreo o Carry).
       Al principio de la leccin aparece ms desarrollado todo lo relacionado
       con los FLAGS.

       Estudiemos ms profundamente el tema de los saltos condicionales:
       Todos los saltos condicionales deben estar dentro del rango (+127, -128)
       bytes. Es decir, que slo se pueden saltar 127 bytes hacia adelante y
       128 bytes hacia detrs dentro del cdigo del programa.
       Si sumamos esos 127 bytes y los otros 128, tenemos un valor de 255.
       Para los que no les suene ese valor, deciros que es el mayor nmero que
       puede contener un dato de tipo byte.

       Es decir, que se reserva un byte para indicar lo grande que va a ser el
       salto. Como el salto puede ser hacia adelante o hacia detrs, hay que
       dividir ese 255 en la mitad (ms o menos) para los valores positivos
       (saltos hacia adelante) y otra mitad para los negativos (saltos hacia
       detrs).

       Qu hacer cuando se quiere realizar un salto condicional mayor que
       esos 127/128 bytes?
       Muy sencillo: Un salto condicional a un salto incondicional.

       Tambin es til conocer que existen saltos condicionales empleados
       cuando se comparan datos con signo, y los saltos condicionales
       empleados en comparaciones de datos sin signo.

       Veamos los posibles saltos condicionales que podemos encontrar en el
       8086:

       * Saltos basados en datos sin signo:

         Instruccin          Efecto            Flag comprobados
       --------------------------------------------------------------

         JE/JZ         (salta si igual)              Zf=1
         JNE/JNZ       (salta si no igual)           Zf=0
         JA/JNBE       (salta si superior)           Cf=0 y Zf=0
         JAE/JNB       (salta si superior o igual)   Cf=0
         JB/JNAE       (salta si inferior)           CF=1
         JBE/JNA       (salta si inferior o igual)   CF=1  Zf=1


       * Saltos basados en datos con signo:

         Instruccin          Efecto            Flags comprobados
       --------------------------------------------------------------

         JE/JZ         (salta si igual)              Zf=1
         JNE/JNZ       (salta si no igual)           Zf=0
         JG/JNLE       (salta si mayor)              Zf=0 y Sf=Of
         JGE/JNL       (salta si mayor o igual)      Sf=Of
         JL/JNGE       (salta si menor)              Sf<>Of
         JLE/JNG       (salta si menor o igual)      ZF=1  Zf<>Of


       Adems de estos saltos encontramos una serie de saltos condicionales
       basados en comprobaciones aritmticas especiales:

        Instruccin          Efecto            Flags comprobados
       --------------------------------------------------------------

         JS            (salta si negativo)           Sf=1
         JNS           (salta si no negativo)        Sf=0
         JC      (salta si se ha producido acarreo)  Cf=1
         JNC  (salta si no se ha producido acarreo)  Cf=0
         JO   (salta si se ha producido *overflow*)  Of=1
         JNO  (salta si no se ha producido overflow) Of=0
         JP/JPE     (salta si *paridad par*)         Pf=1
         JNP/JPO   (salta si *paridad impar*)        Pf=0
         JCX            (salta si CX=0)              CX=0 (registro CX=0)


        *overflow*
        Overflow es lo mismo que desbordamiento, y se produce cuando tras una
        operacin aritmtica, el resultado es demasiado grande para que quepa
        en su destino.
        Al producirse overflow, se activa el flag Of.

        *paridad par* , *paridad impar*
        La paridad indica el nmero de unos (1) en un registro o variable.
        Paridad par indica que ese registro tiene un nmero par de unos.
        Paridad impar indica que el registro tiene un nmero impar de unos.

        Al realizar cada operacin aritmtica, el procesador comprueba el
        nmero de unos del resultado. Si ese nmero de unos es par
        (paridad par), activa el flag Pf. Si es impar, lo pone a 0.


        Veamos la equivalencia entre las sentencias if..then de los lenguajes
        de alto nivel, y las construcciones CMP..Jnnn.

        El equivalente a la sentencia: 'If modo=5 then fondo=7', vendra dado
        en ensamblador por la construccin:

        ;***

        CMP modo,5
        jnz no_fon
        mov fondo,7
no_fon:

        ;***

        Veamos otro ejemplo:
        El equivalente a: 'If modo=5 then fondo=7 else fondo=6', vendra dado
        en ensamblador por:

        ;***

        CMP modo,5
        jnz no_fon
        mov fondo,7
        jmp short fin_fon ;** a continuacin se explica lo de 'jmp short'
no_fon:
        mov fondo,6
fin_fon:

        ;***

        *jmp short* se utiliza cuando se quiere hacer un salto incondicional
        a una posicin de memoria que est dentro del rango (-127 , +128).
        Es decir, que sobra con un byte para indicar el desplazamiento.
        de esta forma, nos ahorramos uno de los dos bytes que seran necesarios
        en caso del salto incondicional normal.

        El salto incondicional normal (JMP) necesita dos bytes para poder
        especificar cualquier direccin dentro del segmento actual.
        Aadindole la palabra 'short', como hemos visto, hacemos que slo
        necesite un byte para especificar la nueva direccin donde pasar el
        control.


        Otro ejemplo:
        El equivalente de 'If modo <> 24 then fondo=modo' quedara en
        ensamblador de la siguiente manera:

        ;*** suponemos las variables (fondo y modo) de tipo byte.

        CMP modo,24
        jz fin_fon
        mov al,modo
        mov fondo,al
fin_fon:

        ;***

        Un ltimo ejemplo:
        El equivalente de 'If modo < 23 then modo=23' quedara en
        ensamblador de la siguiente manera:

        ;***

        CMP modo,23
        jnb fin_fon
        mov modo,23
fin_fon:

        ;***


...    - Llamadas a procedimientos (CALL).
       Al igual que en los lenguajes de alto nivel, en ensamblador tenemos
       los llamdos procedimientos, trozos de cdigo que van a ser usados en
       distintas partes del programa.
       Los cuales nos permiten tener un cdigo ms legible, ms estructurado.
       El formato de un procedimiento en ensamblador es tal como sigue:

       Tomemos como ejemplo un procedimiento llamado inicializacion.

       inicializacion PROC

           .
           .  Cuerpo del procedimiento.
           .
           .


           RET
       inicializacion ENDP


       Cuando el procedimiento va a ser llamado desde otro segmento, se dice
       que es un procedimiento tipo FAR. Y se declara as:


       inicializacion PROC FAR

           ;.
           ;.  Cuerpo del procedimiento.
           ;.
           ;.


           RET
       inicializacion ENDP

       Cuando el procedimiento se usa slo en el segmento donde se ha declarado,
       se denomina procedimiento NEAR. En este caso no es necesario indicar
       que se trata de NEAR. Es decir, que si no se especifica que es FAR, se
       supone que es NEAR.

       O sea, que los dos formatos siguientes, son equivalentes:

       inicializacion PROC
           ;  Cuerpo del procedimiento.
           RET
       inicializacion ENDP

;****

       inicializacion PROC NEAR
           ;  Cuerpo del procedimiento.
           RET
       inicializacion ENDP


     Para llamar a un procedimiento y transferirle de este modo el control,
     usamos la instruccin:

     CALL nombre_procedimiento.
     En caso del ejemplo anterior, sera:  CALL inicializacion.

     Se retorna del procedimiento mediante la instruccin RET (Retorno de
     procedimiento).

     Existen dos tipos de llamadas a procedimientos:
     * Llamadas directas: Mediante la instruccin CALL nombre_procedimiento.
     Donde nombre_procedimiento es el nombre que se le ha dado al procedimiento
     en cuestin.
     * Llamadas indirectas: Aqu no se especifica el nombre del procedimiento
     en cuestin, sino la direccin que contiene la direccin de comienzo del
     procedimiento que se quiere llamar.
     Este mtodo se suele usar mucho en programacin de utilidades residentes,
     cuando se llama a una interrupcin parcheada (ya veremos todo esto
     prximamente).
     En este tipo de llamada, en funcin de que la llamada sea de tipo NEAR o
     FAR, las posiciones de memoria donde tengamos almacenada la direccin
     a la que queremos llamar sern de tipo WORD (palabra)  DWORD (doble
     palabra).

     Pero bueno, por ahora tenemos suficiente con las llamadas directas a
     procedimientos.

...  - Llamadas a Interrupciones o funciones (INT).
     Ya vimos en lecciones anteriores el funcionamiento de las interrupciones.
     Vimos que podan ser de tipo hardware, y de tipo software.
     Pues bien, aqu las que nos interesan son las de tipo software.
     Que son ni ms ni menos que llamadas a procedimientos o subrutinas que
     se encuentran en la ROM del ordenador, y por otra parte tambin estn
     las funciones del DOS (sistema operativo) entre otras.
     Es decir, hay ciertas funciones de muy bajo nivel, como acceso a discos,
     teclado, etc, que vienen ya programadas en la ROM del ordenador, para as
     mantener compatibilidad con el resto de PC's, y por otra parte, ayudar
     al usuario en la programacin.
     Tambin el sistema operativo ofrece al programador una serie de funciones
     para manejo de ficheros, memoria, etc.

     Pues bien, la manera de utilizar estas funciones (pasarles el control), es
     a travs de la instruccin INT. Su sintaxis es la siguiente:
     INT numero_interrupcion.
     Donde numero_interrupcion es un nmero del 0 al 255.

     Por ejemplo, para acceder al driver de vdeo, se usa la interrupcin 10h.
     INT 10H ---> Provocara una llamada a la interrupcin 10h (16 en decimal).

     Para acceder a las funciones del DOS, tenemos la interrupcin 21h
     INT 21H ---> Provocara una llamada a la interrupcin 10h (16 en decimal).

     Estas interrupciones software se dividen en funciones, y stas a su vez
     en subfunciones.
     Para acceder a cada funcin/subfuncin de una interrupcin software,
     existe una convencin de llamada. Es decir, para acceder a una determinada
     funcin/subfuncin, hay que introducir en unos registros determinados
     un valor adecuado.

     Por ejemplo, para crear un fichero, accedemos a la funcin 3Ch de la
     interrupcin 21h.
     La llamada se realiza as en ensamblador:

     ;******

     MOV AH,3Ch ;Seleccionamos funcin
     INT 21H    ;pasamos el control a la funcin.

     ;*****

     Otro ejemplo: para leer un carcter desde el teclado, llamamos a la
     funcin 00h de la interrupcin 16h.

     La llamada se realiza as en ensamblador:

     ;******

     MOV AH,00h ;Seleccionamos funcin
     INT 16H    ;pasamos el control a la funcin.

     ;*****

     Hay dos manuales de bolsillo que son prcticamente imprescindibles para
     un programador en ensamblador. Estos libros son:

     - Funciones del Ms-Dos (RAY DUNCAN / ANAYA MULTIMEDIA).
     - La Rom Bios de IBM   (RAY DUNCAN / ANAYA MULTIMEDIA).

     Contienen una gran informacin acerca de las funciones del DOS y de
     la ROM.

     De todas formas, para el que no los pueda o quiera comprar (1000 pelas
     cada uno, ms o menos), prximamente dar una relacin de las
     interrupciones del 8086, junto con informacin similar a la que viene
     en estos dos manuales.


---  Instrucciones aritmticas.

     (En un principio slo trabajaremos con nmeros codificados en binario
     puro. Es decir, nmeros sin signo.)

     A diferencia de los lenguajes de alto nivel, en los que existen multitud
     de instrucciones aritmticas, en ensamblador del 8086 contamos slo con
     unas pocas instrucciones bsicas fundamentales, como son la suma, la
     resta, el producto, la divisin, y poco ms.

     - ADD (Suma en el 8086).
     Realiza la suma entre dos operandos dados. Estos operandos deben ser del
     mismo tamao.
     Sintaxis: ADD operando1,operando2.
     Se realiza la suma de los dos operandos, y se deposita en operando1.
     Tened en cuenta que puede producirse desbordamiento.
     Tomemos el caso (ADD AX,BX) cuando AX=0F000H y BX=3333H. Al realizarse
     la suma, se produce overflow (desbordamiento), quedando en AX tras la
     ejecucin, el siguiente valor: 2333H. Con la correspondiente prdida del
     dgito ms significativo. Esta situacin se indica en el registro de estado
     (FLAGS) activando el flag de overflow (Of).

     Otro ejemplo: ADD CX,WORD PTR [BX] ---> Suma a CX el valor contenido en la
     posicin de memoria direccionada mediante BX.

     Otro ms: ADD BYTE PTR [SI],7 ---> Introduce el valor 7 en la posicin de
     memoria direccionada por SI.

     Otro: ADD variable1,2345h ---> Suma a la variable1 (que hemos tenido que
     definir de tipo palabra) el valor 2345h (tipo palabra).

     - SUB (Resta en el 8086).
     Realiza la resta entre dos operandos dados. Estos operandos deben ser del
     mismo tamao.
     Sintaxis: SUB operando1,operando2.
     Resta del primer operando el segundo.
     Aqu tambin se nos pueden plantear situaciones especiales, como cuando
     restemos a un operando pequeo uno ms grande (Recordemos que por ahora
     slo trabajamos en binario puro. Es decir, nmeros sin signo).
     Tomemos el caso (SUB CX,DX) cuando CX vale 0077h y DX vale 8273h. Tras
     realizarse la operacin, CX tendra el valor 7E74h. Esto se debe a que
     la resta se realiza de derecha a izquierda, y bit a bit, como vamos a ver
     ahora.
     Cmo se realiza realmente la resta (basmonos en el ejemplo):
     El procesador tiene los dos valores en binario:
     CX = 0000000001110111
     DX = 1000001001110011
     Acto seguido, procede a realizar la resta, bit a bit (y de derecha a
     izquierda).

         CX = 0000000001110111
       - DX = 1000001001110011
       -----------------------
         CX = 0111111001110100 = 7E74H en base hexadecimal.

     Por tanto, CX=7E74H tras realizar la operacin.

     Otro ejemplo: SUB AX,37h ---> Resta a AX el valor 37h

     Otro ms:     SUB BYTE PTR ES:[SI],AL ---> Resta el valor contenido en AL,
     a la posicin direccionada mediante SI, dentro del segmento de datos
     apuntado por ES.

     Otro:         SUB variable1,word ptr [di] ---> Este ejemlo como podreis
     deducir por vosotros mismos, es un ejemplo de instruccin no permitida.
     Como ya vimos en lecciones anteriores, no podemos direccionar dos
     posiciones de memoria diferentes dentro de la misma instruccin.
     De tal manera, que esta instruccin habr que descomponerla en 2
     diferentes:
                 MOV AX,WORD PTR [DI] ---> Deposito en AX el valor contenido
                 en la posicin de memoria direccionada por DI. De esta manera,
                 en la siguiente instruccin usar AX y no una direccin de
                 memoria.

                 SUB variable1,AX ---> Ahora s. Restamos a variable1 (que al
                 fin y al cabo, es una posicin de memoria. Tipo palabra en
                 este caso) el contenido del registro AX.


     - INC (Incremento en una unidad).
     Se utiliza cuando lo que se quiere hacer es una suma de una unidad.
     Entonces se utiliza esta instruccin.
     La sintaxis es: INC operando.
     Ejempo: INC AX ---> Incrementa el valor de AX en una unidad.
     Si antes de la instruccin, AX tena el valor 3656h, ahora tendr el valor
     3657h.
     Muy importante: Si antes de la instruccin, AX tena el valor 0FFFFH,
     ahora tendr el valor 0000h. Al sumar bit a bit y de derecha a izquierda,
     queda todo Cero, y al final quedara un 1, que se pierde porque no cabe
     en el registro. Aqu pues tambin se producira overflow.

     Otro ejemplo: INC BYTE PTR [BX] ---> Incrementa en una unidad el valor
     contenido en la posicin de memoria direccionada por BX.

     - DEC (Decremento en una unidad).
     Se utiliza cuando se quiere restar una unidad a un valor dado.
     La sintaxis de la instruccin es: DEC operando.
     Ejemplo: INC AX ---> Decrementa el valor de AX en una unidad.
     Si antes de la instruccin, AX tena el valor 3656h, ahora tendr el valor
     3655h.
     Muy importante: Si antes de la instruccin, AX tena el valor 0000H,
     ahora tendr el valor 0FFFFh. Al restar bit a bit y de derecha a izquierda,
     queda todo con valor 1, quedando al final 0FFFFH fruto de este DEC.

     Otro ejemplo: DEC BYTE PTR [BX] ---> Decrementa en una unidad el valor
     contenido en la posicin de memoria direccionada por BX.

     - ADC (Suma teniendo en cuenta el acarreo anterior).
     Se utiliza para operaciones cuyos operandos tienen ms de un registro de
     longitud. A la hora de hacer la suma, se tiene en cuenta el posible
     acarreo de una operacin anterior. Esto es posible, gracias al flag Cf 
     flag de acarreo.
     Tanto sta como la siguiente son instrucciones poco usadas.
     Yo nunca las uso.

     - SBB
     (Resta teniendo en cuenta 'lo que me llevo' de la operacin anterior:-))
     Se utiliza para operaciones cuyos operandos tienen ms de un registro de
     longitud. A la hora de hacer la resta, se tiene en cuenta 'lo que me
     llevo' de una operacin anterior. Esto es posible, gracias al flag Cf 
     flag de acarreo.


     * MULTIPLICACION Y DIVISION *
     Estas operaciones aceptan slo un operando, de forma que segn sea su
     tamao byte o palabra, asumen que el otro operando est en AL  AX
     respectivamente.
     Esta es una de las instrucciones que os deca (en la leccin 1) que tienen
     el registro acumulador (AX/AH/AL) implcito en la instruccin.
     De tal manera que no hace falta especificarlo, y slo es necesario indicar
     el otro operando involucrado en la operacin.

     - MUL (multiplicacin de datos sin signo).
     Sintaxis: MUL operando.
     Realiza la multiplicacin del operando dado, con el acumulador.
     Dependiendo del tamao del operando introducido en la operacin, el
     procesador tomar AL o AX como segundo operando.

     * Operando de tipo byte: El procesador asume que el otro operando se
     encuentra almacenado en el registro AL, y el resultado de la operacin
     lo deposita en el registro AX.

     * Operando de tipo palabra: El procesador asume que el otro operando est
     almacenado en el registro AX, y el resultado de la operacin lo depositar
     en el par de registros DX,AX. Teniendo DX la parte ms significativa  de
     mayor peso del resultado.

     -IMUL (multiplicacin de datos con signo).
     Igual que arriba, pero teniendo en cuenta que se trabaja con nmeros
     con signo.

     - DIV (Divisin de datos sin signo).
     Sintaxis: DIV divisor.
     Divide el operando almacenado en el registro acumulador por el divisor.
     Es decir, acumulador/divisor.
     Dependiendo del tamao del divisor introducido, el procesador asume que
     el dividendo se encuentra en AX  en el par de registros DX,AX.

     * Divisor de tipo byte: El procesador asume que el dividendo se encuentra
     almacenado en el registro AX. El resultado de la operacin se desompone
     en AH (resto) y AL (cociente).

     * Divisor de tipo palabra: El procesador asume que el dividendo se
     encuentra almacenado en el par de registros DX,AX. Teniendo DX la parte
     ms significativa. El resultado de la operacin se descompone en
     DX (resto) y AX (cociente).

     - IDIV (Divisin de datos con signo).
     Igual que arriba, pero teniendo en cuenta que se trabaja con nmeros
     con signo.


     Hay que tener muy en cuenta al utilizar estas instrucciones de divisin,
     que la ejecucin de la operacin no desemboque en error.
     Esto sucede con la famosa divisin por Cero, entre otras situaciones.
     Tambin sucede cuando el cociente obtenido en una divisin no cabe en el
     registro utilizado para almacenarlo.
     En estos casos, se produce una INT 0, que origina la terminacin del
     programa en curso.


---  Instrucciones de manejo de bits.

     * Instrucciones de desplazamiento de bits *
     Son instrucciones que nos permiten desplazar los bits dentro de
     un regitro o una posicin de memoria.
     Estas instrucciones actan sobre datos de tipo byte (8 bits) y de tipo
     palabra (16 bits).

     - SHL (desplazamiento a la izquierda).
     Mediante esta instruccin podemos desplazar a la izquierda los bits de
     un registro o posicin de memoria.
     Esto que puede parecer poco prctico, es muy til en determinadas
     situaciones. Por ejemplo, es la manera ms rpida y cmoda de multiplicar
     por 2.
     Sintaxis: SHL registro,1
               SHL registro,CL
               SHL memoria,1
               SHL registro,CL

     Los desplazamientos pueden ser de una sla posicin o de varias.
     Cuando queremos realizar un slo desplazamiento usamos los formatos:
         SHL registro,1
         SHL memoria,1

     Pero cuando queremos realizar desplazamientos de ms de 1 posicin,
     debemos usar el registro CL para indicar el nmero de desplazamientos
     deseados.

     Veamos algunos ejemplos para aclararlo.
     Ejemplo: Queremos desplazar a la izquierda una posicin los bits del
     registro AL.
     La instruccin necesaria sera: SHL AL,1.
     Veamos el efecto de la instruccin:
     Supongamos que en un principio, AL = B7h.
     Tenemos pues, antes de realizar la operacin el registro AL de 8 bits,
     con el siguiente valor en cada uno de estos 8 bits: 10110111.
     Tras realizar el desplazamiento, el registro quedara como: 01101110.
     Hemos desplzado todos los bits una posicin a la izquierda.
     El bit de mayor peso (bit 7), el de ms a la izquierda, se pierde.
     Y el bit de ms a la derecha (bit 0)  de menor peso, toma el valor 0.
     El registro AL (tras la instruccin) tiene un valor de 6EH.
     Si volvemos a ejecutar la instruccin (SHL AL,1) con el nuevo valor de AL,
     tras la ejecucin, tendremos los bits del registro de la siguiente manera:
     AL = 11011100. Si pasamos este nmero binario a hexadecimal, tenemos que
     AL = 0DCH.
     Si seguimos realizando desplazamientos a la izquierda, terminaremos por
     quedarnos con el registro con todos los bits a Cero, debido a que el
     valor que entra por la derecha en cada desplazamiento es un cero (0).

     Otro Ejemplo: Queremos desplazar a la izquierda los bits del registro AL
     3 posiciones.
     Para llevar a cabo el desplazamiento, primero tenemos que introducir en
     CL el nmero de 'movimientos' a la izquierda que se van a realizar sobre
     cada bit.
     Y luego, ejecutar la instruccin de desplazamiento en s.

     MOV CL,3 ---> Indicamos 3 'desplazamientos'.
     SHL AL,CL ---> Realiza el desplazamiento hacia la izquierda (3 veces).

     Supongamos que antes de ejecutar la instruccin, AL = 83h. En binario:
     AL = 10000011.
     Tras la instruccin, los bits quedaran as: AL = 00011000.
     En hexadecimal: AL = 18H.

     Un ltimo ejemplo:
     Veamos ahora el caso especial en el que se utiliza la instruccin SHL para
     realizar multiplicaciones por 2.
     Supongamos que queremos multipicar el contenido del registro AL por 2.
     Pues bien, slo podremos multiplicarlo mediante (SHL AL,1) cuando estemos
     seguros que el bit de mayor peso (de ms a la izquierda) valga cero.
     Es decir, el bit 7  de mayor peso no puede ser 1, ya que se perdera al
     realizar el desplazamiento, con lo cual la multiplicacin sera errnea.
     Siempre que tengamos la certeza que el bit de mayor peso vale cero
     podremos utilizar (SHL reg/mem,1) para duplicar (multiplicar por 2).
     Evidentemente, si hacemos 2 desplazamientos, estamos multiplicando por 4,
     y as sucesivamente: 3 desplazamientos = multiplicar por 8, etc.

     Veamos el ejemplo:
     Queremos multiplicar por 8 el registor AL. Previamente en AL hemos
     depositado un nmero del 1 al 10. Por lo tanto, sabemos con certeza que
     el bit 7 vale 0, con lo cual podemos ahorrar tiempo utilizando la
     multiplicacin mediante desplazamientos.
     La cosa quedara como:

     MOV CL,3
     SHL AL,CL


     - SHR (desplazamiento a la derecha).
     Mediante esta instruccin podemos desplazar a la derecha los bits de
     un registro o posicin de memoria.
     Es la instruccin opuesta y complementaria a SHL.
     En este caso, la instruccin puede utilizarse para realizar divisiones
     por 2.

     Sintaxis: SHR registro,1
               SHR registro,CL
               SHR memoria,1
               SHR registro,CL

     Los desplazamientos pueden ser de una sla posicin o de varias.
     Cuando queremos realizar un slo desplazamiento usamos los formatos:
         SHR registro,1
         SHR memoria,1

     Pero cuando queremos realizar desplazamientos de ms de 1 posicin,
     debemos usar el registro CL para indicar el nmero de desplazamientos
     deseados.

     Veamos algunos ejemplos.
     Ejemplo: Queremos desplazar a la derecha una posicin los bits del
     registro DX.
     La instruccin necesaria sera: SHR DX,1.
     Veamos el efecto de la instruccin:
     Supongamos que en un principio, DX = 4251h.
     Tenemos pues, antes de realizar la operacin el registro DX de 16 bits,
     con el siguiente valor en cada uno de estos 16 bits: 0100001001010001
     Tras realizar el desplazamiento, el registro quedara como:
     DX = 0010000100101000.
     Hemos desplzado todos los bits una posicin a la derecha.
     El bit de menor peso (bit 0), el de ms a la derecha, se pierde.
     Y el bit de ms a la izquierda (bit 15)  de mayor peso, toma el valor 0.
     El registro DX (tras la instruccin) tiene un valor de 2128H, vemos
     que es prcticamente la mitad de su anterior valor.
     Si volvemos a ejecutar la instruccin (SHR DX,1) con el nuevo valor de DX,
     tras la ejecucin, tendremos los bits del registro de la siguiente manera:
     DX = 0001000010010100. Si pasamos este nmero binario a hexadecimal,
     tenemos que DX = 1094H, que vuelve a ser la mitad del valor anterior.
     Si seguimos realizando desplazamientos a la derecha, terminaremos por
     quedarnos con el registro con todos los bits a Cero, debido a que el
     valor que entra por la izquierda en cada desplazamiento es un cero (0).

     En ambas instrucciones SHL y SHR, el valor que entra nuevo en los
     desplazamientos es un cero. Seguidamente veremos instrucciones similares
     a stas que permiten que entre un nmero distinto de cero al realizar
     los desplazamientos. Son las instrucciones SAL y SAR.



     Cuando realizamos divisiones mediante SHR, como el bit que se pierde
     es el de menor peso (el de ms a la derecha), no tenemos el problema
     que se nos planteaba con la multiplicacin mediante SHL.
     Es decir, aqu como mucho el resultado final pierde el valor media
     unidad (0.5).


     - SAL y SAR.
     Estas instrucciones se diferencian de las anteriores (SHL y SHR) en que
     el nuevo valor binario que entra al realizar el desplazamiento es igual
     al bit de mayor peso.
     De cualquier modo, no pongais demasiada atencin en estas instrucciones.
     Rara vez (por no decir nunca) las tendreis que utilizar.


     * Instrucciones de rotacin de bits *
     Son instrucciones anlogas a las anteriores (de desplazamiento).
     La diferencia es que aqu no se producen desplazamientos, sino rotaciones
     en los bits.
     Es decir, no se pierde ningn bit, sino que entra por el lado opuesto a
     por donde sale.

     Estas instrucciones al igual que las anteriores, actan sobre datos de
     tipo byte (8 bits) y de tipo palabra (16 bits).

     - ROL (Rotacin a la izquierda).
     Rota a la izquierda los bits de un registro o posicin de memoria.
     El bit ms significativo no se pierde, sino que al rotar, entra por el
     otro extremo del operando, pasando a ser ahora el bit menos significativo.
     Sintaxis:
               ROL registro,1
               ROL registro,CL
               ROL memoria,1
               ROL registro,CL


     Veamos un ejemplo:
     Tenemos el registro AL con el valor 78h, que en binario es: 01111000.
     Si ejecutamos la instruccin (ROL AL,1), tendremos acto seguido que AL
     tiene el valor binario 11110000. Si volvemos a ejecutar esa instruccin
     con el nuevo valor de AL, tendremos 11100001. Si lo volvemos a hacer
     repetidas veces, tendremos:
                                 11000011
                                 10000111
                                 00001111
                                 00011110
                                 00111100
                                 01111000 ---> vuelta al valor original.

     - ROR (Rotacin a la derecha).
     Rota a la derecha los bits de un registro o posicin de memoria.
     El bit menos significativo no se pierde, sino que al rotar, entra por el
     otro extremo del operando, pasando a ser ahora el bit ms significativo.
     Sintaxis:
               ROR registro,1
               ROR registro,CL
               ROR memoria,1
               ROR registro,CL


     Ejemplo:
     Tenemos el registro AL con el valor 78h (igual que en el ejemplo anterior).
     En binario, AL = 01111000.
     Si ejecutamos la instruccin (ROR AL,1), tendremos acto seguido que AL
     tiene el valor binario 00111100. Si volvemos a ejecutar esa instruccin
     con el nuevo valor de AL, tendremos 00011110. Si lo volvemos a hacer
     repetidas veces, tendremos:
                                 00001111
                                 10000111
                                 11000011
                                 11100001
                                 11110000
                                 01111000 ---> vuelta al valor original.


     - RCL y RCR (Rotar a izquierda y derecha con carry  acarreo).
     Estas instrucciones son variantes de las anteriores.
     La diferencia estriba en que la accin de rotar se va a hacer en dos
     pasos:
      1.- El bit que se encuentra en el flag Cf es el utilizado para introducir
      en el extremo del operando.
      2.- El bit que sale por el otro extremo (bit rotado) pasa a la bandera
      Cf.

     Ejemplo:
     Tenemos el registro AL con el valor 78h (igual que en el ejemplo anterior).
     En binario, AL = 01111000.
     Tenemos tambin el falg Cf (flag de Carry  acarreo) con valor 1.
     AL = 01111000. Cf=1.

     Si ejecutamos la instruccin (RCR AL,1), tendremos acto seguido que AL
     tiene el valor binario 10111100. El valor que ha entrado por la izquierda
     es el que tena la bandera Cf.
     Pero a la vez, la bandera Cf despus de ejecutar la instruccin, tendr
     valor cero (0), por el bit rotado (el que ha salido por la derecha).

     No os preocupeis si os parece muy lioso. Este tipo de instrucciones casi
     nunca se utilizan. Yo nunca las he utilizado en ningn programa.
     De cualquier manera, cuando hagamos unos cuantos programas, ya tendreis
     soltura suficiente como para probarlas.



---  No hemos visto todos los grupos de instrucciones:
     Nos queda por ver, principalmente, las operaciones lgicas (AND, OR, etc.)
     y las operaciones con hileras  cadenas de caracteres.
     Esto lo veremos en una prxima leccin. Por hoy ya hay demasiadas cosas
     nuevas.



     Esto es todo por hoy. El prximo da ms.
     Practicad un poco con las instrucciones que hemos visto hoy.
     Probad a hacer algn programilla con ellas, aunque no lo ensambleis
     luego.
     Lo importante es saber para qu sirven las instrucciones que hemos visto.
