§ Дескриптор
Прежде чем программа сможет обратиться по какому-либо адресу памяти, она должна определить набор сегментов, через которые она сможет получить доступ к памяти.Сегмент определяется в виде структуры данных, которая называется дескриптор. Размер дескриптора – 8 байт, все дескрипторы хранятся последовательно в специально отведённой области памяти – глобальной дескрипторной таблице.
Далее приведен формат дескриптора:
Биты Описание 0..15 Предел, биты 0..15 16..31 Адрес сегмента, биты 0..15 32..39 Адрес сегмента, биты 16..23 40 Бит A (Accessed) 41..43 Тип сегмента 44 Бит S (System) 45,46 DPL (Descriptor Privilege Level) 47 Бит P (Present) 48..51 Предел, биты 16..19 52 Бит U (User) 53 Бит X (64-bit) 54 Бит D (Default size) 55 Бит G (Granularity) 56..63 Адрес сегмента, биты 24..31Эта структура поясняется так:
63 ... 56 | 55 | 54 | 53 | 52 | 51 .. 48 | 47 | 46 45 | 44 | 43 ... 41 | 40 | 39 ... 16 | 15 ... 0 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
Адрес биты 31-24 | G | D | X | U | Предел биты 19-16 | P | DPL | S | Тип | A | Адрес биты 23-0 | Предел биты 15-0 |
Практически, в программах формат дескриптора удобнее использовать в следующем виде:
descriptor: dw limit_low ; младшее слово предела dw address_low ; младшее слово адреса db address_hi ; 3-й (из четырёх) байт адреса db access_rights ; права доступа db limit_hi_and_flags ; старшая часть предела и флаги GDXU db address_hi ; 4-й байт адресаБайт прав доступа имеет следующий формат:
Биты Описание 0 Бит A (Accessed) 1..3 Тип сегмента 4 Бит S (System) 5,6 Поле DPL 7 Бит P (Present)Байт старшей части предела и флагов GDXU имеет формат:
Биты Описание 0..3 Старшая часть предела (биты 16..19) 4 Бит U (User) 5 Бит X (64-bit) 6 Бит D (Default Size) 7 Бит G (Granularity)
Элементы дескриптора
- Адрес сегмента – также называется базовым адресом, – 32-разрядный адрес области памяти, с которой начинается сегмент.
- Предел сегмента – предельное значение смещения в сегменте; также можно рассматривать предел как размер сегмента минус один элемент размера – байт или страницу, смотря в чём измеряется сегмент.
- Бит A (Acessed) – бит доступа в сегмент. Этот бит показывает, был ли произведен доступ к сегменту, описываемому этим дескриптором, или нет. Если процессор обращался к сегменту для чтения или записи данных или для выполнения кода, размещённых в нём, то бит A будет установлен (равен 1), иначе – сброшен (0).
Бит A процессором только устанавливается, сбрасывать его должна операционная система.
При создании нового дескриптора подразумевается, что бит A будет равен 0 (т.е. обращений к этому сегменту ещё не было).
- Тип сегмента – трёхбитовое поле, определяющее тип сегмента (см. таблицу 4-1). Каждый бит типа сегмента имеет следующие значения:
- старший бит (3-й бит в байте прав доступа): если 0, то это сегмент данных, если 1 – то кода
- средний бит (2-й бит) – W (write-enable) бит разрешения записи: если 0, то запись запрещена, 1 – разрешена
- младший бит (1-й бит) – E (expansion-direction) направление расширения сегмента:
- если 0, то вверх (в сторону старших адресов) – как обычно,
- если 1, то вниз (в сторону младших адресов) – как в стеке.
Бит # | 11 | 10 | 9 | Тип | |
Название | E | W | |||
0 | 0 | 0 | Данные | Только чтение | |
0 | 0 | 1 | Данные | Чтение и запись | |
0 | 1 | 0 | Данные | Только чтение, расширяется вниз | |
0 | 1 | 1 | Данные | Чтение и запись, расширяется вниз | |
1 | 0 | 0 | Код | Только выполнение | |
1 | 0 | 1 | Код | Только выполнение | |
1 | 1 | 0 | Код | Только выполнение, согласованный | |
1 | 1 | 1 | Код | Выполнение и считывание, согласованный |
- В защищённом режиме процессор запрещает запись в сегмент кода и, как видно из таблицы, не всегда разрешает даже простое считывание (хотя, запись в сегмент кода, конечно же, можно сделать, но не явно)
- Согласованный сегмент кода означает, что его можно передавать исполнение из сегмента с меньшим уровнем привилегии.
- Бит S (System) – определяет системный объект. Если этот бит установлен, то дескриптор определяет сегмент кода или данных, а если сброшен, то системный объект (например, сегмент состояния задачи, локальную дескрипторную таблицу, шлюз).
- Поле DPL (Descriptor Privilege Level) – Уровень привилегий, который имеет объект, описываемый данным дескриптором. Это двухбитовое поле, в него при создании дескриптора записывают значения от 0 до 3, определяющее уровень привилегий.
- Бит P (Present) – Присутствие сегмента в памяти. Если этот бит установлен, то сегмент есть в памяти, если сброшен, то его нет. Этот бит применяется при реализации механизма виртуальной памяти – если программе понадобится память, то она сохранит содержимое какого-либо сегмента на диск и сбросит бит P. Если любая программа в дальнейшем обратится к этому сегменту, то процессор сгенерирует исключение неприсутствующего сегмента и запустит обработчик этой ситуации, который должен будет подгрузить содержимое сегмента с диска и установить бит P. После этого управление снова передаётся команде, обратившейся к этому сегменту (производится повторное выполнение команды, вызвавшей сбой) и работа программы будет продолжена. Бит P устанавливается и сбрасывается программами, сам процессор его только считывает.
- Бит U (User) – Бит пользователя. Этот бит процессор не использует и позволяет программе использовать его в своих целях.
- Бит X (64-bit) – Определяет 64-х битный тип сегмента
- Бит D (Default size) – Размер операндов по умолчанию. Если бит сброшен, по процессор использует объект, описываемый данным дескриптором, как 16-разрядный, если бит установлен – то как 32-разрядный. Если ваша программа имеет 32-разрядный код, то он должен размещаться в 32-разрядном сегменте кода (т.е. в дескрипторе такого сегмента бит D должен быть равен 1). В защищённом режиме допускается использование одновременно 16- и 32-разрядных сегментов, но при написании новых программ подразумевается, что все сегменты будут 32-разрядные. Подробнее об этом см. в главе "Смешивание 16- и 32-разрядного кода".
- Бит G (Granularity) – Гранулярность сегмента, т.е. единицы измерения его размера. Если бит G=0, то сегмент имеет байтную гранулярность, иначе – страничную (одна страница – это 4Кб).
Создавать дескрипторы достаточно легко. Все биты и битовые поля находятся в байте прав доступа access_rights (P, DPL, S, Тип, A ) и в старших четырёх разрядах байта limit_hi_and_flags (G, D, X, U). Дескрипторы по типу отличаются значениями байта прав доступа, по свойствам – битами G и D, остальное – значения базового адреса и предела. Когда мы будем рассматривать пример перехода в защищённый режим, вы увидите один из вариантов конструирования дескрипторов.