Процессор Intel в защищенном режиме #3 — Архив WASM.RU

Все статьи

Процессор Intel в защищенном режиме #3 — Архив WASM.RU

Рассылка постепенно набирает обороты! Я по прежнему жду не дождусь писем с вопросами… Вариантов здесь может быть только два: или вам все сходу понятно, или вообще ничего не понятно… Второй вариант как то не особо впечатляет на дальнейшее продолжение. Хотя, пока слишком мало материала, и спрашивать, по сути, не о чем.

Таблица дескрипторов

Итак, к чему мы пришли: оказывается, сегменты не раскиданы по памяти как попало и непонятно где, теперь мы с уверенностью можем сказать где какой из сегментов начинается, где заканчивается, что это за сегмент (код, данные или стек), вся эта информация хранится в ДЕСКРИПТОРЕ. Казалось бы, чего нам не хватает для полного счастья? Все же вроде ясно и понятно и не о чем здесь больше говорить! Однако, есть еще кое что… Один вопрос, который уже должен был загореться в твоем подсознании… ГДЕ ЖЕ НАХОДИТСЯ САМ ДЕСКРИПТОР ???!!! :)

Находиться он может в трех местах:

  • Глобальная таблица дескрипторов (GDT - Global Descriptor Table)
  • Локальная таблица дескрипторов (LDT - Local Descriptor Table)
  • Таблица дескрипторов прерываний (IDT – Interrupt Descriptor Table)

Эти таблицы находятся в оперативной памяти (там же, где и собственно сами программы), а не в процессоре, жестком диске или куда еще могут завести тебя фантазии… Поэтому, очевидно, что строить ТАБЛИЦЫ ДЕСКРИПТОРОВ придется «руками», нам самим. И вообще, с этого момента пора привыкать – в защищенном режиме ВСЕ НУЖНО СТРОИТЬ САМОМУ. В этом и заключается сила! :)

Несколько слов по поводу первых двух таблиц (на третьей (IDT) мы остановимся в главе посвященной прерываниям в защищенном режиме).

Глобальная таблица дескрипторов (GDT):

ЗАПОМНИ: КАЖДАЯ ОС ДОЛЖНА ИМЕТЬ ОДНУ ТАБЛИЦУ GDT!!! Без нее – никуда! Ей (таблицей) могут пользоваться ВСЕ (!) программы и задачи системы. Что значит «пользоваться таблицей дескрипторов»? Это значит, хранить в ней СВОЙ дескриптор.

Таблица GDT – сама по себе НЕ СЕГМЕНТ! Это структура данных в линейном адресном пространстве (в памяти). НАЧАЛО таблицы GDT храниться В РЕГИСТРЕ GDTR! Регистр GDTR – это самый обыкновенный регистр, такой же обыкновенный, как EAX, EIP, ES, только вот его функция заключается не в хранении каких-то промежуточных данных, а в хранении фиксированного числа – НАЧАЛА ТАБЛИЦЫ GDT. Называние регистра GDTR запомнить очень легко: GDT – это таблица, R – регистр. Не правда ли, пока все просто? )

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

GDTR:

32-битный линейный базовый адрес|16-битный лимит таблицы

Вот он, регистр GDTR. Весит 48 бит. Как видишь, он содержит не только адрес начала таблицы GDT в памяти, а еще и ее лимит. Лимит таблицы – 16-битное значение, показывает величину таблицы в байтах + 1. (т.е. все как и в случае с лимитом сегмента: если лимит таблицы в GDTR равен 0, то на самом деле это означает что реально (в памяти) лимит равен одному байту).

Как ты уже знаешь, сегментный дескриптор ВСЕГДА занимает 8 байт (2 двойных слова). Если уже забыл – посмотри на картинку из 2 выпуска. Следовательно, лимит таблицы дескрипторов – величина, равная 8N-1 байт. Но и N – тоже не резиновая величина. Скоро узнаешь каков предел этого самого N (т.е. сколько всего дескрипторов может содержать таблица)

Первый дескриптор в GDT не используется и называется «нулевой дескриптор» (null descriptor). При обращении к памяти через этот дескриптор возникает уже знакомая нам «рука правосудия» с #GP, и все опять вынуждены пасть ниц :)

Поэтому первый дескриптор в GDT – РУКАМИ НЕ ТРОГАТЬ!

Загрузить/считать значение регистра GDTR можно командами LGDT/SGDT. По умолчанию (т.е. после нажатия на кнопку Reset или включения компа) база GDT равна нулю, а лимит – FFFFh, т.е. фактически по умолчанию выделено максимум места, под FFFFh/8 = 8191 дескрипторов (ну минус один, учитывая null descriptor).

Локальная таблица дескрипторов (LDT):

В отличии от GDT совершенно не ОБЯЗАНА присутствовать вообще. И в то же самое время, ПО ЖЕЛАНИЮ, их можно развести великое множество (GDT ДОЛЖНА БЫТЬ только одна). Каждая задача может иметь свою собственную LDT, в то же время несколько задач могут использовать одну LDT на всех.

LDT – это СЕГМНЕТ! (GDT – структура данных). Это принципиально! И вот почему: т.к. LDT – это сегмент, то значит у нее тоже есть свой дескриптор! И где бы вы думали? Да все в той же GDT!!! Да да, звучит несколько странновато – у таблицы дескрипторов есть свой дескриптор!! Но, то ли еще будет! :)

Так же, как и у GDT у LDT тоже есть свой регистр – LDTR. В отличии от GDTR этот регистр, помимо инфы про базу и лимит LDT, содержит еще одно поле – сегментный селектор. Пока что не вникай, просто запомни слово – СЕЛЕКТОР.

LDTR:

Сегм. Селектор (16 бит)
32-битный линейный базовый адрес
16-битный лимит сегмента

Инструкции LLDT и SLDT позволяют писать/читать регистр LDTR. Точно так же, при reset-е значение базы в LDTR падает в ноль, а лимит – в FFFFh.

Ну и напоследок - ВНИМАНИЕ! КОНКУРС!!! )

Перед тобой пример структуры, которая являет собой таблицу GDT (вместо ИКС-ов значения, которые мы еще не рассматривали, поэтому не смотри на них); Тебе предстоит найти РЕАЛЬНЫЕ ЗНАЧЕНИЯ базы и лимита для каждого из описуемых семи сегментов (именно линейные адреса в памяти). Для одного из них дана подсказка в комментарии. Победителей ожидают ценные призы, а того, кто первым пришлет ответ – КВАРТИРА В МОСКВЕ! Поторопитесь!!!

Чтобы было проще – открой картинку с дескриптором и смотри одним глазом на нее, другим - на значения. Да, и помни: смотреть картинку нужно «задом-наперед» (т.е. сначала младшие байты, потом старшие):

GDT:
; нулевой дескриптор (ОБЯЗАТЕЛЬНО ДОЛЖЕН ПРИСУТСВОВАТЬ, НО РУКАМИ НЕ ТРОГАТЬ!)
0.                      db    8 dup (0)

; Сегмент с  базой в 0 и лимитом в 1235h (не забывай про +1 к лимиту!)
; Линейный адрес базы = 0, линейный адрес лимита = 0 + 1235h = 1235h
1. Descr_code           db    34h,12h,00h,00h,00h,XXh,0X000000b,00h

2. Descr_data           db    0C8h,0Dh,36h,12h,00h,XXh,0X100000b,00h
3. Descr_stack          db    0FFh,00h,00h,20h,00h,XXh,1X000000b,00h
4. Descr_code2          db    0DEh,0BCh,01h,20h,10h,XXh,0X001010b,00h
5. Descr_data2          db    00h,00h,00h,00h,00h,XXh,0X000000b,10h
6. Descr_stack2         db    01h,00h,10h,00h,00h,XXh,0X000001b,10h
7. Descr_LDT            db    04h,00h,00h,00h,00h,XXh,1X000000b,20h

GDT_limit                =    $-GDT

GDTR                    dw    GDT_limit-1
                        dd    ?

Дополнительные задания:

1. Найди ошибку! Один из дескрипторов содержит ОШИБКУ!
2. Покажи, как правильно нужно загрузить регистр GDTR.

Ответы присылать сюда: brokensword@ukr.net в таком виде

1. Линейный адрес базы = 0
Линейный адрес лимита = 1235h
2. . . .

Слово «линейный адрес» можешь опустить :)

Ариведерчи

2002-2013 (c) wasm.ru