Modelo de memoria Intel x86

El modelo de memoria para plataformas x86  es una forma de especificar las suposiciones que debe hacer el compilador al generar código para plataformas con direccionamiento de memoria segmentada o memoria paginada . La mayoría de las veces, el término se usa cuando se trabaja con varios modos heredados de la plataforma x86 .

Por ejemplo, hay seis modelos de memoria en una plataforma compatible con x86 de 16 bits. Determinan qué suposiciones se hacen sobre el segmento de registro predeterminado y el tamaño del puntero.

Segmentación de la memoria

La arquitectura x86 de 16 bits , debido a la presencia de registros de cuatro segmentos, permite el acceso simultáneo a cuatro segmentos de memoria. Propósito de los registros de segmento:

En dicha plataforma, se acostumbra escribir una dirección lógica como segmento : desplazamiento , donde el segmento y el desplazamiento se dan en notación hexadecimal .

En modo real, para calcular la dirección física de un byte de memoria, el valor del registro del segmento correspondiente se desplaza 4 bits a la izquierda y luego se suma el desplazamiento.

Por ejemplo, la dirección lógica 7522:F139 da una dirección física de 20 bits:

75220 + F139 = 84359

Cabe señalar que este proceso da como resultado un alias de memoria , es decir, cualquier dirección física dada puede tener múltiples representaciones lógicas. Esto hace que la comparación de punteros sea más difícil.

En modo protegido , GDT y LDT se utilizan para el mismo propósito .

Dimensiones del puntero

Los punteros pueden ser de tipo near (near), far (lejos) o enorme (grande).

El puntero cercano se refiere al segmento actual, por lo que ni DS ni CS deben cambiar cuando se elimina la referencia del puntero. Los punteros de este tipo son los más rápidos, pero están limitados a un área de puntero de 64 kilobytes de memoria (es decir, el segmento actual).

Los punteros lejanos contienen el nuevo valor DS o CS. Para usarlos, se debe cambiar el registro, desreferenciar la memoria y luego restaurar el registro. Dichos punteros pueden apuntar a 1 megabyte de memoria. Cabe señalar que las operaciones aritméticas con punteros (suma y resta) no cambian la sección del segmento del puntero, sino que solo afectan su desplazamiento. Las operaciones fuera de cero o 65535 (0xFFFF) estarán sujetas a una operación de módulo 64K, como cualquier operación normal de 16 bits. Por ejemplo, −1 con signo se convierte en 0xFFFF o 65535 sin signo.

Por ejemplo, el siguiente código quedará fuera del alcance y se sobrescribirá:

char lejano * myfarptr = ( char lejano * ) 0x50000000L ; contador largo sin firmar ; for ( contador = 0 ; contador < 128 * 1024 ; contador ++ ) // accede a 128K de memoria * ( myfarptr + contador ) = 7 ; // escribe todos los sietes en él

En algún momento, el contador será igual a (0x10000) y la dirección absoluta resultante excederá 0x5000:0000.

Los punteros enormes son esencialmente punteros lejanos, pero se normalizan cada vez que cambian para que tengan el segmento más alto al que puedan dirigirse. Esto es bastante lento, pero permite que un puntero apunte a múltiples segmentos, y también permite una comparación más precisa de punteros, como si la plataforma fuera un modelo de memoria plana : esto desactiva el alias de memoria como se mencionó anteriormente, por lo que dos punteros grandes apuntar a una misma pieza de memoria siempre será igual.

Modelos de memoria

Los modelos de memoria son:

Modelo Datos El código
Diminuto* cerca
pequeña cerca** cerca
Medio cerca lejos
Compacto lejos cerca
Largo lejos lejos
Enorme enorme enorme

* En el modelo Tiny, los cuatro registros de segmento apuntan al mismo segmento.

** En todos los modelos con punteros cercanos a los datos, SS es igual a DS .

Otras plataformas

En el modo protegido, el segmento no se puede sobrescribir, leer ni ejecutar.

Por lo tanto, al implementar los modelos de memoria Small y Tiny, el registro del segmento de código debe apuntar a la misma dirección física y tener la misma restricción que el registro del segmento de datos. Esto elimina una de las características del procesador 80286 , que garantiza que los segmentos de datos nunca se ejecuten y los segmentos de código nunca se sobrescriban (lo que significa que el código automodificable está completamente prohibido ). Sin embargo, en los procesadores 80386 con su modelo de memoria plana, es posible proteger contra escritura páginas individuales de memoria.

Los modelos de memoria no se limitan a programas de 16 bits. También es posible usar la segmentación en modo protegido de 32 bits (lo que da como resultado punteros de 48 bits), y hay compiladores de C que lo admiten.

Sin embargo, la segmentación en modo de 32 bits no permite el acceso a más espacio de direcciones que el que cubre un segmento, excepto algunos segmentos que no siempre están representados en la memoria, y el espacio de direcciones lineal simplemente se usa como caché debido a la mayor espacio virtual segmentado.

En su mayor parte, esto permite una mejor protección del acceso a varios objetos (las áreas de hasta 1 megabyte de tamaño pueden beneficiarse de la división byte a byte de la protección de acceso, a diferencia de la división bastante "gruesa" de 4 KiB que ofrece un solo página) y, por lo tanto, solo se utiliza en aplicaciones especiales, como software de telecomunicaciones.

Técnicamente, un espacio de direcciones "plano" de 32 bits es un modelo de memoria "pequeño" para un espacio de direcciones segmentado. Bajo la influencia de ambos factores, los cuatro registros de segmento contienen el mismo valor.

En la plataforma x86-64 , hay siete modelos de memoria [1] , siendo la mayoría de los enlaces simbólicos de solo 32 bits, y si la dirección se conoce en el momento del enlace (a diferencia del código independiente de la posición ). Esto no afecta el uso de punteros, que siempre son punteros planos de 64 bits, pero solo en términos de acceso a valores a través de la asignación de caracteres.

Véase también

Notas

  1. アーカイブされたコピー. Consultado el 26 de septiembre de 2010. Archivado desde el original el 16 de julio de 2011.

Literatura

  • Guía del usuario de Turbo C++ versión 3.0 . Borland Internacional, 1992.