Вы сказали, что вас интересует, почему:
В реальном режиме сегмент представляет собой «окно» физической памяти размером 64 КБ, и эти окна расположены на расстоянии 16 байт друг от друга. В защищенном режиме сегмент представляет собой окно для физической или виртуальной памяти, размер и местоположение которого определяется ОС, и у него есть много других свойств, в том числе какой уровень привилегий должен иметь процесс для доступа к нему.
С этого момента все, что я говорю, относится к защищенному режиму.
В памяти есть таблица, называемая таблицей глобальных дескрипторов (GDT), в которой хранится информация об этих размерах и расположении окон, а также о других свойствах. Также могут быть локальные таблицы дескрипторов для каждого процесса, и они работают аналогичным образом, поэтому я просто сосредоточусь на GDT.
Значение, которое вы загружаете в регистр сегмента, называется селектором . Это указатель на GDT или LDT с небольшим количеством дополнительной информации о безопасности. Естественно, если программа пытается загрузить дескриптор, который находится за пределами GDT, возникает исключение. Кроме того, если у процесса недостаточно прав для доступа к сегменту или что-то еще недопустимо, возникает исключение.
Когда возникает исключение, ядро обрабатывает его. Такое исключение, вероятно, будет классифицировано как ошибка сегментации. Таким образом, ОС убивает вашу программу.
Есть одно последнее предостережение: в наборе команд x86 нельзя загружать непосредственные значения в регистры сегментов. Вы должны использовать промежуточный регистр или операнд памяти или POP в регистр сегмента.
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
Я думаю, следует отметить, что архитектура допускает кучу сегментов. Но AFAIK, когда дело доходит до основных операционных систем x86, сегментные регистры служат лишь нескольким целям:
- Механизмы безопасности, такие как защита процессов пользовательского пространства от вреда друг другу или ОС
- Работа с многоядерными / многоядерными процессорами
- Локальное хранилище потоков: в качестве оптимизации некоторые операционные системы (включая Linux и Windows) используют регистры сегментов для локального хранилища потоков (TLS). Поскольку потоки используют одно и то же адресное пространство, потоку трудно «знать», где находится его область TLS, без использования системного вызова или траты регистров ... но поскольку регистры сегментов практически бесполезны, нет никакого вреда в «тратить» их ради быстрого TLS. Обратите внимание, что при настройке ОС может пропускать регистры сегментов и записывать непосредственно в регистры кэша дескрипторов, которые являются «скрытыми» регистрами, используемыми для кэширования поисков GDT / LDT, инициируемых ссылками на регистры сегментов, в этом случае, если вы попытаетесь читать из сегментных регистров вы не увидите.
Помимо сегмента на поток для TLS, на самом деле используется только несколько сегментов (умноженное на число процессоров) и только ОС. Прикладные программы могут полностью игнорировать регистры сегментов.
Это связано с дизайном ОС, а не с какими-либо техническими ограничениями. Могут быть встроенные операционные системы, которые требуют, чтобы программы пользовательского пространства работали с сегментными регистрами, хотя я не знаю ни одного.