Главная страница
Навигация по странице:

  • Рисунок 4-1. Структура дескриптора.

  • Адрес сегмента

  • Предел сегмента

  • Тип сегмента

  • Таблица 4-1. Тип сегмента

  • Рисунок 5-1. Формат селектора. Двухбитовое поле RPL

  • Понятие дескриптора, селектора. Рисунок 4 Структура дескриптора


    Скачать 35.51 Kb.
    НазваниеРисунок 4 Структура дескриптора
    АнкорПонятие дескриптора, селектора
    Дата26.02.2021
    Размер35.51 Kb.
    Формат файлаdocx
    Имя файлаПонятие дескриптора, селектора.docx
    ТипПрограмма
    #179928

    Дескриптор.

            Прежде чем программа сможет обратиться по какому-либо адресу памяти, она должна определить набор сегментов, через которые она сможет получить доступ к памяти.
           Сегмент определяется в виде структуры данных, которая называется дескриптор. Размер дескриптора - 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 (reserved)

    54: бит D (Default size)

    55: бит G (Granularity)

    56..63: адрес сегмента, биты 24..31

            Эта структура поясняется на рис. 4-1:


    Рисунок 4-1. Структура дескриптора.

            Как видите, значения предела и адреса сегмента "разбросаны" по всей структуре дескриптора. Это объясняется тем, что впервые защищённый режим появился в 16-разрядном процессоре 80286 и для совместимости с ним дескриптор не переделывали, а расширили дополнительными полями (биты с 49 по 63), благодаря чему программы, написанные для защищённого режима 286-го процессора работают и на 32-разрядных процессорах.
            Практически, в программах формат дескриптора удобнее использовать в следующем виде:

    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

    5: бит X

    6: бит D

    7: бит G

            Элементы дескриптора.

      

    Адрес сегмента - также называется базовым адресом, - 32-разрядный адрес области памяти, с которой начинается сегмент.

      

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

      

    Бит A (Acessed) - бит доступа в сегмент. Этот бит показывает, был ли произведен доступ к сегменту, описываемому этим дескриптором, или нет. Если процессор обращался к сегменту для чтения или записи данных или для выполнения кода, размещённых в нём, то бит A будет установлен (равен 1), иначе - сброшен (0).
        С помощью бита A операционная система может определить, использовался ли за последнее время этот сегмент или нет и предпринять какие-либо действия.
        Бит A процессором только устанавливается, сбрасывать его должна операционная система.
        При создании нового дескриптора подразумевается, что бит A будет равен 0 (т.е. обращений к этому сегменту ещё не было).

      

    Тип сегмента - трёхбитовое поле, определяющее тип сегмента (см. таблицу 4-1). Каждый бит типа сегмента имеет следующие значения:

     старший бит (3-й бит в байте прав доступа):

    если 0, то это сегмент данных, если 1 - то кода

     средний бит (2-й бит) - W (write-enable) бит разрешения записи:

    если 0, то запись запрещена, 1 - разрешена

     младший бит (1-й бит) - E (expansion-direction) направление расширения сегмента:

    если 0, то вверх (в сторону старших адресов) - как обычно,

    если 1, то вниз (в сторону младших адресов) - как в стеке.

            Для сегмента кода значения битов W и E интерпретируются несколько иначе (см. таблицу 4-1)

    Таблица 4-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

    Код

    Выполнение и считывание, согласованный

    Примечания:

    1.

    В защищённом режиме процессор запрещает запись в сегмент кода и, как видно из таблицы, не всегда разрешает даже простое считывание (хотя, запись в сегмент кода, конечно же, можно сделать, но не явно)

    2.

    Согласованный сегмент кода будет обсуждаться в следующих главах.

     Бит S (System) - определяет системный объект. Если этот бит установлен, то дескриптор определяет сегмент кода или данных, а если сброшен, то системный объект (например, сегмент состояния задачи, локальную дескрипторную таблицу, шлюз).

     Поле DPL (Descriptor Privilege Level) - Уровень привилегий, который имеет объект, описываемый данным дескриптором. Это двухбитовое поле, в него при создании дескриптора записывают значения от 0 до 3, определяющее уровень привилегий.
        Например, Если вам нужно, чтобы процессор выполнял программу на нулевом уровне привилегий, то в DPL дескриптора сегмента кода, где размещается программа, должно быть значение 00B.

     Бит P (Present) - Присутствие сегмента в памяти. Если этот бит установлен, то сегмент есть в памяти, если сброшен, то его нет. Этот бит применяется при реализации механизма виртуальной памяти - если программе понадобится память, то она сохранит содержимое какого-либо сегмента на диск и сбросит бит P. Если любая программа в дальнейшем обратится к этому сегменту, то процессор сгенерирует исключение неприсутствующего сегмента и запустит обработчик этой ситуации, который должен будет подгрузить содержимое сегмента с диска и установить бит P. После этого управление снова передаётся команде, обратившейся к этому сегменту (производится повторное выполнение команды, вызвавшей сбой) и работа программы будет продолжена. Бит P устанавливается и сбрасывается программами, сам процессор его только считывает.

     Бит U (User) - Бит пользователя. Этот бит процессор не использует и позволяет программе использовать его в своих целях.

     Бит X (rezerved) - Зарезервированный бит. Intel не рекомендует использовать этот бит, так как он может понадобится в более поздних моделях процессоров.

     Бит D (Default size) - Размер операндов по умолчанию. Если бит сброшен, по процессор использует объект, описываемый данным дескриптором, как 16-разрядный, если бит установлен - то как 32-разрядный. Если ваша программа имеет 32-разрядный код, то он должен размещаться в 32-разрядном сегменте кода (т.е. в дескрипторе такого сегмента бит D должен быть равен 1). В защищённом режиме допускается использование одновременно 16- и 32-разрядных сегментов, но при написании новых программ подразумевается, что все сегменты будут 32-разрядные. Подробнее об этом см. в главе "Смешивание 16- и 32-разрядного кода".

     Бит G (Granularity) - Гранулярность сегмента, т.е. единицы измерения его размера. Если бит G=0, то сегмент имеет байтную гранулярность, иначе - страничную (одна страница - это 4Кб).
        Например, сегмент, имеющий предел, равный 2, при G=0 будет иметь размер в три байта, а при G=1 - 12Кб (3 страницы)

            Создавать дескрипторы достаточно легко. Все биты и битовые поля находятся в байте прав доступа access_rights (P, DPL, S, Тип, A ) и в старших четырёх разрядах байта limit_hi_and_flags (G, D, X, U). Дескрипторы по типу отличаются значениями байта прав доступа, по свойствам - битами G и D, остальное - значения базового адреса и предела.

    Селектор.

            При адресации памяти в защищённом режиме команды ссылаются на сегменты, указывая не их адреса (как в режиме реальных адресов), а описания сегментов (их дескрипторы). Указатель на описание сегмента называется селектор. Другими словами, селектор - это номер дескриптора из таблицы дескрипторов.
            Адресация производится через пару регистров сегмент:смещение, причём, в качестве сегментного регистра используются обычные CS, SS, DS, ES, FS и GS (последние два появились в 386-м процессоре), но в них указывается не адрес сегмента, а селектор дескриптора.
            Селекторы нужны, по крайней мере, по трём причинам:

    1.

    Описание сегмента занимает 8 байт и использовать 8-байтные сегментные регистры было бы крайне неэффективно.

    2.

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

    3.

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

            Адрес памяти можно указывать не только через пару регистров, но и в переменных, через пару значений селектор:смещение.

            Можно было бы определить селектор просто, как номер сегмента, но в защищённом режиме кроме сегментов, дескриптор может определять целый ряд других системных объектов (например, задач), поэтому лучше не упрощайте понятия селектора и дескриптора, а постарайтесь привыкнуть к этой терминологии.

            Селектор имеет следующий формат:


    Рисунок 5-1. Формат селектора.

    • Двухбитовое поле RPL (Requested Privilege Level) содержит номер уровня привилегий, которое имеет текущая программа. Значение этого поля процессор использует для защиты по привилегиям. К одному и тому же дескриптору можно обращаться, используя селекторы с разными значениями RPL, но процессор позволит доступ только при определённых условиях (подробнее об этом см. в главе "Защита по привилегиям").

    • Бит TI (Table Indicator) определяет таблицу, из которой выбирается нужный дескриптор. Если бит TI = 0, то обращение производится к глобальной дескрипторной таблице GDT (она одна на всю систему), если TI = 1 - то к текущей локальной дескрипторной таблице LDT (таких может быть много).
          Подробнее дескрипторные таблицы обсуждаются в соответствующих главах.

    • Index - это собственной номер дескриптора, от 0 до 8191. Т.к. поле индекса состоит из 13 бит, то максимальное число дескрипторов, одновременно существующих в системе равно 2 13, т.е. 8192. Как видите, это довольно-таки много и вполне удовлетворяет любым системным запросам. На самом деле, число дескрипторов можно значительно увеличить за счёт использования множества дополнительных локальных дескрипторных таблиц.

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

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


    написать администратору сайта