1. 2. CAPITULO II: ASPECTOS BASICOS DE LA PROGRAMACION EN ENSAMBLADOR
2.1. REGISTROS
Los procesadores de la familia 80x81 son procesadores de 16, 32 o 64 bits, el tamaño de bits es el tamaño
máximo de transferencia o tamaño máximo de manipulación de los datos que serán procesados en un
determinado tiempo.
Con relación a esto, el procesador cuenta con una serie de registros para realizar las operaciones de
cálculo, y como almacenamiento de datos.
Un registro es un lugar donde se almacena o guardan los datos, tiene una longitud de 16 o 32, cada
registro tiene dos subregistros de 8 bits cada uno cuando el registro es de 16 bits, dos subregistros de 16
bits cuando el registro es de 32 bits y dos subregistros de 16 bits cuando el registro es de 64 bits.
Estos registros se dividen en 5 grupos, según sus funciones:
2.1.1. REGISTROS DE PROPÓSITO GENERAL: La principal misión de estos registros es el de
almacenar datos relevantes de los programas y operandos.
AX o EAX: Registro Acumulador
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
AH AL
Registro AX (EAX).- Esta dedicado a operaciones aritméticas (multiplicación, división), operaciones de
entrada/salida, de traducción, procesamiento de cadenas (string) y transferencias.
Este registro es el más usado, siendo de propósito general; y tiene ciertas especializaciones, de ahí su
nombre:
§ Es el único que puede ser usado como multiplicando en la multiplicación
§ Es el único que puede ser usado como dividendo en la división
§ Es el parámetro que selecciona los distintos servicios del Sistema Operativo, usados mediante
el mecanismo de Interrupciones.
BX o EBX: Registro Base
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
BH BL
Registro BX (EBX).- Se utiliza como puntero Base, específicamente en el direccionamiento de la
memoria, entre otras actividades puede ser utilizado para almacenar la parte relativa de la dirección del
segmento, (nos referimos al desplazamiento), en este caso trabaja junto al registro DS (Data Segment).
También es utilizado como índice en direccionamiento extendido, para el manejo de tablas y para
operaciones aritméticas.
Este registro, además de las características generales de los registros de propósito general, se especializa
en:
§ El acceso a memoria en combinación con los registros de índice, especialmente para el manejo de
arreglos.
SIS-330 :: Programación en Assembler 14
2. CX o ECX: Registro Contador
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
CH CL
Registro CX (ECX).- Este registro se utiliza como contador de iteraciones, en determinadas
instrucciones de repetición y desplazamientos.
Este registro, como su nombre indica, será ampliamente usado como contador. Puede ser usado como
cualquier registro de propósito general, pero tiene capacidades especiales para ser usado en instrucciones:
§ de manejo de ciclos
§ como contador en los corrimientos
§ de manejo de memoria y strings
DX o EDX: Registro de Datos
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
DH DL
Registro DX (EDX).- Se utiliza en operaciones aritméticas (multiplicación y división), direccionamiento
indirecto, también en operaciones de entrada/salida.
Este registro de propósito general tiene como especializaciones:
§ Formar con AX números de 32 bits, siendo en este caso la parte más significativa.
§ El acceso a puertos. Las instrucciones IN y OUT, que permiten dicho acceso, requerirán en
ciertos casos que el número de puerto esté en DX.
2.1.2.REGISTROS DE SEGMENTO: Para el manejo de los Segmentos
CS: Registro de Segmento de Código
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
Code Segment
Registro CS.- Segmento de Código, este registro contiene la dirección inicial del segmento de código,
guarda o almacena los Códigos de operación de las instrucciones, esta relacionado con el registro IP.
Este registro selecciona el área de 64 Kb. que generalmente dedicamos al código. En este caso, el CPU,
siempre toma las instrucciones de esta región de memoria; por lo que cuando requerimos más de 64 Kb.
de código (instrucciones), este registro tendrá que moverse, tomando distintos valores según recorremos
distintas regiones de memoria.
SIS-330 :: Programación en Assembler 15
3. DS: Registro de Segmento de Datos
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
Data Segment
Registro DS.- Segmento de datos, este registro contiene la dirección inicial donde se almacenan los
datos. selecciona una sección de 64 Kb. que se dedica generalmente a colocar en ella nuestras variables,
por lo cual toma su nombre: sección de memoria dedicada a datos.
SS: Registro de Segmento de Pila
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
Stack Segment
Registro SS.- A través de este registro se incrementa la zona de memoria que actúa como pila. Contiene
la dirección inicial del segmento de pila.
Este registro selecciona la región de 64 Kb. que va a contener la pila del sistema. Como su nombre lo
indica, tendremos una estructura de datos, con política LIFO (Last In, First Out = El último elemento en
entrar, es el primero en salir), con instrucciones básicas PUSH y POP para su manejo. Esta estructura es
usada por los programas de aplicación, pero también por el procesador para el control de instrucciones
que lo requieren, tales como las llamadas a subrutinas y la atención de interrupciones.
ES: Registro de Segmento Extra (FS, GS 386+, Extra Segments)
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
Extra Segment
Registro ES.- Contiene la dirección inicial del segmento de un segmento extra de datos. Generalmente
este segmento extra es utilizado en operaciones con cadena, entradas y salidas para manejar direcciones
de memoria y transferencias de datos entre segmentos.
Este registro nos permite seleccionar una sección de 64 Kb., que no está destinada a ningún uso
específico; por lo que el programador puede aplicarla como comodín, generalmente como un segundo
segmento de datos; o bien, para el acceso a regiones de memoria del sistema, tales como la memoria de
video o las variables del BIOS.
En resumen estos 4 segmentos nos indican las direcciones iniciales de los segmentos de pila, datos,
código y extra.
SIS-330 :: Programación en Assembler 16
4. 2.1.3. REGISTROS PUNTERO DE PILA Y REGISTROS INDICE:
SP o ESP: Registro de Apuntador de Pila
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
Stack Pointer
Registro SP (ESP).- Este registro contiene la dirección de la cabeza o inicio de la pila, esta asociado
estrictamente con el registro SS (Stack Segment).
Este registro también está siempre asociado al manejo de la pila. Su función especial es marcar el tope de
la pila, y por tanto, indica en qué localidad de memoria se localiza la información de la pila; se incrementa
cuando se hace un POP, con lo que apunta al siguiente elemento en la pila; y se decrementa al hacer un
PUSH, con lo que controla el acceso a la memoria de la pila.
BP o EBP: Registro de Apuntador de Base
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
Base Pointer
Registro BP (EBP).- Este registro es denominado Puntero Base, permite direccionamiento a pila, por
otro lado permite la referenciación de parámetros (datos o direcciones relacionados con la pila). Otro uso
es para determinar el offset o desplazamiento dentro de la pila, sea como Índice o como dirección base.
Este registro es usado para accesar, dentro del segmento de pila, la información. Principalmente nos
permite determinar cuando hay un underflow, es decir, cuando se quiere sacar más información de la pila
que la que se ha colocado en ella; y el acceso a variables locales y parámetros.
SI o ESI: Registro Indice Fuente
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
Fuente Index
Registro SI (ESI).- Significa Indice Fuente, relacionado con el registro de segmento DS (Data Segment).
También se utiliza en operaciones con cadenas a través de índices, como elemento de indexación.
Este registro se especializa en el acceso a bytes o words dentro del segmento de datos; existen
instrucciones que lo toman por defecto como el registro que apunta a una localidad de memoria que se va
a leer, por lo cual toma su nombre.
SIS-330 :: Programación en Assembler 17
5. DI o EDI: Registro Indice Destino
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
Destino Index
Registro DI (EDI).- Indice Destino, internamente relacionado con el registro DS (Data Segment), a
través de estas direcciones se pueden hacer varios tipos de operaciones, operaciones con cadenas en
destino.
Este registro se especializa en el acceso a bytes o words dentro del segmento de datos o el extra; existen
instrucciones que lo toman por defecto como el registro que en combinación con el ES apunta a una
localidad de memoria que se va a escribir, por lo cual toma su nombre.
2.1.4.REGISTROS DE PUNTERO Y FLAG:
IP o EPI: Registro de apuntador de siguiente instrucción
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
Instruction Pointer
Registro IP (EPI).- Este registro contiene la dirección del desplazamiento de la instrucción ejecutada,
determinando dentro del segmento de código la dirección de la siguiente instrucción, se añade la dirección
de este registro. Este registro puede manejar direcciones solo en forma indirecta.
FLAG o EFLAG: Registro de Banderas
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
Flag
Registro FLAG (EFLAG).- Este registro permite determinar el estado de ejecución, íntimamente
relacionado con la ALU9 (Unidad Aritmética Lógica), consta de 16 o 32 bits, 9 de estos actúan como
señalizadores.
bit 0 - Carry: Este bit es de acarreo, producto de operaciones aritméticas, de rotaciones y otros. (NC
= no hay acarreo; CY = Sí lo hay)
bit 2 - Parity: Se utiliza para el control de la paridad en operaciones en la A.L.U. e indica el número
de par de bits, cuando este bit es 1 es par, cuando 0 es impar. (PO = paridad non; PE = paridad par)
bit 4 - Auxiliary Carry: Se utiliza para acarreos auxiliares, propiamente entre nibbles (4 bits),
indica el ajuste necesario en operaciones aritméticas decimales. (NA = no hay acarreo auxiliar; AC =
hay acarreo auxiliar)
9 ALU: Aritmetic Unit Logic, este componente, como su nombre indica, contiene la circuitería necesaria para realizar las diversas
operaciones aritméticas y lógicas. Recibe sus operandos por un Bus denominado A, y genera los resultados regresándolos al
mismo bus. Una particularidad que es importante recalcar es su conexión al registro de banderas, por lo cual todas las
operaciones aritméticas y lógicas, de acuerdo a su resultado, lo alterarán.
SIS-330 :: Programación en Assembler 18
6. bit 6 - Zero: Se coloca en 1 cuando el resultado de la operación es cero. (NZ = no es cero; ZR = sí
lo es)
bit 7 - Sign: A través de este bit se indica el resultado de la comparación negativa o de resultados
aritméticos, si el resultado es positivo, el bit se pone en 0, si es negativo se pone en 1. (PL = positivo;
NG = negativo)
bit 8 : Controla la ejecución paso a paso, generalmente controla las excepciones de ejecución. Esta
íntimamente relacionado con el utilitario DEBUG.
bit 9 - Interrupts: Controla las interrupciones 1= interrupción permitido, 0 = interrupción no
permitida. (DI = desactivadas; EI = activadas)
bit 10 - Direction: A través del cual se controla la dirección izquierda o derecha, en cadenas de
caracteres, es decir determinar la dirección de exploración de la cadena, esta íntimamente relacionado
con el registro SI y DI. (UP = hacia adelante; DN = hacia atrás)
bit 11 -Overflow: en relación al bit más significativo, interviene en operaciones aritméticas. (NV = no
hay desbordamiento; OV = sí lo hay)
2.2. SEGMENTACIÓN
Los chips de memoria se dedican meramente a almacenar la información hasta que se necesita. El número
y la capacidad de almacenamiento de estos chips que hay dentro del ordenador determinan la cantidad de
memoria que podremos utilizar para los programas y los datos.
La forma en que la CPU construye las direcciones de memoria es muy importante para la programación
de cualquier sistema, debido a que constantemente utilizamos instrucciones de transferencias de datos, de
acceso a funciones de la BIOS, y del S.O., en la BIOS se encuentran rutinas que se encargan de acceder
al nivel más bajo en cuanto a programación se refiere. Es decir, estas rutinas se encargan de manipular el
hardware por nosotros. BIOS son las siglas de Basic Input Output System (Sistema básico de
entrada/salida).
A principio de los años 80, Intel (fabricante de la familia de procesadores 80x86) se propuso dar un gran
paso adelante con respecto a la competencia. En aquel tiempo los microprocesadores que imperaban entre
los ordenadores domésticos eran de 8 bits, es decir, tenían un ancho de bus de datos de 8 bits, el tamaño
de palabra de memoria era de 8 bits, y los registros del procesador eran de 8 bits. Un claro ejemplo de
esto fue el microprocesador Z80 (de la empresa Zilog), el cual estaba incorporado en máquinas tan
famosas como los spectrum, amstrad, msx. En estos equipos el ancho del bus de datos era de 8 bits. Esto
quiere decir que todas las transferencias de datos que se hicieran se harían de 8 en 8 bits, es decir, byte a
byte.
Pues bien, aunque el microprocesador era de 8 bits, y la mayoría de registros también lo eran, había
alguno mayor (16 bits). Me estoy refiriendo sobre todo al registro de direcciones que era de 16 bits. De
esta forma, un amstrad cpcA464 podía acceder a 64 kb de memoria. 64 Kb es la máximo que podía
direccionar el z80 original.
SIS-330 :: Programación en Assembler 19
7. En ese momento Intel se plantea superar esa barrera de las 64 Ks, pero tenían un problema. El z80 por
ejemplo, había conseguido tener registros de 16 bits cuando el microprocesador es de 8. Pero pasar de 16
bits de capacidad en registros en aquellos momentos no era posible para los microprocesadores. Es decir,
no había suficientes avances tecnológicos como para conseguir tamaños de registros mayores en un
microprocesador. De tal manera que había que buscar una fórmula diferente. De ahí es cuando surgió el
tema de los segmentos que tantos quebraderos de cabeza a dado hasta ahora y sigue dando. A Intel se le
ocurrió la idea de construir una dirección de 20 bits de ancho y colocarla en el bus de direcciones para
poder dirigirse a la memoria. Pero al ser los registros de 16 bits, sólo había una solución posible para
crear este ancho de 20 bits: Usar 2 registros de 16 bits!. El 8086 divide el espacio de direcciones (1
Mbyte) en segmentos, cada uno de los cuales contiene 64 Kb de memoria (la máxima direccionable por un
solo registro). Entonces, para direccionar una posición de memoria nos valemos de dos registros:
Registro de segmento y de desplazamiento
Este primer registro (de SEGMENTO), indica donde comienza el trozo de 64 Kb que buscamos.
Y el segundo registro (el de DESPLAZAMIENTO), contiene el desplazamiento dentro de ese segmento.
Se ha visto que son necesarios 2 registros para direccionar ese Mbyte de memoria, y tenemos un bus de
direcciones de 20 bits. Esto nos conduce a que el microprocesador debe realizar unas operaciones sobre
estos dos registros para obtener la dirección física de 20 bits.
Esto se logra de la siguiente manera:
El 80x86 mueve el valor del segmento 4 bits a la izquierda y le suma el valor del desplazamiento para
crear una dirección de 20 bits.
Gráficamente: Tenemos dos registros de 16 bits.
DS: XXXXXXXXXXXXXXXX BX: XXXXXXXXXXXXXXXX
El primer registro, es el de segmento (en este caso, segmento DS, de datos). El segundo registro es el de
offset o desplazamiento. En este caso utilizamos el registro BX para direccionar dentro de el segmento.
Podíamos haber utilizado también el registro SI, el DI, etc. A partir de estos dos registros, debemos
acceder a una posición de memoria física dentro del Mbyte de que disponemos para el 80x86. Pongamos
que el registro DS tiene el valor 0B800h (en hexadecimal), y el registro BX contiene el valor 0037h.
Tenemos pues (en binario):
DS: 1011100000000000 BX: 0000000000110111
Para obtener la dirección física de memoria, y teniendo en cuenta todo lo dicho relativo a segmentos, el
microprocesador actuaría así:
Haría una suma de la siguiente forma:
1 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 1 1 0 1 1 1
1 0 1 1 0 0 0 0 0 0 0 0 0 0 1 1 0 1 1 1
DS:
BX:
SIS-330 :: Programación en Assembler 20
8. Obteniendo así la dirección de 20 bits necesaria para cubrir todo el Mbyte. Si ese número
(10111000000000110111) que está en binario, lo pasamos a hexadecimal, tenemos que la dirección física
correspondiente a la anterior segmentada es: 0B8037h.
De todo lo anterior, se desprende que los segmentos empiezan siempre en direcciones divisibles por 16.
Más técnicamente: cada segmento comienza en una dirección de párrafo.
Un párrafo son 16 bytes. Por supuesto nunca habrá un segmento que empiece en una dirección impar.
Aquí una observación, si uno prueba con diferentes valores tanto en el segmento y en el desplazamiento,
se dará cuenta que diferentes combinaciones de direcciones segmentadas dan una misma dirección física.
También se puede apreciar que los segmentos se pueden superponer unos a otros, pueden ser idénticos, o
pueden encontrarse en partes totalmente lejanas en la memoria.
2.3. DESPLAZAMIENTOS
En un programa, todas la localidades de memoria están referidas a una dirección inicial de segmento. La
distancia en bytes desde la dirección del segmento se define como el desplazamiento (offset).
Un desplazamiento de dos bytes (16 bits) puede estar en el rango de 0000H hasta FFFFH, o bien, desde
cero hasta 65, 535. Así el primer byte del segmento de código tiene un desplazamiento 00, el segundo byte
tiene un desplazamiento 01, etc. hasta el desplazamiento 65, 535. Para referir cualquier dirección de
memoria en un segmento, el procesador combina la dirección del segmento en un registro de segmento
con un valor de desplazamiento.
Indistintamente del lenguaje de programación que estemos utilizando, cuando obtenemos el ejecutable,
éste está compuesto únicamente por ese tipo de instrucciones básicas (instrucciones de código máquina).
Dependiendo de la calidad y prestaciones de ese lenguaje de programación, el código resultante, necesita
más instrucciones del procesador o menos.
De todos es conocido, que hay lenguajes de alto o medio nivel (como C, pascal, basic, C++, etc.) en los
que para una misma tarea, un lenguaje puede generar un ejecutable más grande que otro. 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.
Las instrucciones del 8086 se codifican sobre 4 campos como máximo, y tienen un tamaño de 1 a 6 bytes.
Es decir, dependiendo de la instrucción de que se trate, necesita más o menos bytes para su codificación,
así como más o menos campos.
Los cuatro campos en una instrucción código máquina son:
§ Código de operación: Una vez que el procesador descifra el significado de este campo, sabe si la
instrucción consta de más campos o si se trata de una instrucción de un sólo campo.
§ Desplazamiento del dato (sobre 8 o 16 bits): En caso de existir éste campo, supone un
desplazamiento sobre la dirección dada por un registro índice o base (especificado este registro
mediante el byte EA).
SIS-330 :: Programación en Assembler 21
9. § 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).
§ 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.
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.
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, 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.
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 mayú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.
2.4. DIRECCIONAMIENTO
El direccionamiento y sus modos de direccionamiento son un conjunto de reglas que se especifican para
localizar la posición de un dato que es utilizado durante la ejecución de una instrucción. También se puede
decir que son procedimientos que se emplean en las instrucciones para localizar sus operandos donde se
encuentran los datos que la Unidad Central de Proceso tendrá que procesar.
La extensión máxima que se puede direccionar con algunas maquinas es 1 Megabyte. Las formas que
pueden especificarse para el direccionamiento de memoria se lo realiza a través de un desplazamiento, de
esta forma producir una dirección efectiva, y estas formas pueden utilizarse los registros BX o BP, el
registro SI o DI o utilizando un desplazamiento relativo como parte de la instrucción (una instrucción esta
formada por un código de operación y operandos
Código de Operación Operando1, Operando2
Destino Fuente
SIS-330 :: Programación en Assembler 22
10. MODOS DE DIRECCIONAMIENTO:
Para comprender los diferentes modos de direccionamiento que se presentaran, es imperativo entender el
ciclo de operación básico de la computadora. La unidad de control de una computadora esta diseñada
para recorrer un ciclo de instrucciones que se divide en tres fases principales:
§ Búsqueda de la instrucción de la memoria.
§ Decodificar la instrucción.
§ Ejecutar la instrucción.
Direccionamiento Registro.- En este modo el campo de los operandos corresponde a uno de los
registros de la CPU. La velocidad de este modo es bastante alta en relación a las otras. El dato a procesar
esta en un registro, la CPU trabaja con este dato, en este modo NO se utiliza dirección de segmento.
Los diferentes registros son utilizados como variables.
ADD AX, BX
Antes de la operación Ejecutando
AX = 0001 -------> 0003
BX = 0002 -------> 0002
Direccionamiento Inmediato: En este caso el valor del operando es el que consta en la propia
instrucción, de este modo se utiliza cuando se necesitan definir constantes, no existe la utilización de un
registro segmento, se trabaja directamente con los siguientes registros del CPU.
Ejemplo: MOV AX, 34h
Direccionamiento Directo: La dirección viene dada a través de un nombre simbólico, que representa a
una variable o etiqueta. La dirección efectiva es especificada como parte de la instrucción. El registro DS
se asume por defecto.
Ejemplo:
MOV Num, 8 específicamente MOV DS:Num, 8
Direccionamiento mediante un registro: En este caso el desplazamiento o el offset, se halla en uno de
los registros indice o base; Registros Indice BX, BP; registros SI, DI
Para especificar al registro referido se usa el segmento DS.
[BX], [SI], [DI] ---> por defecto se usa el segmento DS
[BP] ---> por defecto utiliza el segmento SS
Ejemplo: ADD AL, [ BX ]
SIS-330 :: Programación en Assembler 23
11. Direccionamiento Relativo a Base: En este modo la posición del dato con respecto al registro segmento
viene dado por el contenido de BX o BP como base y un registro offset sobre esa base.
Ejemplo: MOV AX, [ BX + 5 ]
Lleva el contenido de la dirección resultante de esta operación, al registro AX. Una de las aplicaciones
que se puede hacer con este modo de direccionamiento es cuando se trabaja con vectores en memoria.
Direccionamiento Directo Indexado: La dirección del dato viene dado por una base que es una
constante o una variable y un desplazamiento con respecto a la base que viene contenido en los registros
SI o DI.
Ejemplo: ADD AX, [ DI + 8 ]
Direccionamiento Indexado a Base: Este modo es una combinación de los 2 modos anteriores. El
desplazamiento que nos da la posición del dato viene dado por la suma de los contenidos de BX o BP, de
DI o SI y en forma opcional un desplazamiento adicional que puede ser dado por una constante o una
variable.
BX, SI, DI --> Segmento DS
BP --> Segmento SS
Ejemplo: ADD [ BX + SI + Num ], AX
SIS-330 :: Programación en Assembler 24