Primero, esto no tiene nada que ver con RAM, realmente. Estamos hablando del espacio de direcciones aquí, incluso si solo tiene 16 MiB de memoria, todavía tiene los 32 bits completos de espacio de direcciones en una CPU de 32 bits.
Esto ya responde a su primera pregunta, realmente: en el momento en que esto fue diseñado, las PC del mundo real no tenían ni cerca de los 4 GiB de memoria; estaban más en el rango de 1-16 MiB de memoria. El espacio de direcciones era, para todos los efectos, gratuito.
Ahora, ¿por qué 0xFFFFFFF0 exactamente? La CPU no sabe qué cantidad de BIOS hay. Algunas BIOS solo pueden tomar unos pocos kilobytes, mientras que otras pueden tomar megabytes completos de memoria, y ni siquiera estoy entrando en las diversas RAM opcionales. La CPU debe estar conectada a alguna dirección para comenzar, no hay forma de configurar la CPU. Pero esto es solo una asignación del espacio de direcciones: la dirección se asigna directamente al chip ROM del BIOS (sí, esto significa que no tiene acceso a los 4 GiB completos de RAM en este punto si tiene tantos, pero eso no es nada especial, muchos dispositivos requieren su propio rango en el espacio de direcciones). En una CPU de 32 bits, esta dirección le proporciona 16 bytes completos para realizar la inicialización muy básica, que es suficiente para configurar sus segmentos y, si es necesario, el modo de dirección (recuerde,"procedimiento" de arranque real . En este punto, no usa RAM en absoluto; todo es solo ROM asignada. De hecho, la RAM ni siquiera está lista para usarse en este momento, ¡ese es uno de los trabajos de BIOS POST! Ahora, podría estar pensando: ¿cómo accede un modo real de 16 bits a la dirección 0xFFFFFFF0? Claro, hay segmentos, por lo que tiene un espacio de direcciones de 20 bits, pero eso todavía no es lo suficientemente bueno. Bueno, hay un truco: los 12 bits altos de la dirección se configuran hasta que ejecutas tu primer salto largo, dándote acceso al espacio de direcciones altas (mientras rechazas el acceso a cualquier cosa menor que 0xFFF00000, hasta que ejecutes un salto largo) .
Todo esto son las cosas que en su mayoría están ocultas para los programadores (sin mencionar a los usuarios) en los sistemas operativos modernos. Por lo general, no tiene acceso a nada de tan bajo nivel: algunas cosas ya están más allá de la recuperación (no puede cambiar los modos de la CPU de forma involuntaria), algunas son manejadas exclusivamente por el núcleo del sistema operativo.
Entonces, una mejor vista proviene de la codificación de la vieja escuela en MS DOS. Otro ejemplo típico de la memoria del dispositivo que se asigna directamente al espacio de direcciones es el acceso directo a la memoria de video. Por ejemplo, si desea escribir texto en la pantalla rápidamente, escribió directamente a la dirección B800:0000
(más desplazamiento - en modo de texto 80x25, esto significa que (y * 80 + x) * 2
si mi memoria me sirve bien - dos bytes por carácter, línea por línea). Si deseaba dibujar píxel por píxel, utilizaba un modo gráfico y la dirección de inicio A000:0000
(normalmente, 320x200 a 8 bits por píxel). Hacer cualquier cosa de alto rendimiento generalmente significa sumergirse en los manuales del dispositivo, para descubrir cómo acceder a ellos directamente.
Esto sobrevive hasta nuestros días, simplemente está oculto. En Windows, puede ver las direcciones de memoria asignadas a los dispositivos en el Administrador de dispositivos: solo abra las propiedades de algo como su tarjeta de red, vaya a la pestaña Recursos, todos los elementos del Rango de memoria son asignaciones de la memoria del dispositivo a su espacio de direcciones principal. Y en 32 bits, verá que la mayoría de esos dispositivos se asignan por encima de la marca de 2 GiB (más tarde 3 GiB), nuevamente, para minimizar los conflictos con la memoria utilizable por el usuario, aunque esto no es realmente un problema con la memoria virtual ( las aplicaciones no se acercan al espacio real de direcciones de hardware : tienen su propia porción de memoria virtualizada, que podría asignarse a RAM, ROM, dispositivos o al archivo de página, por ejemplo).
En cuanto a la pila, bueno, debería ayudar entender que, de manera predeterminada, la pila crece desde la parte superior. Entonces, si hace una push
, el nuevo puntero de la pila estará en 0xFFFFFEC
, en otras palabras, no está tratando de escribir en la dirección de inicio del BIOS :) Lo que, por supuesto, significa que las rutinas de inicio del BIOS pueden usar la pila de manera segura, antes de reasignarla En algún lugar más útil. En la programación de la vieja escuela, antes de que la paginación se convirtiera en el valor predeterminado de facto, la pila generalmente se iniciaba al final de la RAM y se producía un "desbordamiento de la pila" cuando comenzaba a sobrescribir la memoria de la aplicación. La protección de la memoria cambió mucho de esto, pero en general, mantiene la compatibilidad con versiones anteriores tanto como sea posible; tenga en cuenta que incluso la CPU x86-64 más moderna puede arrancar MS DOS 5 - o cómo Windows aún puede ejecutar muchas aplicaciones de DOS que no tienen idea de la paginación.