 LECCION 5:
 ----------


      ASM POR AESOFT. (leccin 5).
      --------------------------------------------------------------------

     - CODIFICACION DE LAS INSTRUCCIONES EN EL 8086.
      --------------------------------------------------------------------

      Hola de nuevo, aplicados alumnos :-)
      En esta leccin vamos a tratar conceptos muy tcnicos acerca del
      formato de las instrucciones en cdigo mquina.
      Veremos cmo se codifican las instrucciones en el 8086.


     - CODIFICACION DE LAS INSTRUCCIONES EN EL 8086.
       (Este apartado es muy tcnico. Aunque no es imprescindible comprender
       lo que se expone a continuacin para programar en ensamblador, es
       muy til conocer cmo el procesador interpreta lo que le 'pedimos'.
       Esto nos da un mayor conocimiento acerca de la mquina en cuestin.
       Y de esta forma entendemos el porqu de ciertas sintaxis de
       instrucciones. Y resolveremos ms fcilmente los errores una vez que
       se nos presenten).
      --------------------------------------------------------------------
      Cada procesador tiene un conjunto de instrucciones para manejarlo,
      as como para manejar la mquina por medio de l.
      Indistintamente del lenguaje de programacin que estemos utilizando,
      cuando obtenemos el ejecutable, ste est compuesto nicamente por
      ese tipo de instrucciones bsicas (instrucciones de cdigo mquina).
      Dependiendo de la calidad y prestaciones de ese lenguaje de programacin,
      el cdigo resultante, necesitar ms instrucciones del procesador o menos.
      De todos es conocido, que hay lenguajes de alto o medio nivel (como C,
      pascal, basic, etc.) en los que para una misma tarea, uno dar un
      ejecutable ms grande que otro. Velocidad, aparte.
      Esto no sucede as con ensamblador, en el que para cada instruccin,
      existe una y slo una instruccin en cdigo mquina.

      Pues bien, ahora vamos a ver la estructura de esas instrucciones bsicas
      o de cdigo mquina.

      Las instrucciones del 8086 se codifican sobre 4 campos como mximo, y
      tienen un tamao de 1 a 6 bytes.
      Es decir, dependiendo de la instruccin de que se trate, necesitar
      ms o menos bytes para su codificacin, as como ms o menos campos.

      Los cuatro campos en una instruccin cdigo mquina son:
      1.- Cdigo de operacin: Este campo siempre aparece (obviamente).
          Una vez que el procesador descifra el significado de este campo,
          sabe si la instruccin consta de ms campos o si se trata de
          una instruccin de un slo campo.
      2.- Modo de direccionamiento (byte EA): Le indica al procesador el
          nmero de operandos que acompaan al cdigo de operacin, as
          como el tipo de estos operandos(registros, memoria, valor inmediato).
      3.- Desplazamiento del dato (sobre 8 o 16 bits): En caso de existir
          este campo, supone un desplazamiento sobre la direccin dada por
          un registro ndice o base (especificado este registro mediante el
          byte EA).
      4.- Valor inmediato (sobre 8 o 16 bits): Almacena un valor numrico
          de 8 o 16 bits, que va a ser utilizado para una transferencia, una
          operacin aritmtica, etc.

      Ahora entramos un poco ms en detalle:

      Primero veremos un esquema de una instruccin cdigo mquina:

    +-------------------------------------------------------------------+
         8 bits       2   3   3      8  16 bits       8  16 bits     
     +-----------+  +---------+  +--------------+  +--------------+  
      cdigo de                                Valor         
      operacin   MODREGR/M  Desplazamiento    Inmediato     
     +-----------+  +---------+  +--------------+  +--------------+  
     -- 1 byte -  -- 1 byte -   1  2 bytes -   1  2 bytes -  
    +-------------------------------------------------------------------+

    - El cdigo de operacin est codificado sobre 8 bits.
      Por medio de este campo se sabe si va a ser necesario cualquier otro
      de los tres restantes. Tambin el cdigo de operacin contiene
      informacin acerca de si se va a trabajar con palabras o con bytes.


    - Byte EA  Modo de direccionamiento: Contiene 3 campos. Los campos MOD y
      R/M especifican el modo de direccionamiento, y el campo REG especifica
      el registro de que se trata en la instruccin.

        El campo MOD que es de 2 bits puede tener 4 valores diferentes: Los
      3 primeros seleccionan el desplazamiento en los modos de direccionamiento
      de memoria. El cuarto selecciona un registro. Detallemos la funcin
      de estos bits en cada una de las 4 posibilidades:
       00 ---> No hay desplazamiento.
       01 ---> Se usa un byte para codificar el desplazamiento.
       10 ---> Se usan 2 bytes (una palabra) para codificar el desplazamiento.
       11 ---> Hace que R/M seleccione un registro usando la misma codificacin
               de los registros que para REG (ver ms abajo), en lugar de un
               modo de direccionamiento de la memoria.
               Es decir, que se produce una transferencia de un registro a otro.

        El campo REG que es de 3 bits codifica el registro empleado. Por tanto
      es posible especificar hasta 8 registros diferentes por medio de este
      campo. Dependiendo de que se trate de acceso a palabras o a octetos, se
      seleccionar un registro de entre un grupo de 8, o de un segundo grupo de
      8 registros.
      Para cuando se accede a registros de 16 bits, el campo REG codifica los
      registros de palabra de la siguiente manera:

          AX (000), CX (001), DX (010), BX (011)
          SP (100), BP (101), SI (110), DI (111)

      Cuando se accede a registros de 8 bits, la codificacin de los registros
      de tamao byte queda como sigue:

          AL (000), CL (001), DL (010), BL (011)
          AH (100), CH (101), DH (110), BH (111)

        El campo R/M indica el segundo registro (si lo hay) o el tipo de
     direccionamiento a memoria.

     En caso de que haya segundo registro, ste se codifica de la misma forma
     que para el campo REG.

     En caso de que se trate de un modo de direccionamiento de memoria,
     estos tres bits seleccionan uno de los modos de direccionamiento posibles
     de acuerdo con la siguiente tabla:

     000  desplazamiento final = [BX] + [SI] + desplazamiento
     001  desplazamiento final = [BX] + [DI] + desplazamiento
     010  desplazamiento final = [BP] + [SI] + desplazamiento
     011  desplazamiento final = [BP] + [DI] + desplazamiento
     100  desplazamiento final = [SI] + desplazamiento
     101  desplazamiento final = [DI] + desplazamiento
     110  desplazamiento final = [BP] + desplazamiento
     111  desplazamiento final = [BX] + desplazamiento



    - El desplazamiento en caso de existir, supone un incremento en la direccin
      dada por un registro ndice o base, dando lugar as a un desplazamiento
      final, dentro de un segmento dado. Es decir, como se ve en la tabla
      superior, podemos acceder a memoria a travs de un registro base (BX) o
      un registro ndice (SI, DI), etc, o bien hacerlo a travs de uno de esos
      registros, pero ayudndonos de un desplazamiento que se suma a la
      direccin que tienen establecida esos registros.
      Veremos ms adelante la utilidad de utilizar desplazamientos sobre un
      registro base o ndice.

      Como ejemplo: Tenemos el registro DI apuntando a (con valor igual a) la
      direccin 3000h (direcciones siempre en hexadecimal).
      En esa direccin tenemos el comienzo de una cadena de caracteres que
      queremos convertir a mysculas. Y una vez que los hemos convertido, los
      queremos copiar a la memoria de pantalla.

      Pues bien, podemos ir incrementando DI para tratar cada uno de estos
      caracteres, o bien podemos utilizar DI junto con un desplazamiento para
      acceder a cada uno de los caracteres. Es decir, para acceder al primer
      elemento sera DI+0, para el segundo, sera DI+1, etc. De esta forma, al
      terminar la tarea, DI seguir apuntando al principio de la cadena,
      y podremos copiar la cadena desde el principio a donde corresponda.

      Si no utilizramos desplazamiento, tendramos que tener una variable
      apuntando al inicio de la cadena, para tenerlo luego localizable.
      Bueno... Esto es un simple ejemplo. Las posibilidades que nos ofrece
      el utilizar desplazamientos acompaando al registro base o ndice son
      mucho ms interesantes que lo que acabamos de ver en el ejemplo.

    - El valor inmediato se utiliza cuando hacemos movimientos de datos a
      registros o a memoria. Por ejemplo queremos introducir en el registro
      AX la cantidad 37867 (93EBH), pues ese 37867 sera el valor inmediato.

      En ensamblador la instruccin sera:
      MOV AX,37867
      Simple, no?  Mover (MOV) la cantidad 37867 al registro AX.
      Prximamente se ver el resto de instrucciones en ensamblador,
      mientras tanto, y por ser necesario ahora, aprenderemos el uso de la
      instruccin MOV.

      La instruccin como hemos podido ver, se utiliza para movimientos o
      transferencias de datos: de registro a registro, de registro a memoria,
      y de memoria a registro. Pero nunca de memoria a memoria, ya que la
      arquitectura del procesador y bus no lo permiten.

      La sintaxis bsica de la instruccin es la siguiente:
      MOV destino,fuente.
      El destino siempre a la izquierda, y la fuente a la derecha.

      Ejemplos:
      * MOV ax,5 ---> mueve el valor inmediato (o dato) 5 al registro AX.
        Examinemos esta instruccin. Alguien podra pensar que como el valor 5
        cabe en un slo registro de 8 bits (AL en este caso), el registro AH
        quedara como estaba antes de la instruccin. Pues no es as.
        Si le decimos al procesador que introduzca un 5 en AX, as se har.
        Poniendo a cero el registro AH, para que AX tenga el valor 5.

        Veamos cmo se codifica esta instruccin:
        MOV AX,5  --->  B8 05 00  (Cdigo mquina, siempre en hexadecimal).
        En primer lugar tenemos el primer byte que contiene el cdigo de
        operacin (B8).
        Debido a que este cdigo de operacin(B8) tiene implcita la utilizacin
        del registro AX como destino, no es necesario el byte EA  byte de
        direccionamiento, que s sera necesario para transferencias con otros
        registros. Como vimos en la primera leccin al hablar de registros,
        el registros AX (AH, AL) se utiliza normalmente como acumulador, de
        tal manera que existen operaciones especiales para trabajar con l, como
        la instruccin B8 y otras muchas de movimiento de datos, en las que
        no se especifica el registro mediante el byte EA, ya que est implcito
        en el cdigo de operaicn. De esta manera se gana velocidad en la
        ejecucin del programa utilizando los registros para lo que han sido
        creados. AX acumulador, CX contador, etc.

        Despus del cdigo de operacin tenemos dos bytes (1 palabra).
        Estos dos bytes forman el campo Valor Inmediato, que como vemos
        aqu es de 16 bits.
        Como os habreis dado cuenta, de los 4 campos que puede tener una
        instruccin cdigo mquina, sta slo tiene dos:
        El primero (cdigo de operacin), y el ltimo (valor inmediato).

        Y volviendo de nuevo al campo Valor inmediato y a su tamao en esta
        instruccin (2 bytes):
        El orden de estos bytes es muy significativo. Veamos...
        Tenemos el valor 5 para introducir en una palabra. Lo normal sera
        que en el cdigo se almacenara este cinco como (00 05), pues en el
        8086 esto no es as. Como siempre, para acelerar el programa cuando
        se manejan transferencias de datos, se lleg a la conclusin de que
        si se almacenan los bytes que componen una palabra en orden inverso
        al normal, luego es mucho ms rpido recuperarlos. Y es as como se
        hace en la prctica. Cada vez que almacenamos una palabra en memoria,
        el byte de mayor peso queda a la derecha del byte de menor peso.
        De lo anterior se desprende que el nmero 5 al introducirlo en una
        palabra de memoria, quedara como (05 00).

        Otro ejemplo: Una vez que almacenamos el nmero 8BC3H en memoria,
        si hacemos un volcado de memoria para ver qu tenemos, veremos que
        en memoria no est el nmero como 8BC3H, sino que nos encontramos con
        C38BH.



      * MOV al,5 ---> Introduce el valor 5 en el registro AL.
        En este caso, s que AH queda como estaba antes de la instruccin, ya
        que en la misma no interviene tal registro de ninguna forma (ni
        implcita al referirse a AX, ni explcita al referirnos a l en
        concreto).
        La instruccin se codifica como:
        MOV AL,5 ---> B0 05
        Este ejemplo es prcticamente como el anterior, excepto que el cdigo
        de operacin en vez de ser B8 es B0, y adems ya no hay 2 bytes en
        el campo valor inmediato, sino que hay uno slo, ya que vamos a
        introducir el dato en un registro de tamao byte.

     Ejemplo cuando se trata de transferencias entre registros:

      * MOV CX,SI ---> Introduce el valor del registro SI en el registro CX.
        La instruccin se codifica como:
        MOV CX,SI ---> 8B CE
        En esta instruccin tenemos un cdigo de operando y el byte EA.
        Mediante este byte EA el procesador sabe qu registros intervienen
        en la transferencia.
        Descomponiendo el byte EA en sus dgitos binarios, tenemos:
        CE ---> 11001110
        El campo MOD con valor 11, hace que R/M seleccione un registro como
        fuente.
        El campo REG con valor 001, indica que el registro destino es CX.
        El campo R/M con valor 110, indica que el registro fuente es SI.


---
      Hemos visto la manera de introducir un dato en un registro. Pero cmo
      hacemos para introducir un dato en memoria?
      Bien, para esto se utilizan las variables (que tambin existen en
      ensamblador) o bien, se indica una posicin de memoria concreta, pasando
      de variables.
      Hay una tercera manera que es utilizar registros ndice o base.

    + En el primer caso, es muy simple. Si queremos introducir el valor 70h
      en la variable X, basta con escribir   MOV X,70h.
      Previamente la variable X la hemos definido y hemos definido tambin
      su tamao: byte, palabra, doble palabra.
      Una vez que el compilador d el cdigo ejecutable, lo que antes era
      la variable X, ahora ser la posicin de memoria ocupada por la variable.
      Es decir, que el usar variables es para darnos una gran comodidad a los
      programadores. Podramos hacer un programa sin usar variables, indicando
      posiciones de memoria directamente, pero eso es ya ms parecido a cdigo
      mquina puro que a ensamblador.

   +  En el segundo caso, el de indicar la posicin de memoria concreta, hay
      que tener en cuenta si esa posicin de memoria la utilizamos como un
      byte o como una palabra.
      Esto es as ya que si por medio del programa queremos guardar un 5 en
      la posicin de memoria 7654h (por ejemplo), el procesador no sabe si
      queremos guardar un byte o una palabra.

     Para que no surja ningn tipo de lios, el lenguaje ensamblador cuenta
     con ciertos convencionalismos para tratar estas transferencias a memoria.
     Cuando queremos introducir un byte en una posicin dada de memoria lo
     hacemos con el siguiente formato:   MOV BYTE PTR DS:[7654H],5
                                             ^^^^^^^^ ^^ ^     ^
     BYTE PTR indica que vamos a acceder a una posicin de memoria de tipo BYTE.
    
     Caundo queremos introducir una palabra a partir de una posicin de memoria
     el formato queda como sigue:           MOV WORD PTR DS:[7654H],5
                                                ^^^^^^^^ ^^ ^     ^
     WORD PTR indica que vamos a acceder a una posicin de memoria de tipo WORD.

      Tened en cuenta tambin que cuando se quiere acceder a una posicin
      concreta de memoria sin pasar por una variable, se debe indicar entre
      corchetes, como en los ejemplos de arriba.
      Pero eso no es todo, se debe indicar un segmento, para que el procesador
      sepa a qu zona de 64 ks de la memoria pertenece la posicin dada
      entre los corchetes.
      En este caso indicamos el segmento DS (segmento de datos), que es lo
      usual. Aunque tambin podramos haber seleccionado el segmento ES(segmento
      extra de datos) para as poder transferir algo fuera de nuestra zona
      de datos.

      Obsrvese la manera de indicar una direccin en direccin segmentada,
      no real. Primero se indica el segmento, luego dos puntos para separar,
      y luego entre corchetes el offset o desplazamiento dentro de ese segmento.
      Segmento:[desplazamiento]
      DS:[2626h], ES:[FFFFh], etc.


    + En el tercer caso nos valemos de un registro ndice o base, el cual
      contiene la direccin de la posicin de memoria que nos interesa, para
      acceder a dicha posicin de memoria.
      Un ejemplo: MOV BYTE PTR [DI],5
      Obsrvese que aqu no es necesario indicar el segmento al que nos
      referimos. Se coge por defecto el segmento DS.
      En definitiva, cuando accedemos a memoria a travs de registros indice
      o base, no es necesario indicar el segmento. Mientras que si lo hacemos
      en forma directa, indicando la posicin de memoria tal que [2635h],
      debemos indicar el segmento con el que vamos a tratar.

-------------------
      Qu lioooooooooooooooooooooooo... verdad?
      He intentado ponerlo lo ms claro posible, con muchos ejemplos, y como
      se lo explicara a una persona que tuviera a mi lado. Pasando de rollos
      tericos de libros y dems parafernalia, pero si an as os resulta
      lioso o complicado, no os preocupeis. Estoy aqu para re-explicar lo que
      haga falta. Y adems cuando empecemos a hacer programillas, todo esto
      se ver muy claro en la prctica.
-------------------- Sigamos:

      Veamos ahora cmo se codifica una instruccin en la que se hace acceso
      a memoria.

      * MOV WORD PTR DS:[7654H],5 ---> Esta instruccin introduce el valor 5
        a partir de la posicin de memoria 7654h. Y digo a partir, ya que
        necesita dos posiciones de memoria para almacenarlo, ya que se
        trata de un valor inmediato de 16 bits (esto se determina al poner
        lo del WORD PTR).
        Con lo cual, la palabra con valor 5, queda almacenada en dos posiciones
        de memoria, la indicada [7654h] y la contigua [7655h].
        Si tenemos en cuenta lo que hemos comentado antes acerca de cmo el
        8086 almacena las datos de tipo palabra en memoria, sabremos de antemano
        que la posicin [7654h] contendr el valor 05, y la posicin [7655h]
        contendr el valor 00.

      Veamos cmo se codifica esta instruccin:

        MOV WORD PTR [7654H],5 ---> C7 06 54 76 05 00
        Vemos que esta instruccin ha ocupado el mximo posible (6 bytes).
        De tal forma que los 4 campos de instruccin estn presentes.
        Vamos a estudiarla detenidamente:
        Lo primero que tenemos es el cdigo de operacin: C7.
        Este cdigo indica una operacin MOV sobre una direccin concreta 
        desplazamiento, y con un valor numrico de tipo palabra.

        El 3 y 4 byte juntos forman el desplazamiento (tener en cuenta
        lo del tema del orden inverso en los bytes), y los bytes 5 y 6
        juntos forman el valor inemdiato a introducir (tener en cuenta de nuevo
        lo del orden inverso).

        Y nos queda el 2 byte, que es el byte EA o de direccionamiento.
        Que por qu lo he dejado para el final?
        je. Porque llevo 2 o 3 horas intentando descubrir el por qu de que sea
        06. No me cuadra por ningn sitio, ya que este 6 indica que no hay
        desplazamiento, cuando s lo hay.

        A ver si para la prxima leccin, consigo descifrar el misterio.


     Un saludo.
     AESOFT....
