Глава 7. Глобальная дескрипторная таблица.
Прежде, чем процессор перейдёт в защищённый режим, должна быть определена глобальная дескрипторная таблица GDT (Global Descriptor Table), так как все сегменты и прочие системные объекты должны быть описаны в дескрипторной таблице.
Глобальная дескрипторная таблица GDT - это область памяти, в которой находятся дескрипторы. Процессору всё равно, где именно вы расположили эту таблицу, но в любом случает она будет находится в первом мегабайте адресного пространства, потому что только из режима реальных адресов можно перевести процессор в защищённый режим. Также подразумевается, что сама таблица GDT будет выравнена на границу 8 байт, так как дескрипторы, из которых она состоит, имеют 8-байтный размер. Такое выравнивание позволит процессору максимально быстро обращаться к дескрипторам, что, естественно, увеличивает производительность.
Число дескрипторов, определённых в GDT, может быть любым, от 0 до 8192. Нулевой дескриптор, т.е. определённый в самом начале GDT, процессор не использует, обращение к такому дескриптору могло бы быть, когда поле Index селектора равно 0. Если всё же в программе встречается обращение к нулевому дескриптору, то процессор генерирует исключение и не позволит доступ к такому дескриптору. В связи с этим, везде в литературе рекомендуется использовать нулевой дескриптор как шаблон, на основе которого программа может создавать новые дескрипторы, но на практике их удобнее создавать иными способами, о которых мы ещё будем говорить.
GDT используется процессором всё время, пока он находится в защищённом режиме. Параметры GDT хранятся в специальном 48-разрядном регистре GDTR:
Рисунок 7-1. Формат регистра GDTR.
Формат регистра GDTR следующий:
биты: | |
0..15: | 16-разрядный предел GDT |
15..47: | 32-разрядный адрес начала GDT |
Адрес начала GDT - это тот адрес, по которому вы разместили GDT.
Предел таблицы GDT - это максимальное смещение относительно её начала.
Например, вы создаёте GDT, состоящую из 3-х дескрипторов - для сегментов кода, стека и данных. Общее число дескрипторов будет равно четырём, потому что первым по счёту будет идти нулевой дескриптор, а за ним уже остальные три:
Смещение от начала GDT | Назначение дескриптора |
0 | Нулевой |
8 | Сегмент кода |
16 | Сегмент стека |
24 | Сегмент данных |
Размер GDT в данном случае будет равен 32 байтам, следовательно, предельное смещение в таблице будет равно 31 - это и есть предел GDT.
Для загрузки значения в регистр GDTR используется команда LGDT. Операндом этой команды является 48-разрядное значение адреса в памяти, где размещается адрес и предел GDT. Вы также можете сохранить содержимое GDTR командой SGDT, указав в операнде адрес 48-разрядной переменной в памяти.
Далее приводится пример подготовки параметров GDT и их загрузки в регистр GDTR.
Пример 1. Подготовка параметров GDT и их загрузка в регистр GDTR. Алгоритм: 1. Вычисляем 32-разрядный адрес GDT 2. Вычисляем размер GDT 3. Сохраняем параметры GDT в 48-разрядную переменную 4. Загружаем значение в регистр GDTR Код: ; 1. Вычисляем 32-разрядный адрес GDT xor eax,eax ; EAX = 0; адрес будем вычислять в ; регистре EAX. mov ax,ds ; Подразумевается, что GDT находится в ; текущем сегменте данных. shl eax,4 ; EAX = адрес начала сегмента DS xor edx,edx ; EDX = 0. lea dx,GDT ; EDX = DX = смещение начала GDT ; относительно DS. add eax,edx ; EAX = полный физический адрес GDT ; в памяти. ; 2. Вычисляем размер GDT mov cx,4 ; CX = число дескрипторов + ; + нулевой дескриптор. shl cx,3 ; CX = CX * 8 - столько байт будут ; занимать в GDT эти дескрипторы. dec cx ; Предел меньше размера на 1 ; 3. Сохраняем параметры GDT в 48-разрядную переменную mov GDT_address,eax mov GDT_limit,cx ; 4. Загружаем значение в регистр GDTR lgdt GDT_params ;-------------------------------------------------------------------------- GDT_params label fword GDT_limit dw ? GDT_address dd ? GDT: dd ? ; 0-й дескриптор dd ? dd ? ; 1-й дескриптор (код) dd ? dd ? ; 2-й дескриптор (стек) dd ? dd ? ; 3-й дескриптор (данные) dd ?
Остаётся добавить, что размер GDT желательно не менять в процессе выполнения программ в защищённом режиме. Если ваша программа будет динамически создавать новые дескрипторы, то размер GDT лучше всего заранее задать достаточно большим, например, 64 Кб (максимальный размер). Однако, следует учитывать, что при обращении процессора к несуществующим дескрипторам, его поведение непредсказуемо, хотя оно, скорее всего, закончится зависанием.
Следующая глава | Оглавление | Вопросы? Замечания? Пишите: sasm@narod.ru |
Copyright © Александр Семенко. |