Управление памятью в микропроцессорах семейства Х86, страница 7

Обобщая все сказанное выше, можно следующим образом сформулировать алгоритм формирования линейного (физического) адреса в защищенном режиме работы процессоров семейства i80х86.

1.  Взять селектор из сегментного регистра.

2.  Если бит TI показывает на GDT (TI = 0), взять из GDTR адрес дескрипторной таблицы и перейти к шагу 4.

3.  Если бит TI показывает на LDT (TI  = 1), то:

а) взять селектор сегмента LDT из регистра LDTR;

б) выделить в селекторе поле индекса (старшие 13 разрядов) и умножить индекс на 8 (сдвинуть на 3 разряда влево);

в) прибавить результат к базовому адресу из регистра     GDTR;

г) считать из памяти адресуемый дескриптор;

д) выделить из этого дескриптора базовый адрес сегмента,

    содержащего таблицу LDT. Полученный базовый адрес является

    адресом дескрипторной таблицы  LDT. Перейти к шагу 4.

           4.  Выделить в селекторе сегментного регистра поле индекса (старшие 13

                разрядов), умножить на 8 содержащийся в нем код,  и прибавить к

                базовому адресу соответствующей дескрипторной таблицы. Считать

                из памяти дескриптор по этому адресу.

           5.Выделить из дескриптора базовый адрес искомого сегмента.

           6. Прибавить значение смещения в сегменте (из инструкции) к

               базовому адресу искомого сегмента. Это и будет требуемый  линейный

               адрес. Он же является и физическим адресом, если не включено

               страничное преобразование.

            7. Осуществить обращение к памяти по полученному адресу.

Рассматривая алгоритм формирования линейного адреса по его виртуальному адресу (селектор:смещение) в защищенном режиме работы видим, что обращение к байту в памяти дополнительно требует (в наихудшем случае, при использовании LDT) обращений к двум 8 байтовым дескрипторам в памяти (в GDT и LDT) и выполнении двух 32 битных сложений. Сначала при получении адреса LDT данной задачи в GDT, путем сложения 32 битного адреса начала GDT (базы GDT, полученной из GDTR) и 32 битного значения базы из дескриптора LDT, определенного по селектору, взятому из регистра LDTR. Затем, при получении окончательного линейного адреса искомого байта, путем сложения 32 битного адреса начала соответствующего сегмента (базы сегмента) и 32 битного эффективного адреса. При этом заметим, что операции сдвига при умножении на 8 и выделения баз из дескрипторов не расходуют заметного времени, благодаря специальной «маршрутизации проводников» на кристалле МП, т.е. осуществлении этих операций аппаратным способом, при помощи комбинационных схем. (Вспомним, что в реальном режиме, эмулирующем МП 8086, при формировании физического адреса, достаточно было только одного 20 битового сложения (базы сегмента с эффективным адресом) без какого либо дополнительного обращения к памяти).

Для ускорения формирования линейного адреса при защищенном режиме работы, пользуются тем обстоятельством, что обращение к памяти производится гораздо чаще, чем изменение содержимого сегментных регистров и переключения задач. Поэтому целесообразно ускорить обращение к памяти за счет замедления загрузки сегментных регистров и переключения задач. Такой компромисс достигается путем ассоциирования с регистрами LDTR, TR и каждым сегментным регистром (CS, DS, SS, ES, FS, GS) так называемых теневых (Shadow) регистров, которые невидимы для пользовательских программ и даже программ операционной системы. Они автоматически модифицируются и невидимо используются схемами процессора

. На рисунке III.13 приведены все регистры преобразования адреса и их теневые регистры. Иногда теневые регистры называют кэш-регистрами, а сам этот прием – кэшированием (caching) дескрипторов, поскольку теневые регистры организованы как регистровая кэш-память.

Таким образом, если адресация не выходит из рамок текущего сегмента, то полный цикл формирования дальнейших адресов в программе осуществляется без обращения к ОЗУ. Когда программа загружает селектор в сегментный регистр, процессор автоматически считывает (кэширует) нужный дескриптор в соответствующий теневой регистр. Поскольку дескриптор теперь находится внутри процессора, для получения линейного адреса памяти потребуется только сформировать эффективный адрес и просуммировать его с базовым адресом сегмента из нужного теневого регистра.

Поэтому, если программа редко модифицирует свои сегментные регистры, то в защищенном режиме работы процессора она будет выполняться примерно с такой же скоростью, как и в реальном.

Заметим следующее. Случай, когда селектор имеет нулевое поле индекса и TI = 0, в принципе допустим, но первый элемент таблицы GDT зарезервирован процессором и должен содержать нули. Такой селектор называется «пустым селектором» (null selector) или нуль-селектором, а соответствующий дескриптор – пустым дескриптором.

          Рис.III.13. Теневые регистры дескрипторов.

Следовательно, пустые селекторы 0000h…0003h не описывают никаких полезных сегментов. Пустой селектор разрешается загружать в сегментный регистр (кроме CS и SS), но любая попытка использовать его в формировании адреса вызывает прерывание (особый случай). Одно из возможных применений пустых селекторов заключается в следующем. Перед инициированием задачи ОС может загрузить в регистры DS и ES  пустые селекторы. Если в последующем не инициализировать эти регистры правильными селекторами, то адресация памяти через них вызовет особый случай.

Регистр LDTR хранит селектор сегмента, содержащего текущую LDT. Этот селектор должен индексировать дескриптор текущей LDT в таблице GDT. Во время переключения задач процессор изменяет все локальное адресное пространство простой перезагрузкой регистра LDTR. Вот почему переключение задач реализуется очень быстро. Использование в регистре LDTR селектора, а не физического адреса (как в регистре GDTR) позволяет обменивать локальные дескрипторные таблицы с внешней памятью теми же самыми механизмами виртуальной памяти, которые применяются для всех сегментов.