Dijiste que estabas interesado en saber por qué, así que:
En modo real, un segmento es una "ventana" a 64 K de memoria física y estas ventanas están espaciadas a 16 bytes de distancia. En el modo protegido, un segmento es una ventana a la memoria física o virtual, cuyo tamaño y ubicación viene determinado por el sistema operativo, y tiene muchas otras propiedades, incluido el nivel de privilegio que debe tener un proceso para acceder a él.
A partir de ahora, todo lo que digo se refiere al modo protegido.
Hay una tabla en la memoria llamada la tabla de descriptores globales (GDT), que es donde se guarda la información sobre estos tamaños de ventana y ubicaciones y otras propiedades. También puede haber tablas de descriptores locales por proceso, y funcionan de manera similar, así que solo me concentraré en el GDT.
El valor que carga en un registro de segmento se conoce como selector de segmento . Es un índice en el GDT o LDT, con un poco de información de seguridad adicional. Naturalmente, si un programa intenta cargar un descriptor que está fuera de los límites del GDT, se produce una excepción. Además, si el proceso no tiene suficiente privilegio para acceder al segmento o si algo más no es válido, se produce una excepción.
Cuando ocurre una excepción, el núcleo la maneja. Este tipo de excepción probablemente se clasifique como una falla de segmentación. Entonces el sistema operativo mata tu programa.
Hay una advertencia final: en el conjunto de instrucciones x86, no puede cargar valores inmediatos en registros de segmentos. Debe usar un registro intermedio o un operando de memoria o POP en el registro de segmento.
MOV DS, 160 ;INVALID - won't assemble
MOV AX, 160 ;VALID - assembles, but will probably result in an
MOV DS, AX ;exception, and thus the death of your program
Creo que debe señalarse que la arquitectura permite montones de segmentos. Pero yo sepa, cuando se trata de los sistemas operativos de la corriente principal x86, registros de segmentos sirven sólo unos pocos propósitos:
- Los mecanismos de seguridad, tales como el mantenimiento de los procesos del espacio de usuario de dañar a otra o el sistema operativo
- tratar con múltiples/procesadores multi-core
- Almacenamiento local de subprocesos: como optimización, algunos sistemas operativos (incluidos Linux y Windows) usan registros de segmento para almacenamiento local de subprocesos (TLS). Como los hilos comparten el mismo espacio de direcciones, es difícil que un hilo "sepa" dónde está su región TLS sin usar una llamada al sistema o desperdiciar un registro ... pero como los registros de segmentos son prácticamente inútiles, no hay daño en "desperdiciar" ellos por el bien de TLS rápido. Tenga en cuenta que al configurar esto, un SO puede omitir los registros de segmentos y escribir directamente en los registros de caché de descriptores, que son registros "ocultos" utilizados para almacenar en caché las búsquedas GDT/LDT activadas por referencias a los registros de segmentos, en cuyo caso si lo intenta para leer de los registros de segmentos, no lo verá.
Aparte de un segmento por subproceso para TLS, en realidad solo se utilizan unos pocos segmentos (multiplicado por el número de procesadores) y solo por el sistema operativo. Los programas de aplicación pueden completamente ignorar los registros de segmentos.
Esto se debe al diseño del sistema operativo, no a limitaciones técnicas. Puede haber sistemas operativos integrados que requieren programas de espacio de usuario para trabajar con los registros de segmentos, aunque no conozco ninguno.
¿Cuál es el error? – Blorgbeard
¿Bajo un sistema operativo o independiente? 16 modo protegido real o de 32 bits? ¿Qué código no compiló? Ejemplo mínimo de 16 bits con efectos observables: https://github.com/cirosantilli/x86-bare-metal-examples/blob/d4aae6183b98564819107b44a77641979c35d2c3/segment_registers.S –