Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
мпс с 1 по 294.doc
Скачиваний:
13
Добавлен:
16.04.2019
Размер:
6.2 Mб
Скачать

2.7. Работа процессора в защищенном и реальном режимах

Процессоры семейства Р6, как и другие микропроцессоры 80x86, имеют два основных рабочих режима: защищенный и реальный.

Наиболее полно возможности процессора реализуются при работе в защищенном режиме. При этом обеспечивается физическая адресация памяти объемом до 2 32 = 4 Гбайт и доступ к виртуальной памяти объемом до 2 46 = 64 Гбайт. Помимо сегментации памяти в защищенном режиме может быть реализована страничная организация. Этот режим по­зволяет использовать дополнительные команды, введенные для поддержки многозадач­ных операционных систем. Кроме того, обеспечивается защита пользовательских программ друг от друга и от операционной системы, предотвращающая возможное взаимное вмеша­тельство в их работу.

При работе в реальном режиме возможности микропроцессора существенно ограничиваются: сокращается до 1 Мбайт объем адресуемой памяти, исключаются основ­ные механизмы защиты, не реализуется страничная организация памяти и многозадачное функционирование систем. Этот режим обычно используется либо как промежуточный для перехода в защищенный режим после инициализации микропроцессорной системы, либо для более быстрого выполнения программ, написанных для микропроцессоров 8086,80186. По сравнению с ними процессоры Р6 в реальном режиме имеют более широкий набор вы­полняемых команд и обеспечивают обработку 32-разрядных операндов.

Быстрое выполнение программ, написанных для микропроцессоров 8086, вместе с обес­печением защиты памяти, страничной организации и многозадачности достигается при работе процессора в режиме виртуального 8086, который является вариантом защищен­ного режима.

В настоящей главе подробно рассматривается функционирование процессоров Р6 в защи­щенном режиме (сегментация, страничная организация памяти, многозадачность), особеннос­ти реализации реального режима и режима виртуального 8086.

2.7.1. Сегментация памяти в защищенном режиме

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

Дескрипторы сегментов хранятся в памяти в виде массивов данных, которые сформированы в виде таблиц. Таблицы могут иметь размеры от 8 байт до 64 Кбайт, т. е. содержать до 8192 дескрипторов. Имеется три типа таблиц дескрипторов:

GDT - глобальная таблица дескрипторов; LDT-локальная таблица дескрипторов; ЮТ-таблица дескрипторов прерываний.

Таблица GDT содержит дескрипторы, которые могут использоваться системой при вы­полнении различных задач. Таблицы LDT содержат дескрипторы сегментов, используе­мых при решении данной задачи. Количество создаваемых таблиц LDT определяется операционной системой и зависит от числа выполняемых задач. Общее количество таб­лиц LDT может достигать 8192. В принципе, каждая задача может иметь отдельную LDT, которая включает дескрипторы сегментов, используемых при ее решении. В случае совме­стного использования сегментов таблицы LDT могут полностью или частично перекрывать друг друга. Таблица ЮТ обеспечивает выполнение процедур обслуживания исключений (прерываний), которые будут рассмотрены в гл. 8. В данной главе описывается адресация памяти в защищенном режиме, которая обеспечивается с помощью таблиц GDT и LDT.

Обращение к необходимому дескриптору в таблице осуществляется с помощью селек­тора, загружаемого в соответствующий сегментный регистр: OS, DS, SS, ES, FS или GS. Селектор представляет собой 16-разрядный указатель, который имеет три поля (рис. 2.39).

Поле RPL (биты 0-1) определяет уровень привилегий запроса (request privilege level). Это двухразрядный код, указывающий допустимый уровень защиты сегмента, который может быть выбран с помощью данного селектора.

Поле TI (бит 2) служит индикатором таблицы. Его значение указывает выбираемую таб­лицу: GDT при TI = О, LDT при TI = 1.

Поле INDEX (биты 3-15) служит индексом для выбора одного из 8192 дескрипторов, содержащихся в таблице.

Регистр LDTR (см. рис. 2.6) содержит 16-разрядный селектор, определяющий размещение в GDT дескриптора используемой таблицы LDT. Поле INDEX в этом указателе содержит смещение, которое используется для формирования адреса дескриптора табли­цы LDT, выбираемого из GDT. Дескриптор LDT содержит 32-разрядный базовый адрес ис­пользуемой LDT, ее 16-разрядную границу и атрибуты, определяющие права доступа к таб­лице. При загрузке в LDTR селектора таблицы LDT соответствующий дескриптор выбирается из GDT и хранится во внутреннем программно недоступном регистре процессора — «тене­вом» регистре LDTR (рис. 2.40).

Загрузка регистров GDTR, LDTR из памяти, а также сохранение в памяти их содержимого реализуется с помощью команд LGDT, LLDT и SGDT, SLDT. Загрузка селекторов в регистры сегментов данных DS, ES, FS, GS, SS производится командами LDS, LES, LFS, LGS, LSS. Регистр CS является программно недоступным, поэтому прямая загрузка в него (или выгрузка) селекторов для выбора сегментов программ невозможна. Начальное содержимое CS устанавливается при инициализации системы и затем изме­няется программно при выполнении команд межсегментных вызовов и переходов CALL, JUMP и при переключении задач.

Если селектор, загруженный в сегментный регистр CS, SS, DS, ES, FS или GS, обращается к таблице GDT (бит TI = 0) или LDT (бит TI -1), то его индекс, сдвинутый на три разряда влево

(т. е. умноженный на 8 - число байтов в дескрипторе), служит в качестве относительного адре­са (смещения) для формирования адреса дескриптора в данной таблице (рис. 2.40). Это смещение сравнивается с границей таблицы, хранящейся в GDTR или «теневом» регистре LDTR. Если смещение превышает границу, т. е. выходит за пределы таблицы GDT, то вырабатывается прерывание типа #GP («нарушение защиты»). Если нарушения границы нет, то смещение прибавляется к содержащемуся в GDTR базовому адресу, в результате чего образуется адрес младшего байта выбираемого дескриптора. При обращении к таб­лице LDT проверяются также права доступа к данной таблице, которые устанавливаются также, как для выбираемых сегментов.

Селектор с нулевым значением полей INDEX и TI (разряды 2-15, рис. 2.39) называется • нуль-индикатором. Он обеспечивает обращение к первому дескриптору в таблице GDT (нуль-дескриптор). Загрузка такого селектора в регистр CS или SS для выборки сегмента команд или стека вызывает исключение типа #GP («нарушение общей защиты»). Так как при иници­ализации системы обычно производится установка нулевых начальных значений дескрип­торов и селекторов, то данное исключение предотвращает возможность запуска рабочих программ до загрузки операционной системой необходимых сегментов и дескрипторов.

Таким образом, в защищенном режиме программно задается логический адрес ячеек памяти, хранящих команды или данные, который состоит из селектора и относительного адреса. С помощью селектора и таблиц GDT, LDT процессор производит выборку соответ­ствующего дескриптора. Затем формируется линейный адрес ячейки памяти путем сложе­ния базового адреса, содержащегося в дескрипторе, и относительного адреса, образуемого в соответствии с используемым способом адресации (рис. 2.41). Линейный адрес опреде­ляет местоположение ячейки в линейном адресном пространстве, которое может быть раз­бито на отдельные страницы при введении страничной организации памяти.

Если при работе процессора не используется страничная организация памяти (бит 32 в регистре управления CRO сброшен: PG = 0), то полученный линейный адрес является физическим адресом для выбора требуемой ячейки памяти.

При выполнении программ, написанных для процессоров 80386,80486, Pentium, P6, ба­зовый и относительный адреса содержат по 32 разряда. При работе в режиме виртуального 8086 в качестве базового адреса используется селектор, сдвинутый влево на 4 разряда. Таким образом, базовый адрес имеет 20 разрядов. В этом режиме используется 16-разряд­ный относительный адрес, а формируемый линейный адрес содержит 20 разрядов.

Иногда при работе микропроцессорной системы сегментации памяти не требуется. В этом случае необходимо загрузить все регистры сегментов селекторами дескрипторов, ' имеющих нулевые базовые адреса и задающие размеры сегментов по 4 Гбайт. В результате каждый из сегментов использует полное адресное пространство, т. е. сегментация подав­ляется. При этом может быть реализована страничная организация памяти.

В таблицах GOT, LDT могут размещаться следующие виды дескрипторов:

  • дескрипторы сегментов команд;

  • дескрипторы сегментов данных;

  • системные дескрипторы.

В общем, виде формат дескриптора представлен на рис. 2.42, где 32-разрядный базо­вый адрес сегмента (база ВА31-0) и 20-разрядная граница сегмента (L19-0) размещены по частям в различных байтах дескриптора.

Граница сегмента L указывает максимальное допустимое значение относительного адреса, которое может использоваться при обращении к сегменту. Величина (L+1) опреде­ляет размер сегмента в байтах или страницах. Обращение к ячейке памяти, находящейся за границей данного сегмента, вызывает исключение типа #GP.

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

Бит дробности G указывает, в каких единицах задан размер сегмента: в байтах при G = 0 или страницах объемом по 4 Кбайт при G = 1. Таким образом, сегмент может иметь размер до 220 = 1 Мбайт при G = 0 или до 232 = 4 Гбайта при G = 1.

Бит разрядности по умолчанию D/B для сегментов команд определяет разрядность формируемого относительного адреса и выбираемого операнда: 16 разрядов при D/B = О, 32 разряда при D/B = 1. Если производится обращение к сегменту стека (при выполнении команд типа PUSH, POP, CALL), то при D/B = 0 используется регистр SP и 16-разрядные, а при D/B= 1 -регистр ESP и 32-разрядные данные. Для расширяемых вниз сегментов дан­ных (сегменты со стековой адресацией) бит D/B определяет их верхнюю границу: М = FFFFh при D/B = 0 или М = FFFFFFFFh при D/B = 1. Для системных дескрипторов этот бит должен иметь нулевое значение.

Бит 5 в байте 6 всегда должен иметь нулевое значение, а бит 4 (AVL) может принимать значение, устанавливаемое пользователем или операционной системой.

Байт 5 дескриптора определяет права доступа к выбираемому сегменту. В зависимости от вида сегмента байт доступа имеет различные форматы (рис. 2.43), хотя назначение ряда полей (битов) остается одинаковым. Одинаковое назначение имеют следующие биты и поля.

Бит присутствия Р определяет наличие соответствующего сегмента в памяти. Если Р = 0 (сегмент отсутствует), то данный дескриптор не используется для формирования адресов, т. е. соответствующие байты дескриптора не загружаются в регистры, хранящие базовый адрес и размер сегмента. Поэтому содержимое этих байтов может быть уста­новлено произвольно. Если в регистр сегмента поступает селектор дескриптора, имею­щего Р = 0, то процессор переходит к обработке соответствующего исключения #NP («от­сутствие сегмента»).

Поле DPL (биты 6-5) указывает уровень защиты сегмента (уровень привилегий дескриптора). В зависимости от соотношения значений DPL и RPL, задаваемого в млад­ших битах селектора (см. рис. 2.39), разрешается или запрещается обращение к данному сегменту. Таким образом, обеспечивается требуемый уровень защиты сегмента.

Системный бит S определяет вид выбираемого сегмента. При 8=1 дескриптор обес­печивает обращение к сегментам программ (кодов) или данных (включая стек). Системные дескрипторы, имеющие значение 8 = 0, служат для обращения к таблицам LDT, сегментам состояния задачи TSS или шлюзам для входа в другие задачи или программы, включая программы обслуживания исключений и прерываний.

Форматы байта доступа для дескрипторов сегментов программ и данных (рис. 2.43, а, б) отличаются значениями бита 3, который имеет значение «1» для сегментов программ и «О» для сегментов данных.

Бит обращения А устанавливается в единицу при обращении к сегменту, т. е. при загрузке соответствующего селектора в сегментный регистр. Этот бит периодически проверяется операционной системой, реализующей виртуальную память, которая таким образом выяв­ляет невостребованные сегменты, имеющие А = 0. Сегменты, долгое время остающиеся невостребованными, выводятся из оперативной памяти на магнитный диск, освобождая место для других сегментов.

Назначение битов 1 и 2 байта доступа зависит от типа сегмента.

Бит разрешения считывания R вводится для сегмента программ и разрешает при R=1 производить считывание его содержимого. При R = 0 допускается только выборка содержимого этого сегмента для выполнения через регистр CS. Попытка считывания сегмента в этом слу­чае вызовет исключение типа #GP. Отметим, что прерывание этого типа возникает также при попытке записи в сегмент программ независимо от значения бита R. Таким образом, запись в сегмент программ запрещена. Если возникает необходимость внести изменение в этот сег­мент, то можно создать сегмент данных с разрешением записи (W = 1), занимающий то же адресное пространство, что и модифицируемый сегмент программ. После внесения измене­ний в созданный сегмент данных можно обратиться к нему как к сегменту программ, загрузив селектор этого сегмента в регистр CS.

Бит подчиненности С определяет дополнительные правила обращения, которые обес­печивают защиту сегментов программ: при С = 0 обращение к данному сегменту разреша­ется только программам, имеющим уровень привилегии CPL (значение поля RPL в регистре CS) такой же, как значение поля DPL в дескрипторе сегмента; при С = 1 допускается обращение к данному сегменту программ, имеющих CPL>=DPL :

Бит разрешения записи W вводится для сегментов данных. Разрешает (при W = 1) или запрещает (при W = 0) изменение содержимого этих сегментов. При W - 0 разрешается только считывание данных, а при попытке записи реализуется исключение типа #GP.

Бит направления расширения Е определяет размещение сегмента данных относительно заданной границы сегмента. При Е = 0 (расширение вверх) данные в сегменте размещаются от базового адреса ВА, задающего нижний предел сегмента до верхнего предела, определяемого суммой базового адреса и границы сегмента: (BA+L). Таким образом, сег­мент размещается вниз от границы - в направлении уменьшения адресов до базового.

При Е = 1 (расширение вниз) данные располагаются, начиная с адреса (BA+L+1), опреде­ляющего нижний предел сегмента. Остальные ячейки размещаются в направлении возрас­тания адресов (вниз от границы) до верхнего предела, задаваемого адресом (ВА+М). Верх­ний предел сегмента в этом случае равен базовому адресу, увеличенному на М = FFFFh (размер сегмента до 64 Кбайт) или на М = FFFFFFFFh (размер сегмента до 4 Гбайт) в зависи­мости от значения бита разрядности D/B в байте 6 дескриптора (см. рис. 2.42). Размер сег­мента будет равен (M-L), и его максимальное значение достигается, когда заданная граница L = 0. Отметим, что для сегментов с расширением вниз значения битов дробности и разряд­ности должны быть равными: G = D/B.

Таким образом, при расширении вверх (бит Е = 0) относительный адрес выбираемой ячейки должен быть меньше или равен границе сегмента, при расширении вниз (бит Е -1) относительный адрес должен быть больше границы сегмента.

Формат байта доступа для системных дескрипторов (S = 0) приведен на рис. 2.43, в. Поле TYPE определяет тип системного дескриптора в соответствии с табл. 2.58. Можно выделить три основных класса системных дескрипторов.

Таблица 2.58

Дескрипторы таблиц LD 7" обеспечивают обращение к локальной таблице дескрипторов для выбора сегментов, используемых при выполнении текущей программы.

Дескрипторы сегментов TSS используются при переключении задач в многозадач­ном режиме. При этом бит 3 поля TYPE байта доступа указывает, решается ли вызываемая задача с использованием 16- или 32-разрядных адресов и данных. Бит В в байте доступа сегмента TSS называется битом занятости и указывает, является ли вызываемый сегмент занятым (соответствующая задача находится в процессе выполнения) или доступным (за­дача еще не поступила на выполнение). Переключение на занятую задачу вызывает ис­ключение типа #GP («нарушение защиты»). Отметим, что дескрипторы LDT и TSS всегда должны иметь значение бита разрядности D/B = 0 (см. рис. 2.42).

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

Дескрипторы сегментов, использующих 16-разрядные адреса и операнды при размере сегментов до 1 Мбайт (значения битов G - D/B = 0), имеют нулевые значения байтов 5 и 6 дескриптора (см. рис. 2.42). Такие дескрипторы использовались в 16-разрядных микропро-цесорах 80286. Остальные биты и поля дескрипторов для процессоров 80286 полностью соответствуют форматам, приведенным на рис. 2.42, 2.43. Поэтому процессоры семей­ства Р6, как и более ранние модели, обеспечивают полную программную совместимость с 16-разрядным микропроцессором 80286, выполняя сегменты команд (программы), напи­санные для 80286, без какой-либо модификации. Отличие состоит только в разрядности базового адреса, которая для 80286 равна 24 битам (ВА23-0 в байтах 2,3,4 дескриптора), и границе сегмента, которая не должна превышать 64 Кбайт (L15-0 в байтах 0,1 дескрип­тора). Дробность и разрядность для этих сегментов устанавливается байтами G, D/B дескриптора, которые имеют нулевое значение.

Если системные дескрипторы имеют нулевые значения старших байтов 6,7 дескриптора (дескрипторы, аналогичные используемым для процессора 80286), то старший бит в поле TYPE байта доступа (см. рис. 2.43, в) всегда должен иметь нулевое значение. При этом до­пускается использование только тех типов системных дескрипторов, которые указаны в вось­ми верхних строках табл. 2.58.