LECCION 2: ---------- ASM POR AESOFT. (lección 2). ---------------------------- - DIRECCIONAMIENTO DE MEMORIA EN EL 8086. - SEGMENTACION. -------------------------------------------------------------------- Hola a todos los seguidores del curso de ensamblador de AESOFT. En esta lección vamos a ver cómo direcciona la memoria el 8086, es decir, cómo el 8086 accede a cada una de las posiciones de memoria. La forma en que la CPU construye las direcciones de memoria es muy importante para la programación del sistema, debido a que constantemente utilizamos instrucciones de transferencias de datos, de acceso a funciones de la BIOS, del DOS, etc. Más adelante estudiaremos la BIOS. Valga por ahora que es un conjunto de utilidades y procedimientos grabados en la ROM (memoria de sólo lectura), los cuales 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). En cuanto al DOS (sistema operativo de disco), decir que aquí nos referi- mos no a las utilidades o comandos que trae consigo, que es lo típico que se enseña en academias e institutos, sino a la estructura interna del mismo: interrupción 21h, 24h, etc. Ya veremos también qué es una interrupción. Bien, antes de entrar de lleno en el tema, conviene saber un poco del por qué del mismo. Es decir, qué llevó a que fuera de esta forma y no de otra. 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, etc. Como he dicho, 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 fuera, 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 cpc-464 podía acceder a 64 ks de memoria. 64 Ks es la máximo que podía direccionar el z80 original. En ese momento Intel se planteó superar esa barrera de las 64 Ks, pero tenía un problema. El z80 por ejemplo, había consguido 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... Y 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 Ks de memoria (la máxima direccionable por un sólo registro). Entonces, para direccionar una posición de memoria nos valemos de dos registros: Registro de segmento y de offset. Ya vimos en la lección anterior que había varios registros de segmento: cs (registro de segmento de código), ds (de datos), etc. Pues bien, este primer registro (de segmento), indica dónde comienza el trozo de 64 Ks que buscamos. Y el segundo registro (el de offset), contiene el desplazamiento dentro de ese segmento. Bien. Hemos 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 8086 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 15 87 0 15 87 0 +------++------+ +------++------+ Byte alto Byte bajo Byte alto Byte bajo (más significativo)(menos signific) 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 8086. Pongamos que el registro DS tiene el valor 0B800h (en hexadecimal) (podeis utilizar SB-CALCU de SAN BIT para hacer los cambios de base, y trabajar con bases diferentes a la decimal. También para la decimal, por supuesto). 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 acturaría así: (Gráficamente) Haría una suma de la siguiente forma: DS: 1011100000000000 BX: + 0000000000110111 ---------------------------- 10111000000000110111 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, por ejemplo. Como ejemplo: El primer segmento posible empieza en la dirección física 0. El segundo empieza en la dirección Esto es más complejo de lo que parece. Si tienes alguna duda, ya sabes... Si le das vueltas a la idea, te darás 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. Si llegados a este punto no comprendes el tema de los segmentos, no sigas, ya que te perderías. Dime qué no entiendes y lo explicaré más detalladamente. Es todo por ahora. Ah, y no sé si recibísteis la primera lección. Parece que todo estaba claro. Si en éste no os surge ninguna duda, ya me mosqueo }:-))) Saludos. AESOFT..