Búsqueda personalizada

Anuncios Google

La plataforma IA-32

Registros de segmento

Los registros de segmento se utilizan para referenciar áreas de memoria. La plataforma IA-32 permite direccionar la memoria según el modelo de memoria lineal o el modelo de memoria segmentada. El modelo de memoria lineal presenta todo el espacio de direcciones de la memoria como un espacio contiguo. Todas las instrucciones, los datos y la pila se encuentran en el mismo espacio de direcciones de memoria. Cada posición de memoria se referencia mediante una dirección específica llamada "dirección lineal".

El problema del enfoque anterior consiste en que todos los datos se encuentran mezclados entre si y a la vez distribuidos a lo largo de todo el espacio de direcciones memoria, lo cual hace que su manejo sea engorroso e ineficiente. El modelo de memoria segmentada resuelve este problema dividendo el espacio de direcciones en segmentos independientes entre si. Cada segmento contiene un tipo específico de información, es decir el código (las instrucciones) se ubica en un segmento, los datos en otro y la pila en un tercer segmento. Las posiciones de memoria en los segmentos se definen por direcciones lógicas. Una dirección lógica está compuesta por una dirección de segmento y un desplazamiento. El procesador traduce una dirección lógica a una dirección lineal.

Nota: Aún cuando la siguiente información es muy útil para aprender acerca de cómo está estructurada la memoria no es imprescindible para comenzar a programar en lenguaje ensamblador. Si quieres, puedes pasar directamente al tema acerca de las banderas.

Los procesadores de la familia Intel poseen un grupo de registros creados con el fin de soportar el modelo de memoria segmentada, los cuales son conocidos como registros de segmento:

Registro de segmento Descripción
cs Segmento de código
ds Segmento de datos
ss Segmento de pila
es Apuntador de segmento extra
fs Apuntador de segmento extra
gs Apuntador de segmento extra

El contenido de los mismos es interpretado de diferente forma dependiendo si el procesador se encuentra trabajando en modo real o en modo protegido. Los procesadores más antiguos de esta familia trabajaban en modo real, en el cual un registro de segmento simplemente contenía una dirección lineal que señalaba el comienzo de un segmento. De esta forma, si un programa intentaba acceder a un dato ubicado en el desplazamiento "D" del segmento apuntado por el registro ds, la traducción a una dirección lineal consistía en tomar el contenido de dicho registro, multiplicarlo por 0x10 (esto es la dirección de inicio del segmento de datos en uso) y sumarle el desplazamiento "D".

Por ejemplo:

Sin embargo, con el paso de los años este enfoque resultó ser insuficiente, ya que por ejemplo, no había forma de determinar si un desplazamiento causaba que la dirección lineal cayera fuera del segmento. Para solventar éste y otros problemas de seguridad, se implementó a partir del procesador 80286 el modo protegido.

En el modo protegido, el registro de segmento ya no contiene la dirección base del segmento, sino un selector de segmento, el cual permite seleccionar un descriptor de segmento. Este último no es más que una estructura de ocho bytes, la cual posee un formato definido y contiene entre otras cosas la dirección base del segmento en cuestión:

Descriptor de segmento del 80286

Descriptor de segmento del 80386 y posteriores

De esta manera, la dirección base del segmento pasa ahora a ocupar 24 ó 32 bits (dependiendo del procesador), en contraposición a los 16 bits que pueden almacenarse en el registro de segmento en modo real. Adicionalmente se cuenta con un campo de límite de segmento que puede ocupar 16 ó 20 bits, lo que determina el tamaño máximo de los segmentos en 64KB o 1MB. El descriptor de segmento del 80386 incluye una bandera (G) que indica que el campo límite debe ser multiplicado por 4K, permitiendo entonces la existencia de segmentos entre 4KB y 4 GB.

El descriptor de 80386 incluye dos banderas adicionales. La primera de ellas (D/B), permite determinar si se está trabajando en modo de 16 ó 32 bits. La segunda (AVL) puede ser utilizada por los sistemas operativos para marcar el segmento descrito como disponible o no (Available). El campo de permisos de acceso posee los siguientes subcampos:

El campo RPL (Request Privilege Level) permite indicar el nivel de privilegio con el cual se está accediendo al segmento, siendo 00 el nivel más bajo y 11 el más alto. Este valor debe ser mayor o igual al del campo DPL del descriptor correspondiente. Adicionalmente el campo TI (Table Indicador) es una bandera que permite escoger la tabla en la cual será seleccionado el descriptor de segmento con los bits restantes (0 = tabla de descriptores globales, 1 = tabla de descriptores locales). Los descriptores globales son utilizados por todos los programas y a menudo se les conoce como descriptores de sistema, mientras que los descriptores locales son exclusivos de un programa particular y a menudo se les conoce como descriptores de aplicación.

De esta forma, el mismo acceso a memoria que ejemplificamos anteriormente, se llevaría a cabo de la siguiente manera en modo protegido:

En primer lugar, el descriptor de segmento indica que debe seleccionarse el descriptor número 2 (Selector = 0000000000010) de la tabla de descriptores locales (TI = 1) con un nivel de privilegio de 1 (RPL = 01). De esta manera, se procede a interpretar los ocho bytes correspondientes al mismo en la TDL. Dicho descriptor indica que la dirección base del segmento en cuestión es la 0x00020000, y que el tamaño del mismo es de 0x0A000, lo que quiere decir que el límite del mismo corresponde a la dirección 0x2A000. Dado que el RPL es mayor que el DPL (00) se permite el acceso al segmento. De manera similar, se verifica que la dirección lineal resultante (0x20000 + 0x8A00) se encuentra dentro de los límites del segmento.

El proceso de traducción de direcciones es un poco más complejo de lo que puede intuirse a partir de esta breve explicación, involucrando el uso de una caché para agilizar el acceso a las tablas de descriptores. Es importante tener en mente también que la memoria puede estar paginada, en cuyo caso será necesario transformar las direcciones lineales (virtuales) a direcciones físicas o reales. Por último, cabe acotar que los registros ES, FS y GS apuntan a segmentos de datos (o seleccionan descriptores de segmentos de datos).

Registro apuntador de instrucción

El registro apuntador de instrucción (eip) o contador de programa contiene la dirección de la próxima instrucción a ejecutarse.

Registros de punto flotante

Son ocho registros los cuales son tratados como una pila. Se denominan %st(0), %st(1), %st(2), etc. %st(0) se ubica en el tope de la pila.