lunes, 26 de marzo de 2007

Curso de ensamblador (Parte 3)

¡Hola de nuevo, aplicados alumnos! En esta lección vamos a tratar conceptos muy técnicos acerca del formato de las instrucciones en código máquina. Veremos cómo se codifican las instrucciones en el 8086.

LECCION 5:

- CODIFICACION DE LAS INSTRUCCIONES EN EL 8086. (Este apartado es muy tecnico. Aunque no es imprescindible comprender lo que se expone a continuación para programar en ensamblador, es muy útil conocer cómo el procesador interpreta lo que le 'pedimos'. Esto nos da un mayor conocimiento acerca de la maquina en cuestión. Y de esta forma entendemos el porque de ciertas sintaxis de instrucciones. Y resolveremos mas facilmente los errores una vez que se nos presenten). -------------------------------------------------------------------- Cada procesador tiene un conjunto de instrucciones para manejarlo, así como para manejar la maquina por medio de el. Indistintamente del lenguaje de programación que estemos utilizando, cuando obtenemos el ejecutable, ‚este esta compuesto únicamente por ese tipo de instrucciones basicas (instrucciones de código m quina). Dependiendo de la calidad y prestaciones de ese lenguaje de programación, el código resultante, necesitar mas 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 mas grande que otro. Velocidad, aparte. Esto no sucede así con ensamblador, en el que para cada instrucción, existe una y sólo una instrucción en código m quina.

Pues bien, ahora vamos a ver la estructura de esas instrucciones basicas o de código m quina.

Las instrucciones del 8086 se codifican sobre 4 campos como maximo, y tienen un tamaño de 1 a 6 bytes. Es decir, dependiendo de la instrucción de que se trate, necesitar mas o menos bytes para su codificación, así como mas o menos campos.

Los cuatro campos en una instrucción código maquina son: 1.- Código de operación: Este campo siempre aparece (obviamente). Una vez que el procesador descifra el significado de este campo, sabe si la instrucción consta de mas campos o si se trata de una instrucción de un sólo campo. 2.- Modo de direccionamiento (byte EA): Le indica al procesador el número de operandos que acompañan al código de operación, 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 dirección 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 num‚rico de 8 o 16 bits, que va a ser utilizado para una transferencia, una operación aritm‚tica, etc.

Ahora entramos un poco mas en detalle:

Primero veremos un esquema de una instrucción código m quina:

Ú-------------------------------------------------------------------¿ ³ 8 bits 2 3 3 8 ó 16 bits 8 ó 16 bits ³ ³ ÉÍÍÍÍÍÍÍÍÍÍÍ» ÉÍÍÍÑÍÍÍÑÍÍÍ» ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» ³ ³ º código de º º ³ ³ º º º º Valor º ³ ³ º operación º ºMOD³REG³R/Mº ºDesplazamientoº º Inmediato º ³ ³ ÈÍÍÍÍÍÍÍÍÍÍͼ ÈÍÍÍÏÍÍÍÏÍÍͼ ÈÍÍÍÍÍÍÍÍÍÍÍÍÍͼ ÈÍÍÍÍÍÍÍÍÍÍÍÍÍͼ ³ ³ _-- 1 byte -_ _-- 1 byte -_ _ 1 ó 2 bytes -_ _ 1 ó 2 bytes -_ ³ À-------------------------------------------------------------------Ù

- El código de operación est codificado sobre 8 bits. Por medio de este campo se sabe si va a ser necesario cualquier otro de los tres restantes. También el código de operación contiene información 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 instrucción.

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 función 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/Maseleccione un registro usando la misma codificación de los registros que para REG (ver mas 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 codificación de los registros de tamaño 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 dirección 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 través de un registro base (BX) o un registro índice (SI, DI), etc, o bien hacerlo a través de uno de esos registros, pero ayud ndonos de un desplazamiento que se suma a la dirección que tienen establecida esos registros. Veremos mas 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 dirección 3000h (direcciones siempre en hexadecimal). En esa dirección tenemos el comienzo de una cadena de caracteres que queremos convertir a myúsculas. 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 sería DI+0, para el segundo, sería 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 utiliz ramos desplazamiento, tendríamos 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 acompañando al registro base o índice son mucho mas 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 sería el valor inmediato.

En ensamblador la instrucción sería: MOV AX,37867 Simple, ¨no? Mover (MOV) la cantidad 37867 al registro AX. Próximamente se ver el resto de instrucciones en ensamblador, mientras tanto, y por ser necesario ahora, aprenderemos el uso de la instrucción MOV.

La instrucción 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 b sica de la instrucción 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 instrucción. Alguien podría pensar que como el valor 5 cabe en un sólo registro de 8 bits (AL en este caso), el registro AH quedaría como estaba antes de la instrucción. Pues no es así. Si le decimos al procesador que introduzca un 5 en AX, así se hara. Poniendo a cero el registro AH, para que AX tenga el valor 5.

Veamos cómo se codifica esta instrucción: MOV AX,5 ---> B8 05 00 (Código maquina, siempre en hexadecimal). En primer lugar tenemos el primer byte que contiene el código de operación (B8). Debido a que este código de operación(B8) tiene implícita la utilización del registro AX como destino, no es necesario el byte EA ó byte de direccionamiento, que sí sería necesario para transferencias con otros registros. Como vimos en la primera lección al hablar de registros, el registros AX (AH, AL) se utiliza normalmente como acumulador, de tal manera que existen operaciones especiales para trabajar con el, como la instrucción B8 y otras muchas de movimiento de datos, en las que no se especifica el registro mediante el byte EA, ya que est implícito en el código de operaicón. De esta manera se gana velocidad en la ejecución del programa utilizando los registros para lo que han sido creados. AX acumulador, CX contador, etc.

Despues del código de operación 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 instrucción código m quina, ‚sta sólo tiene dos: El primero (código de operación), y el último (valor inmediato).

Y volviendo de nuevo al campo Valor inmediato y a su tamaño en esta instrucción (2 bytes): El orden de estos bytes es muy significativo. Veamos... Tenemos el valor 5 para introducir en una palabra. Lo normal sería que en el código 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 conclusión de que si se almacenan los bytes que componen una palabra en orden inverso al normal, luego es mucho mas r pido recuperarlos. Y es así como se hace en la pr ctica. 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 número 5 al introducirlo en una palabra de memoria, quedaría como (05 00).

Otro ejemplo: Una vez que almacenamos el número 8BC3H en memoria, si hacemos un volcado de memoria para ver que tenemos, veremos que en memoria no est el número 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 instrucción, ya que en la misma no interviene tal registro de ninguna forma (ni implícita al referirse a AX, ni explícita al referirnos a el en concreto). La instrucción se codifica como: MOV AL,5 ---> B0 05 Este ejemplo es pr cticamente como el anterior, excepto que el código de operación en vez de ser B8 es B0, y ademas ya no hay 2 bytes en el campo valor inmediato, sino que hay uno sólo, ya que vamos a introducir el dato en un registro de tamaño byte.

Ejemplo cuando se trata de transferencias entre registros:

* MOV CX,SI ---> Introduce el valor del registro SI en el registro CX. La instrucción se codifica como: MOV CX,SI ---> 8B CE En esta instrucción tenemos un código de operando y el byte EA. Mediante este byte EA el procesador sabe que registros intervienen en la transferencia. Descomponiendo el byte EA en sus dígitos binarios, tenemos: CE ---> 11001110 El campo MOD con valor 11, hace que R/Maseleccione 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 cómo hacemos para introducir un dato en memoria? Bien, para esto se utilizan las variables (que también existen en ensamblador) o bien, se indica una posición 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 también su tamaño: byte, palabra, doble palabra. Una vez que el compilador d‚ el código ejecutable, lo que antes era la variable X, ahora ser la posición de memoria ocupada por la variable. Es decir, que el usar variables es para darnos una gran comodidad a los programadores. Podríamos hacer un programa sin usar variables, indicando posiciones de memoria directamente, pero eso es ya mas parecido a código maquina puro que a ensamblador.

+ En el segundo caso, el de indicar la posición de memoria concreta, hay que tener en cuenta si esa posición 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 posición de memoria 7654h (por ejemplo), el procesador no sabe si queremos guardar un byte o una palabra.

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

Tened en cuenta también que cuando se quiere acceder a una posición 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 que zona de 64 ks de la memoria pertenece la posición dada entre los corchetes. En este caso indicamos el segmento DS (segmento de datos), que es lo usual. Aunque también podríamos haber seleccionado el segmento ES(segmento extra de datos) para así poder transferir algo fuera de nuestra zona de datos.

Obs‚rvese la manera de indicar una dirección en dirección 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 dirección de la posición de memoria que nos interesa, para acceder a dicha posición de memoria. Un ejemplo: MOV BYTE PTR [DI],5 Obs‚rvese 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 través de registros indice o base, no es necesario indicar el segmento. Mientras que si lo hacemos en forma directa, indicando la posición de memoria tal que [2635h], debemos indicar el segmento con el que vamos a tratar.

------------------- Que lioooooooooooooooooooooooo... ¨verdad? He intentado ponerlo lo mas claro posible, con muchos ejemplos, y como se lo explicaría a una persona que tuviera a mi lado. Pasando de rollos teóricos de libros y demas parafernalia, pero si aún así os resulta lioso o complicado, no os preocupeis. Estoy aquí para re-explicar lo que haga falta. Y ademas cuando empecemos a hacer programillas, todo esto se ver muy claro en la pr ctica.

-------------------- Sigamos:

Veamos ahora cómo se codifica una instrucción en la que se hace acceso a memoria.

* MOV WORD PTR DS:[7654H],5 ---> Esta instrucción introduce el valor 5 a partir de la posición 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 cómo el 8086 almacena las datos de tipo palabra en memoria, sabremos de antemano que la posición [7654h] contendr el valor 05, y la posición [7655h] contendr el valor 00.

Veamos cómo se codifica esta instrucción:

MOV WORD PTR [7654H],5 ---> C7 06 54 76 05 00 Vemos que esta instrucción ha ocupado el m ximo posible (6 bytes). De tal forma que los 4 campos de instrucción están presentes. Vamos a estudiarla detenidamente: Lo primero que tenemos es el código de operación: C7. Este código indica una operación MOV sobre una dirección concreta ó desplazamiento, y con un valor num‚rico 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 que lo he dejado para el final? je. Porque llevo 2 o 3 horas intentando descubrir el por que de que sea 06. No me cuadra por ningún sitio, ya que este 6 indica que no hay desplazamiento, cuando sí lo hay.

A ver si para la próxima lección, consigo descifrar el misterio.

Un saludo. AESOFT....

ASM POR AESOFT. (lección 6). --------------------------------------------------------------------

- CODIFICACION DE LAS INSTRUCCIONES EN EL 8086 (continuación lección 5). - MODOS DE DIRECCIONAMIENTO EN EL 8086. --------------------------------------------------------------------

- CODIFICACION DE LAS INSTRUCCIONES EN EL 8086 (continuación lección 5). -----------------------------------------------------------------------

En la lección 5 nos quedamos por descifrar el valor del byte EA en la siguiente instrucción:

MOV WORD PTR DS:[7654H],5 ---> C7 06 54 76 05 00

Teníamos claro el primer byte (código de operación) que nunca ofrece problemas de interpretación. Y era obvio también el campo 'desplazamiento' (formado por los bytes 3 y 4), así como el campo 'valor inmediato' (formado por los bytes 5 y 6).

Pero ante el segundo byte (byte EA o de direccionamiento) surgía la duda. He estado probando con instrucciones parecidas para ver si se aclaraba el tema. Y como conclusión puedo decir que cuando se direcciona una posición de memoria (como destino) sin ayuda de ningún registro (SI, DI,BX+SI, etc), el byte EA tendr valor 06. Esto lo digo de modo empírico. No lo he leído en ningún sitio, ni nada por el estilo. Me baso en las pruebas que he estado haciendo para encontrar algún sentido a ese 06.

Sinceramente, no s‚ por el porque de esta 'peculiaridad'. Por que se me ocurriría poner este ejemplo! :-) Por ejemplo, si hubiera usado un registro junto con el desplazamiento en esa instrucción habría problema. Veamos cómo quedaría la cosa:

* MOV WORD PTR DS:[DI+7654H],5 ---> Introduce el valor 5 (tipo palabra) en la posición de memoria direccionada mediante [DI] + 7654H. Es pr cticamente igual que la instrucción anterior, excepto que en ‚sta, hemos incluido el registro DI para acceder a la posición de memoria oportuna.

La codificación de la instrucción quedaría como sigue: MOV WORD PTR DS:[DI+7654H],5 ---> C7 85 54 76 05 00

Estudiemos el 'byte EA' de esta instrucción tan parecida a la anterior: 85h en binario queda como 10000101. El campo MOD con valor 10 indica que se usan 2 bytes para codificar el desplazamiento. Hasta ahora perfecto: 2 bytes para almacenar el desplazamiento 7654h. El campo REG con valor 000, ya que el valor a introducir no est en ningún registro, sino que es un dato inmediato (05) El campo R/M con valor 101, indicando que la dirección final viene dada por [DI] + desplazamiento.

Como podemos ver, la codificación de esta instrucción se ajusta a las tablas de codificación que vimos en la lección 5.

Veamos algún ejemplo mas, para que nos quede mas claro: * MOV BYTE PTR [DI+7],0AEH Esta instrucción deposita el valor 0AEH en la posición de memoria apuntada por DI+7, dentro del segmento direccionado por DS. Veamoslo mas detalladamente estudiando su codificación:

MOV BYTE PTR [DI+7],0AEH ---> C6 45 07 AE En primer lugar tenemos el código de operación C6, que le indica al procesador que se va a transferir un dato inmediato de tipo byte a una posición de memoria.

El tercer byte (campo 'desplazamiento') tiene un valor de 7, que es el que hemos indicado en la instrucción. Este valor es el que se sumar a DI para direccionar la posición de memoria deseada.

El cuarto byte (campo 'valor inmediato') tiene un valor de AE. Este valor es el que se depositar en la posición de memoria direccionada mediante DI+7.

Sólo nos queda estudiar el segundo byte (byte EA o modo de direccionamiento), el cual tiene un valor de 45 (en hexadecimal). Este 45, queda como 01000101 en binario.

Tenemos así que el campo MOD tiene un valor de 01. Si miramos en las tablas de codificación (ver lección 5), tenemos que 01 indica que se utiliza un byte para indicar desplazamiento. El campo REG tiene valor 000. Como no hay ningún registro involucrado en la instrucción, este campo no se tiene en cuenta. Por último, el campo R/M tiene como valor, 101. Esto indica que el desplazamiento final estar dado mediante [DI] + desplazamiento.

Como vemos, en esta instrucción est totalmente claro cada valor en cada uno de los campos del byte EA o 'modo de direccionamiento'.

Un último ejemplo:

* MOV WORD PTR [BX+SI+37H],AX Esta instrucción, introduce el valor del registro AX en la dirección de memoria indicada mediante el valor de la suma BX+SI+37H. Dentro del segmento DS, por supuesto. Siempre que no se especifique otro segmento, las transferencias a/desde memoria se har n sobre el segmento DS.

Veamos su codificación: MOV WORD PTR [BX+SI+37H],AX ---> 89 40 37 Simplemente 3 bytes para codificar esta instrucción que parece tan complicada. El primer byte (código de operación) tiene el valor 89 (hexadecimal). Este código 89 indica que se va a realizar una transferencia de datos de tipo palabra desde un registro (tamaño palabra) a un destino que puede ser (dependiendo del valor del byte EA): un registro de tamaño palabra o una dirección de memoria. Ya sabemos que el destino se trata de una dirección de memoria porque lo hemos indicado así al teclear la instrucción, pero el procesador no lo sabr hasta que descifre el valor del byte EA.

Este byte EA tiene un valor de 40h, que en binario queda como 01000000 El campo MOD tiene un valor de 01, que indica que se usa 1 byte para codificar el desplazamiento. Sólo es necesario 1 byte para codificar el valor 37h. El campo REG, que aquí tiene valor 000, indica que el registro fuente empleado es AX. El campo R/M con valor 000, indica que la dirección final se consigue mediante la suma: [BX] + [SI] + desplazamiento. Ver tablas en la lección 5. Como vemos aquí también est totalmente claro el valor del byte EA.

El tercer byte (campo 'desplazamiento') contiene el valor 37h como hemos indicado en la instrucción.

Espero que estos nuevos ejemplos hayan sido ilustrativos. En caso de que aún exista alguna duda acerca de la codificación de las instrucciones, levantad la mano :-)))

- MODOS DE DIRECCIONAMIENTO EN EL 8086. --------------------------------------------------------------------

Como ya hemos visto, las instrucciones están codificadas con 0, 1 ó 2 operandos. Estos operandos son cada uno de los campos que puede componer una instrucción ('byte EA', 'desplazamiento' y 'valor inmediato'). Pues bien, las operaciones se realizan entre registros o registros y memoria. Nunca entre memoria y memoria. Si echamos un vistazo al esquema de codificación, nos daremos cuenta del porque: No hay dos campos para almacenar 2 posiciones diferentes de memoria, mientras que sí que se pueden indicar 2 registros diferentes (uno fuente y otro destino) en una misma instrucción.

Existen varios modos de direccionamiento. Esta variedad se ofrece para una mayor comodidad en la programación. Así por ejemplo se puede utilizar el modo directo, cuando se conoce la dirección de la posición de memoria que nos interese. El resto de modos se utilizar n cuando no vayamos a acceder a una dirección de memoria conocida, o cuando nos sea mas cómodo por cualquier motivo.

* Modos de direccionamiento:

Inmediato --------- El dato aparece directamente en la instrucción. Es decir, se indica explícitamente en la instrucción.

Ejemplo: MOV AL,0AEH ---> Almacena el valor AE en el registro de tipo palabra (AL).

Modo Registro ------------- Cuando en la instrucción se realizan transferencias entre registros del procesador.

Ejemplo: MOV AX,BX ---> Introduce el valor de BX en AX.

Directo absoluto a memoria -------------------------- Aparece en la instrucción de forma explícita la dirección a la cual se quiere acceder. Esto es, en la codificación de la instrucción podemos encontrar 2 bytes indicando la posición de memoria que se quiere direccionar.

Ejemplo: MOV CX,WORD PTR DS:[7777] ---> Introduce el valor almacenado en la posición de memoria 7777 (dentro del registro DS) en el registro de tipo palabra (CX).

Directo relativo a un registro base ----------------------------------- Accede a una posición de memoria con la ayuda de un registro base. Estos registros base como ya vimos son BX y BP. La dirección final de la posición de memoria se indicar de la forma: Dirección final = [Registro_Base] + desplazamiento. Donde Registro_Base es o bien BX o bien BP.

Ejemplo: MOV AX,BYTE PTR [BX+7] ---> Introduce en AX el valor contenido en la posición de memoria direccionada mediante BX+7.

Directo relativo a un registro índice (Indexado) ------------------------------------------------ La dirección se obtiene sumando un desplazamiento (que se indicar en la instrucción) al contenido de un registro índice. Registros índice como ya vimos son: SI y DI. Donde SI se suele utilizar como registro índice fuente. 'Indice fuente' en ingl‚s = 'Source Index' = SI. Obviamente, DI se utilizar como registro índice destino. 'Indice destino' en ingl‚s = 'Destine Index' = DI.

La dirección final de la posición de memoria se indicar de la forma: Dirección final = [Registro_Indice] + desplazamiento. Donde Registro_Indice es o bien SI o bien DI.

Ejemplo: MOV AX,WORD PTR [SI+7] ---> Introduce en AX el valor contenido en la posición de memoria direccionada mediante SI+7.

En realidad, excepto cuando se utilizan los dos registros fuentes en una misma operación (al copiar cadenas de caracteres p.e.), en cuyo caso hay que asignar a SI la dirección de la cadena origen, y a DI hay que asignarle la dirección de la cadena destino... Excepto en este tipo de operaciones (como digo), podemos hacer uso de los registros SI y DI indistintamente al trabajar con direccionamientos. Es decir, que las dos instrucciones siguientes son correctas, y realizan exactamente la misma tarea (siempre que SI y DI tengan el mismo valor): MOV AX,WORD PTR [SI+7] MOV AX,WORD PTR [DI+7]

Modos indirectos de direccionamiento ------------------------------------ Si en los dos últimos modos de direccionamiento no se especifica desplazamiento, entonces hablamos de: Modo de direccionamiento indirecto por registro base, Modo de direccionamiento indirecto por registro índice, respectivamente.

Ejemplo: MOV AX,BYTE PTR [SI] ---> Introduce en AX el contenido de la posición de memoria direccionada mediante SI.

Indexado mediante una base -------------------------- La posición de memoria seleccionada se direcciona aquí mediante cuatro configuraciones posibles. Un registro BX o BP contiene la base y un registro SI o DI contiene el desplazamiento. Ademas, puede existir un desplazamiento opcional indicado mediante un valor num‚rico.

La dirección final de la posición de memoria se indicar de la forma: Dirección final = [Registro_Base] + [Registro_Indice] + desplazamiento. Donde Registro_Base es o bien BX o bien BP. Donde Registro_Indice es o bien SI o bien DI. Tenemos así las cuatro configuraciones posibles mencionadas:

- [BX] + [SI] + desplazamiento - [BX] + [DI] + desplazamiento - [BP] + [SI] + desplazamiento - [BP] + [DI] + desplazamiento

Ejemplo: MOV BYTE PTR [BX+SI],AL ---> Introduce el valor del registro AL en la posición de memoria direccionada mediante [BX] + [SI] + desplaz.

En todos los modos de direccionamiento, excepto en los dos primeros, se puede indicar un segmento diferente a DS para realizar las operaciones con la memoria. De esta forma, podemos manejar todo el Megabyte de memoria sin necesidad de modificar de valor el registro DS (registro de segmento de datos). Así, podemos utilizar el registro ES cuando queramos acceder a posiciones de memoria que est‚n fuera de nuestro segmento de datos.

Ejemplo: MOV AX,WORD PTR ES:[BX+7] ---> Introduce en AX el valor contenido en la posición de memoria direccionada mediante BX+7, dentro del segmento indicado por ES.



Artículos relacionados


No hay comentarios: