Goto... Search.. Hext Change.. Follou Previous 12 глава




Как уже отмечалось, адрес, вычисляемый процессором на основе се­лектора и смещения, относится к линейном)' адресному' пространству, не обязательно совпадающему с физическим. Преобразование линейных ад­ресов в физические осущсстатяется с помощью так называемой странич­ной трансляции, частично реализуемой процессором, а частично — one-


усширенные возможности современных микропроцессоров



щионной системой. Если страничная трансляция выключена, все ли-£ейные адреса в точности совпадают с физическими; если страничная >ансляция включена, то линейные адреса преобразуются в физические в этветствии с содержимым страничных таблиц (рис. 4.5).

 

15 0 31 0 образование рипторов) 31 0 >бразоваиис 1 ранни) 31 0
Селектор; Смещение — > * * -> -> 8-2 с 3
Виртуальный адрес Сегментпо (таблицы Линейный адрес 2? = о IE & и Физический адрес *

Рис. 4.5. Цепочка преобразований виртуального адреса в физический.

Страницей называется связный участок линейного или физического адресного пространства объемом 4 Кбайт. Программа работает в линей­ном адресном пространстве, не подозревая о существовании страничного преобразования или даже самих страниц. Механизм страничной трансля­ции отображает логические страницы на физические в соответствии с информацией, содержащейся в страничных таблицах. В результате отдель­ные 4х-килобайтовые участки программы могут реально находиться в любых несвязных друг с другом 4х-килобайтовых областях физической памяти (рис. 4.6). Порядок размещения физических страниц в памяти мо­жет не соответствовать (и обычно не соответствует) порядку следования логических страниц. Более того, некоторые логические страницы могут перекрываться, фактически сосуществуя в одной и той же области физи­ческой памяти.

Страничная трансляция представляет собой довольно сложный меха­низм, в котором принимают участие аппаратные средства процессора и находящиеся в памяти таблицы преобразования. Назначение и взаимо­действие элементов системы страничной трансляции схематически изоб­ражено на рис. 4.7.

Система страничных таблиц состоит из двух уровней. На первом уров­не находится каталог страниц — резидентная в памяти таблица, содержа­щая 1024 4х-байтовых поля с адресами таблиц страниц. На втором уровне находятся таблицы страниц, каждая из которых содержит так же 1024 4х-байтовых поля с адресами физических страниц памяти. Максимально воз­можное число таблиц страниц определяется числом полей в каталоге и может доходить до 1024. Поскольку размер страницы составляет 4 Кбайт, 1024 таблицы по 1024 страницы перекрывают все адресное пространство (4 Гбайт).



Глава 4



4 Кбайт

4 Кбайт

4 Кбайт

4 Кбайт

4 Кбайт

4 Кбайт

4 Кбайт

4 Кбайт


Линейное адресное пространство


Физическое адресное пространство


Рис. 4.6. Отображение логических адресов на физические.


 

Страничный кадр
Каталог страниц 1024 4х-байтовых полей

Линейный адрес

2221 12 Ц


Физический адрес

12 11

Смещение


Таблица страниц

CR3

Каждая таблица содержит 1024 4х-байтовых полей

Базовый адрес каталога

Рис. 4.7. Страничная трансляция адресов.


расширенные возможности современных микропроцессоров_____________________ 181

Не все 1024 таблицы страниц должны обязательно иметься в наличии (кстати, они заняли бы в памяти довольно много места — 4 Мбайт). Если программа реально использует лишь часть возможного линейного адрес­ного пространства, а так всегда и бывает, то неиспользуемые поля в ката­логе страниц помечаются, как отсутствующие. Для таких полей система, экономя память, не выделяет страничные таблицы.

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

Старшие 10 бит линейного адреса образуют номер поля в каталоге страниц. Базовый адрес каталога хранится в одном из управляющих реги­стров процессора, конкретно, в регистре CR3. Из-за того, что каталог сам представляет собой страницу и выровнен в памяти на границу 4 Кбайт, в регистре CR3 для адресации к каталогу используются лишь старшие 20 бит, а младшие 12 бит зарезервированы для будущих применений.

Поля каталога имеют размер 4 байт, поэтому индекс, извлеченный из линейного адреса, сдвигается влево на 2 бит (т.е. умножается на 4) и полу­ченная величина складывается с базовым адресом каталога, образуя адрес конкретного поля каталога. Каждое поле каталога содержит физический базовый адрес одной из таблиц страниц, причем, поскольку таблицы стра­ниц сами представляют собой страницы и выровнены в памяти на границу 4 Кбайт, в этом адресе значащими являются только старшие 20 бит.

Далее из линейного адреса извлекается средняя часть (биты 12...21), сдвигается влево на 2 бит и складывается с базовым адресом, хранящим­ся в выбранном поле каталога. В результате образуется физический адрес страницы в памяти, в котором опять же используются только старшие 20 бит. Этот адрес, рассматриваемый, как старшие 20 бит физического адре­са адресуемой ячейки, носит название страничного кадра. Страничный кадр дополняется с правой стороны младшими 12 битами линейного ад­реса, которые проходят через страничный механизм без изменения и иг­рают роль смещения внутри выбранной физической страницы.

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

mov EAX,DS:[EBX]

при этом содержимое DS (селектор) составляет 1167h, а содержимое ЕВХ (смещение) 31678h.

Старшие 13 бит селектора (число 116U) образуют индекс дескриптора в системной дескрипторной таблице. Каждый дескриптор включает в себя довольно большой объем информации о конкретном сегменте и, в част­ности, его линейный адрес. Пусть в ячейке дескрипторной таблицы с но­мером 116h записан линейный адрес (базовый адрес сегмента) 01051000h.



Глава -t


Тогда полный линейный адрес адресуемой ячейки определится, как сум­ма базового адреса и смещения:

Базовый адрес сегмента 01051000h
Смещение 00031678h

Полный линейный адрес 01082678h

При выключенной табличной трансляции величина 01082678U будет представлять собой абсолютный физический адрес ячейки, содержимое которой должно быть прочитано приведенной выше командой mov. Легко сообразить, что эта ячейка находится в самом начале 17-го мегабайта оперативной памяти.

Посмотрим, как будет образовываться физический адрес при использо­вании страничной трансляции адресов. Полученный линейный адрес надо разделить на три состаатяющис для выделения индексов и смещения (рис. 4.8)



22 21



О


| 0000000100 I 0010000010 | 01100111 1000 I

Индекс каталога Индекс таблицы Смещение

страниц Рис, 4.8. Пример линейного адреса.

Индекс каталога составляет 4h. Умножение его на 4 даст смещение от начала каталога. Это смещение равно 10h.

Индекс таблицы страниц оказался равным 82h. После умножения на 4 получаем смещение в таблице страниц, равное в данном случае 210h.

Предположим, что регистр CR3 содержит число 80001г. Тогда физичес­кий адрес ячейки в каталоге, откуда надо получить адрес закрепленной за данным участком программы таблицы страниц, составит SOOOh + 10h = 8010h. Пусть по этому адресу записано число 460211г. Его 12 младших битов составляют служебную информацию (в частности, бит 1 свидетельствует о присутствии этой таблицы страниц в памяти, а бит 5 говорит о том, что к этой таблице уже были обращения), а старшие биты, т.е. число 46000h образуют физический базовый адрес таблицы страниц. Для получения ад­реса требуемой ячейки этой таблицы к базовому адресу надо прибавить смещение 210U. Результирующий адрес составит 462101г.

Будем считать, что по адресу 46210h записано число 01FF5021h. От­бросив служебные биты, получим адрес физической страницы в памяти 01FF5000U. Этот адрес всегда оканчивается тремя нулями, так как страни­цы выровнены в памяти на границу' 4 Кбайт. Для получения физического адреса адресуемой ячейки следует заполнить 12 младших бит полученного адреса битами смещения из линейного адреса нашей ячейки, в которых в нашем примере записано число 678U. В итоге получаем физический адрес памяти 01FF5678h, расположенный в конце 32-го Мбайта.

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


расширенные возможности современных микропроцессоров



ким следствием правил адресации защищенного режима является уже упоминавшаяся «оторванность» прикладной программы от физической памяти. Программист, отлаживающий программу защищенного режима (например, приложение Windows), может легко заглянуть в сегментные регистры и определить селекторы, выделенные программе. Однако селек­торы абсолютно ничего не говорят о физических адресах, используемых программой. Физические адреса находятся в таблицах дескрипторов, а эти таблицы недоступны прикладной программе. Таким образом, програм­мист не знает, где в памяти находится его программа или используемые ею области данных.

С другой стороны, использование в процессе преобразования адресов защищенных системой таблиц имеет свои преимущества. Обычно много­задачная операционная система создает для каждой выполняемой задачи свой набор таблиц преобразования адресов. Это позволяет каждой из за­дач использовать весь диапазон виртуальных адресов, при этом, хотя для разных задач виртуальные адреса могут совпадать (и, как правило, по край­ней мере частично совпадают), однако сегментное и страничное преобра­зования обеспечивают выделение для каждой задачи несовпадающих об­ластей физической памяти, надежно изолируя виртуальные адресные про­странства задач друг от друга.

Вернемся теперь к таблицам дескрипторов и рассмотрим их более де-тально. Существует два типа дескрипторных таблиц: таблица глобальных дескрипторов (GDT от Global Descriptor Table) и таблицы локальных дескрипторов (LDT от Local Descriptor Table).Обычно для каждой из этих таблиц в памяти создаются отдельные сегменты, хотя в принципе это не обязательно. Таблица глобальных дескрипторов существует в единствен­ном экземпляре и обычно принадлежит операционной системе, а локаль­ных таблиц может быть много (это типично для многозадачного режима, в котором каждой задаче назначается своя локальная таблица).

Виртуальное адресное пространство делится на две равные половины. К одной половине обращение происходит через GDT, к другой половине через LDT. Как уже отмечалось, все виртуальное пространство состоит из 214 сегментов, из которых 213 сегментов адресуются через GDT, и еще 213 - чрез LDT.

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

Для программирования защищенного режима и даже для отладки при­кладных программ, работающих в защищенном режиме, полезно пред­ставлять себе структуру дескриптора и смысл его отдельных полей. Следу­ет заметить, что существует несколько типов дескрипторов, которым при­сущи разные форматы. Так, дескриптор сегмента памяти (наиболее распространенный тип дескриптора) отличается от дескриптора шлюза, используемого, в частности, для обслуживания прерываний. Рассмотрим формат дескриптора памяти (рис. 4.9).



Глава -f


 

 

Байты
      .6 5    
База 31...24 •\триб\ты 2' Атрибуты Г База сегмента 23...0 rP™mja сегмента i i i
Биты 765 /< 43210   Ч Биты 43210  
G D   А V L 1 1 1 Граница 19...16 i i i i Р DPL   Тип i i А

Рис. 4.9. Формат дескриптора памяти.

Как видно из рисунка, дескриптор занимает 8 байт. В байтах 2..,4 и 7 записывается линейный базовый адрес сегмента. Полная длина базового адреса — 32 бит. В байтах 0-1 записываются младшие 16 бит границы сег­мента, а в младшие четыре бита байта атрибутов 2 — оставшиеся биты 16...19. Границей сегмента называется номер его последнего байта. Мы видим, что граница описывается 20-ю битами, и ее численное значение не может превышать 1М. Однако, единицы, в которых задается граница, можно изменять, что осуществляется с помощью бита дробности G (бит 7 байта атрибутов 2). Если G=0, граница указывается в байтах; если 1 — в блоках по 4 Кбайт. Таким образом, размер сегмента можно задавать с точ­ностью до байта, но тогда он не может быть больше 1 Мбайт; если же установить G=l, то сегмент может достигать 4 Гбайт, однако его размер будет кратен 4 Кбайт. База сегмента и в том, и в другом случае задастся с точностью до байта.

Рассмотрим теперь атрибуты сегмента, которые занимают два байта дескриптора.

Бит A (Accessed, было обращение) устанавливается процессором в тот момент, когда в какой-либо сегмс!ггаый регистр загружается селектор данного сегмента. Далее процессор этот бит не сбрасывает, однако его может сбросить программа (разумеется, если она имеет доступ к содержи­мому дескриптора, что обычно является прерогативой операционной си­стемы). Анализируя биты обращения различных сегментов, программа может судить о том, было ли обращение к данному сегменту после того, как она сбросила бит А.

Тип сегмента занимает 3 бит (иногда бит А включают в поле типа, и тогда тип занимает 4 бит) и может иметь 8 значений. Тип определяет пра­вила доступа к сегменту. Так, если сегмент имеет тип 1, для него разреше­ны чтение и запись, что характерно для сегментов данных. Назначив сег­мент)' тип 0, мы разрешим только чтение этого сегмента, защитив его тем самым от любых модификаций. Тип 4 обозначает разрешение исполне­ния, что характерно для сегментов команд. Используются и другие типы сегментов.


Расширенные возможности современных микропроцессоров_____________________ 185

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

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

Бит 4 байта атрибутов 1 является идентификатором сегмента. Если он равен 1, как это показано на рис. 4.9, дескриптор описывает сегмент памя­ти. Значение этого бита 0 характеризует дескриптор системного сегмента.

Поле DPL (Descriptor Privilege Level, уровень привилегий дескрипто­ра) служит для защиты программ друг от друга. Уровень привилегий мо­жет принимать значения от 0 (максимальные привилегии) до 3 (мини-матьные). Программам операционной системы обычно назначается уро­вень 0, прикладным программам — уровень 3, в результате чего исключается возможность некорректным программам разрушить операционную систе­му. С другой стороны, если прикладная программа сама выполняет функ­ции операционной системы, переводя процессор в защищенный режим и работая далее в этом режиме, ее сегментам следует назначить наивысший (нулевой) уровень привилегий, что откроет ей доступ ко всем средствам защищенного режима.

Бит Р говорит о присутствии сегмента в памяти. В основном он ис-

|j пользуется для организации виртуальной памяти. С помощью этого бита

система может определить, находится ли требуемый сегмент в памяти, и

при необходимости загрузить его с диска. В процессе выгрузки ненужного

пока сегмента на диск бит Р в его дескрипторе сбрасывается.

Младшая половина байта атрибутов 2 занята старшими битами грани­цы сегмента. Бит AVL (от Available, доступный) не используется и не анализируется процессором и предназначен для использования приклад­ными программами.

Бит D (Default, умолчание) определяет действующий по умолчанию

размер для операндов и адресов. Он изменяет характеристики сегментов

двух типов: исполняемых и стека. Если бит D сегмента команд равен 0, в

^сегменте по умолчанию используются 16-битовые адреса и операнды, если

1 — 32-битовые.



Глава 4


 


Атрибут сегмента, действующий по умолчанию, можно изменить на противоположный с помощью префиксов замены размера операнда (66h) и замены размера адреса (67h). Таким образом, для сегмента с D=0 пре­фикс 66U перед некоторой командой заставляет ее рассматривать свои операнды, как 32-битовые, а для сегмента с D=l тот же префикс 66h, наоборот, сделает операнды 16-битовыми. В некоторых случаях транслятор сам включает в объектный модуль необходимые префиксы, в других слу­чаях их приходится вводить в программу «вручную».

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

Для того, чтобы наша программа могла бы хоть что-то сделать в защи­щенном режиме, для нее необходимо создать среду защищенного режи­ма, в первую очередь, таблицу глобальных дескрипторов с описанием всех сегментов, с которыми программа будет работать. Кроме нас никто эту таблицу (при работе в DOS) не создаст. Таким образом, наша про­грамма будет в какой-то мере выполнять функции операционной систе­мы защищенного режима.

Для практического исследования защищенного режима придется вы­полнить некоторую работу по персконфигурированию компьютера. В наше время компьютеры обычно конфигурируются так, что при их включении сразу загружается система Windows. Работы, для которых требуется DOS, выполняются либо в режиме эмуляции DOS, либо в сеансе DOS, органи­зуемом системой Windows. Для запуска прикладной программы защищен­ного режима такой способ не годится. Нам понадобится DOS в «чистом виде», без следов Windows. Более того, перед запуском программы необ­ходимо выгрузить все драйверы обслуживания расширенной памяти (HIMEM.SYS и EMM386.EXE) и программы, использующие расширен­ную память, например, SMARTDRV.EXE. Лучше всего загружать DOS с системной дискеты, подготовив файлы CONFIG.SYS и AUTOEXEC.BAT в минимальном варианте.

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

Пример 4-4. Программирование защищенного режима
.586Р разрешение трансляции всех команд МП 586

;Структура для описания дескрипторов сегментов

dcr struc limit dw base_ldw basc_m db attr Idb

;Имя структуры;Граница (биты 0...15);База, биты 0...15;База, биты 16...23;Байт атрибутов 1


уширенные возможности современных микропроцессоров



;Граница (биты 16...19) и атрибуты 2;База, биты 24...31

attr_2db О

baseji db О

dcr ends;

data segment use!6;

;Таблица глобальных деифипторов GOT

gdt_null dcr <0,0,0,0,0,0>;Селектор О -обязательный

;нулевой дескриптор

gdt_data dcr <data_size-l,0,0,92h,0,0>;Селектор 8,

;сегмент данных

gdt_code dcr <сос!е_817е-1,0,0,98п,0,0>;Селектор 16,

;сегмент команд

gdt_stack dcr <511,0,0,92h,0,0>;Селектор 24 —

;сегмент стека

gdt_screen dcr <4095,8000h,OBh,92h,0,0>;Селектор 32,

видеобуфер

pdescr df 0; Псевдодескриптор для команды Igdt

data_size=:S-gdt_iiull;Размер сегмента данных

data ends;Конец сегмента данных

text segment use!6;Сегмент команд, 16-разрядный режим

assume CS:text,DS:data;

main proc;

xor EAX,EAX;Очистим ЕАХ

mov AX,data;3агрузим в DS сегментный

mov DS,AX;адрес сегмента данных

;Вычислим 32-битовый линейный адрес сегмента данных

;и загрузим его в дескриптор сегмента данных в GDT.

;В регистре АХ уже находится сегментный адрес.

;Умножим его на 16 сдвигом влево на 4 бита

shl ЕАХ,4;В ЕАХ линейный базовый адрес

mov ЕВР,ЕАХ;Сохраним его в ЕВР для будущего

mov BX,offset gdt_data;B BX адрес дескриптора

mov [BX].base_I,AX;3агрузим младшую часть базы

rol ЕАХ,16;Обмен старшей и младшей половин ЕАХ

mov [BX].base_m,AL;3arpy3HM среднюю часть базы

;Вычислим 32-битовый линейный адрес сегмента команд

;и загрузим его в дескриптор сегмента команд в GDT
хог ЕАХ,ЕАХ;Очистим ЕАХ

mov AX,CS;Сегментный адрес сегмента команд

shl ЕАХ,4;В ЕАХ линейный базовый адрес

mov BX,offset gdt_code;В ВХ адрес дескриптора.
mov [BX].base_I,AX;3arpy3HM младшую часть базы
rol ЕАХ, 16;Обмен старшей и младшей половин ЕАХ

mov [BX].base_m,AL;3arpy3HM среднюю часть базы

;Вьгчислим 32-битовый линейный адрес сегмента стека
хог ЕАХ,ЕАХ;Все, как и для других

mov AX,SS дескрипторов

shl EAX,4



Глава -t


 


mov BX,offset gdt_stack

mov {BX].base_l,AX

rol ЕАХД6

mov [BX].base_m,AL
;Подготовим псевдодескриптор pdescr для загрузки регистра GDTR

mov dword ptr pdescr+2,EBP;База GOT

mov word ptr pdescr,39;ГраницаООТ

Igdt pdescr;3агрузим регистр GDTR

cli;3апрет прерываний

; Переходим в защищенный режим

mov EAX,CRO;Получим содержимое CRO

or EAX,1;Установим бит защищенного режима

mov CRO,EAX;3апишем назад в CRO


; Теперь процессор работает в защищенном режиме;
?,

;3агружаем в CS:IP селектор смещение точки continue

db OEAh;Код команды far jmp

dw offset continue;Смещение

dw 16;Селектор сегмента команд

continue:;Делаем адресуемыми данные

mov АХ,8;Селектор сегмента данных

mov DS,AX;3агрузим в DS

;Делаем адресуемым стек

mov mov
АХ,24 SS,AX

;Селектор сегмента стека;3агрузим в SS

Инициализируем ES и вьшодим символ

mov AX,32;Селектор сегмента видеобуфера

mov ES,AX;3агрузим в ES

mov BX,2000;Начальное смещение на экране

mov AX,09FOFh;Символ с атрибутом mov ES:[BX],AX;Вывод в видеобуфер;Вернемся в реальный режим

; Установим;значение границы;для реатъного;режима ;3агрузим теневой регистр ;сегмента данных

mov gdt_data.limit,OFFFFh mov gdt_code.limit,OFFFFh

mov mov mov mov mov mov mov mov

gdt_stack.limit,OFFFFh

gdt_screen. limit, OFFFFh

AX, 8

DS,AX

;То же для ; стека ;То же ;для регистра ES

АХ,24 SS,AX АХ,32 ES,AX

;Выполним дальний переход, чтобы заново загрузить;селектор в CS и модифицировать его теневой регистр


Расширенные возможности современных микропроцессоров



db OEah;Код команды jmp far

dw offset go;Смещение точки перехода

dw 16;Селектор сегмента команд

;Переключим режим процессора

go: mov EAX,CRO;Получим содержимое CRO

and EAX,OFFFFFFFEh;C6pocHM бит РЕ
mov CRO,EAX;3апишем назад в CRO

db OEah;Код команды far jmp

dw offset return;Смещение точки перехода

dw text;Сегментный адрес

^ ^

; Теперь процессор снова работает в реальном режиме;

^ ^

; Восстановим операционную среду реального режима

return: mov AX,data mov DS,AX mov AX,stk SS,AX SP,512
mov mov sti mov
AX.4COOU

;3агрузим сегментный;регистр DS;3агрузим сегментный;регистр SS восстановим SP;Разрешим прерывания;3авершим программу;обычным образом

2Ih

int

;Размер сегмента команд; Конец сегмента команд; Сегмент; стека

main endp code_size=S -main text ends stk segment stack

db 512 dup О stk ends

;Конец программы и точка входа
Для того, чтобы разрешить использование всех, в том числе привиле­гированных команд 32-разрядных процессоров, в программу включена директива.586Р. Программа начинается с объявления структуры dcr, с помощью кото­рой будут описываться дескрипторы сегментов. Сравнивая описание струк­туры dcr в программе с рис. 4.9, нетрудно проследить их соответствие друг другу. Для удобства программного обращения в структуре dcr база описы­вается тремя полями: младшим словом (base_l) и двумя байтами: средним (base_m) и старшим (base_h). В байте атрибутов 1 задается ряд характеристик сегмента. В примере 4.4 используются сегменты двух типов: сегмент команд, для которого байт attr_l должен иметь значение 98h (присутствующий, только исполнение, DPL=0), и сегмент данных (или стека) с кодом 92п (присутствующий, чтение и запись, DPL=0). Некоторые дополнительные характеристики сегмента указываются в старшем полубайте байта attr_2. Для всех наших сегментов значение этого

end main



Глава 4


полубайта равно 0 (бит G=0, так как граница указывается в байтах, а D=0, так как программа 16-разрядная).

Сегмент данных data начинается с описания важнейшей системной структуры — таблицы глобальных дескрипторов. Как уже отмечалось выше, обращение к сегментам в защищенном режиме возможно исключительно через дескрипторы этих сегментов. Таким образом, в таблице дескрипто­ров должно быть описано столько дескрипторов, сколько сегментов ис­пользует программа. В нашем случае в таблицу включены, помимо обяза­тельного нулевого дескриптора, всегда занимающего первое место в таб­лице, четыре дескриптора для сегментов данных, команд, стека и дополнительного сегмента данных, который мы наложим на видеобуфер, чтобы обеспечить возможность вывода в него символов. Порядок деск­рипторов в таблице (кроме нулевого) не имеет значения.

Поля дескрипторов для наглядности заполнены конкретными данны­ми явным образом, хотя объявление структуры dcr с нулями во всех по­лях позволяет описать дескрипторы несколько короче, например:


gdt_null dcr <>

gdt_datadcr <data_size-l,,,92h>


;Селектор 0 — обязательный;нулевой дескриптор;Селектор 8 — сегмент данных


В дескрипторе gdt_data, описывающем сегмент данных программы, заполняется поле границы сегмента (фактическое значение размера сег­мента data_size будет вычислено транслятором, см. последнее предложе­ние сегмента данных), а также байт атрибутов 1. База сегмента, т.е. линей­ный адрес его начала, в явной форме в программе отсутствует, поэтому ее придется программно вычислить и занести в дескриптор уже на этапе выполнения.



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2016-02-16 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: