> man operating_systems
WYOS - Выпуск №4
Защищенный режим процессора
на Вторник, 29 Июнь 2004, 23:42
добавил: commrade список авторов печатать элемент контента создать pdf-файл  элемент контента
категория Статьи > Write Your Own OS
комментарии: 0
просмотров: 922

Рассматривается защищенный режим (protected mode) процессора, адресация, включение режима...

<p>Приветствую вас, о светлейшие из светлейших, о
наумнейшие из суперумных!</p>

<p>Меня зовут commrade. Со мной можно связаться по email: <a href="mailto:sergo92@yandex.ru">sergo92@yandex.ru</a>, либо по ICQ: 248544753. В этом выпуске я вам расскажу о защищенном режиме работы процессора. О режиме, в котором работает
UNIX, XENIX, OS/2, PC-MOS, QNX, Desk View, сетевая операционная система NOVELL,
операционная система Microsoft WINDOWS, драйверы расширенной памяти EMM386 и
QEMM и СУБД ORACLE. </p>

Введение
Защищенный режим работы процессора это режим, в котором реализуются такие возможности современных процессоров, как: многозадачность изолированностьодного приложения от другого, работа с большим объемом оперативной памяти, использование виртуальной памяти, использование на полную катушку всех возможностей "".
Основные отличия реального режима от защищенного
<p>В основном эти два режима между собой отличаются, в следующем:</p>

<ol>
<li>Адресация памяти.

<p>В реальном режиме работы процессора память адресуется посредством
двухкомпонентноо логического адреса (пример: <tt>A700:FFFFh</tt>). Делается это потому что для представления
физического адреса в компьютерах IBM PC и IBM XT используется двадцать двоичных
или пять шестнадцатеричнх разрядов. Но все регистры процессора i8086 являются
16-разрядными. Для разрешения этой проблемы используется двухкомпонентны
логический адрес. Логический адрес состоит из 16-разрядных компонент:
компоненты сегмента памяти и компоненты смещения внутри сегмента. Такой способ
адресации накладывает ограничение на адресное пространство до 1 мегабайта плюс
примерно 64 килобайта старшей области памяти для процессоров i80286, i80386 и
i80486.</p>

<p>При работе в защищенном режиме используется более сложный способ адресации памяти, который позволяет избежать ограничения в 1 мегабайт
памяти. Для получения физического адреса памяти используется так называемый
селектор, который фактически является индексом к таблице дескрипторов, где
храняться 24-разрядные базовые адреса, а физический адрес получается сложением
этого базового адреса и смещения.</p>
</li>
<li>Защита

<p>В реальном режиме работы процессора есть свободный доступ для любых программ
к любым областям данных, что представляет потенциальную опасность для
целостности операционной системы. В защищенном режиме работы программа имеют
доступ только к той области данных которую ей выделяет
процессор. Грубо говоря любой процесс (программа)
видит только свою <tt>LDT</tt>. Также для защиты памяти и файлов операционной системы
используется поле <tt>RPL</tt> в селекторе.</p>
</li>
<li>Виртуальная память
<p>Основная идея виртуальной памяти заключается в том, чтобы хранить (и
обновлять) содержимое большой виртуальной памяти на диске, подкачивая отдельные
участки виртуальной памяти в реальную оперативную память по необходимости.
Данная возможность доступна только в защищенном режиме работы </p>
</li>
</ol>

Локальная и глобальная таблицы дескрипторов
Селектор - индекс к таблице дескрипторов, где храняться 24-разрядные
базовые адреса для вычисления физического адреса сегмента.

<p><img border=0 src='files/images/articles/wyos/selector.png'></p>
<p>Формат селектора следующий (см. рисунок): с 3 бита по 15 отводится под сам
индекс, бит 2 это так называемый индикатор таблицы (Table Indicator далее <tt>TI</tt>),
если этот бит равен нулю, для преобразования адреса
используется так называемая глобальная таблица дескрипторов (Global Descriptor
Table далее <tt>GDT</tt>), в противном случае - локальная таблица дескрипторов (Local
Descriptor Table далее <tt>LDT</tt>). Биты с 0 по 1 задают запрошенный
программой уровень привилегий (Requested Privilege Level далее <tt>RPL</tt>). Поле <tt>TI</tt>
(Table Indicator) состоит из одного бита. Если этот бит
равен нулю, для преобразования адреса используется так называемая глобальная
таблица дескрипторов <tt>GDT</tt> (Global Descriptor Table), в противном случае -
локальная таблица дескрипторов <tt>LDT</tt> (Local Descriptor Table).</p>
<b>Таблица дескрипторов - это просто таблица преобразования адресов,
содержащая базовые 24-разрядные физические адреса сегментов и некоторую другую
информацию. То есть каждый элемент таблицы дескрипторов (дескриптор)
содержит 24-разрядный базовый адрес сегмента и другую информацию, описывающую
сегмент.</b>
<p>Таблица <tt>GDT</tt> - единственная в системе. Обычно в ней находятся описания
сегментов операционной системы. Таблиц <tt>LDT</tt> может быть много. Эти таблицы
содержат описания сегментов программ, работающих под управлением операционной
системы, т.е. отдельных задач. В отдельный момент времени процессор может
использовать только одну таблицу <tt>LDT</tt>. Процессор имеет два регистра,
предназначенныхдля адресации используемых в настоящий момент таблиц <tt>GDT</tt> и <tt>LDT</tt>.
Регистр <tt>GDTR</tt> описывает расположение и размер таблицы <tt>GDT</tt>, а регистр <tt>LDTR</tt>
содержит ссылку на использующуюся в настоящее время таблицу <tt>LDT</tt>.
Регистры процессора <tt>GDTR</tt> и <tt>LDTR</tt> определяют расположение в памяти таблиц <tt>GDT</tt> и
<tt>LDT</tt> соответственно. Формат регистра <tt>GDTR</tt> показан на рисунке:</p>
<p><img border=0 src='files/images/articles/wyos/gdtr.png'></p>
<p>Таблицы <tt>GDT</tt> и <tt>LDT</tt> содержат дескрипторы, описывающие сегменты памяти. В этих
дескрипторах, помимо другой информации содержится 24-разрядный базовый адрес
сегмента. Старшие 13 битов селектора выбирают элемент из таблицы <tt>GDT</tt> или <tt>LDT</tt> в
зависимости от состояния бита <tt>TI</tt> селектора. Извлечённый из таблицы дескрипторов
базовый адрес сегмента складывается процессором для получения 24-разрядного
физического адреса. Структура дескриптора следующая (см. рисунок):</p>
<p><img border=0 src='files/images/articles/wyos/descript.png'></p>
<p>Назначения этих полей следующие:</p>

<p>Базовый адрес – 24-разрядное чило указывающие на физический адрес сегмента.</p>

<p>Резерв – дополнительное 16-разрядное число, совместно с базовым адресом
указывающие на физический адрес сегмента, в основном используется
процессорами i80386, i80486 и выше, т.к. разрядность шины адреса у этих
процессоров 32-бита (<i>Khimov Roman:</i> начиная с Pentium II шина адреса Intel'овских процеесоров - 36 бит (причем, заметьте - в Celeron от Pentium II адресная шина была по прежнему 32-битная!). AMD не отстает... .</p>

<p>Доступ – 8-разрядное число говорящее о том, к каком типу данных принадлежит тот или иной
сегмент, возможно ли чтение или запись данных в этот сегмент.</p>

<p>Предел – указывает на размер сегмента в байтах, уменьшенный на единицу.</p>

<p>Если с базовым адресом, резервом, и пределом все понятно, то полем доступа
не все так просто. В защищенном режиме существует три типа сегмента. Сегмент
кода, сегмент данных и системный сегмент. Структура этих сегментов покзана на
рисунке ниже:</p>
<p><img border=0 src='files/images/articles/wyos/seg.png'></p>
<p>Остановимся на назначении битов в поле доступа для каждого типа сегмента.
Поле доступа дескриптора сегментов кода содержит битовое поле <tt>R</tt>, называемое
битом разрешения чтения сегмента. Если этот бит
установлен в 1, программа может считывать содержимое сегмента кода. В противном
случае процессор может только выполнять этот код. Поле <tt>W</tt>, поле доступа сегмента
данных, называется битом разрешения записи в сегмент. Бит <tt>C</tt> называется битом
подчинения. Бит <tt>P</tt> называется битом присутствия сегмента в памяти. Для тех
сегментов, которые находятся в физической памяти бит должен быть установлен в
1. Бит <tt>A</tt> называется битом обращения к сегменту. Поле
<tt>D</tt> задаёт направление расширения сегмента. Обычный сегмент данных расширяется в
область старших адресов. Если же в сегменте расположен стек, расширение
происходит в обратном направлении - в область младших адресов. Для сегментов, в
которых организуются стеки, необходимо устанавливать поле <tt>D</tt> равным 1.
Поле <tt>DPL</tt>, используюется для организации защиты сегментов. Данное поле
очень тесно связано полем <tt>RPL</tt> селектора. Дескрипторы
системных сегментов содержат поле <tt>TYPE</tt>, определяющее тип системного сегмента. В
таблице приведены возможные для этого поля значения.</p>

<table border=1 cellpadding=0>
<tr>
<td>
Поле <tt>TYPE</tt>
</td>
<td>
Тип сегмента
</td>
</tr>
<tr>
<td>
0
</td>
<td>
Запрещённое значение
</td>
</tr>
<tr>
<td>
1
</td>
<td>
Доступный <tt>TSS</tt> для процессора i80286
</td>
</tr>
<tr>
<td>
2
</td>
<td>
Сегмент <tt>LDT</tt>
</td>
</tr>
<tr>
<td>
3
</td>
<td>
Занятый <tt>TSS</tt> для процессора i80286
</td>
</tr>
<tr>
<td>
4
</td>
<td>
Вентиль вызова для процессора i80286
</td>
</tr>
<tr>
<td>
5
</td>
<td>
Вентиль задачи для процессоров i80286 и i80386
</td>
</tr>
<tr>
<td>
6
</td>
<td>
Вентиль прерывания для процессора i80286
</td>
</tr>
<tr>
<td>
7
</td>
<td>
Вентиль исключения для процессора i80286
</td>
</tr>
<tr>
<td>
8
</td>
<td>
Запрещённое значение
</td>
</tr>
<tr>
<td>
9
</td>
<td>
Доступный <tt>TSS</tt> для процессора i80386
</td>
</tr>
<tr>
<td>
A
</td>
<td>
Зарезервировано
</td>
</tr>
<tr>
<td>
B
</td>
<td>
Занятый <tt>TSS</tt> для процессора i80386
</td>
</tr>
<tr>
<td>
C
</td>
<td>
Вентиль вызова для процессора i80386
</td>
</tr>
<tr>
<td>
D
</td>
<td>
Зарезервировано
</td>
</tr>
<tr>
<td>
E
</td>
<td>
Вентиль прерывания для процессора i80386
</td>
</tr>
<tr>
<td>
F
</td>
<td>
Вентиль ловушки для процессора i80386
</td>
</tr>
</table>

<p>Программы
реального режима работают всегда с сегментами размером 64 килобайта. Если
программа состоит из нескольких сегментов, то некоторые сегменты могут
перекрываться. Существует потенциальная опасность, что в результате программной
ошибки (например, выхода индекса массива за допустимые пределы) произойдёт
запись в другой сегмент. Процессор i80286 позволяет создавать сегменты любого
размера в пределах 64 килобайт (процессоры i80386 и i80486 могут работать с
сегментами размером 4 гигабайта). Кроме того, он следит за тем, чтобы при
адресации памяти не происходил выход за границы сегмента. Границы сегмента
задаются полем предела в дескрипторе сегмента. Мы уже говорили, что значение
этого поля должно быть равно размеру сегмента в байтах минус единица.
Интерпретация поля предела зависит от состояния бита <tt>D</tt> поля доступа. Для
сегментов стеков необходимо устанавливать поле <tt>D</tt> равным 1.
В этом случае попытка записи в переполненный стек вызовет прерывание программы.
В ответ на это прерывание операционная система может, например, выделить
дополнительную память для стека. В реальном режиме переполнение стека никак не
контролируется и может привести к разрушению самой программы или операционной
системы.</p>

Команды защищенного режима

<p>Все
описанные выше структуры данных легко можно описать и задать с помощью
ассемблера для этих целей подойдет как TASM (как наиболее популярный интерпретатор) так и FASM (как наиболее простой в
использовании). У этих двух ассемблерных интепретаторов имеются команды для
работы в защищенном режиме и выхода в защищенный режим. Вот основные команды
ассемблера для выхода и работы в защищенном режиме (более детально данные
команды нужно рассматривать исходя из конкретного
интепретатора):</p>

<table border=1 cellpadding=0>
<tr>
<td>
Команда
</td>
<td>
Выполняемые функции
</td>
</tr>
<tr>
<td>
<tt>LGDT</tt>
</td>
<td>
Загрузка регистра глобальной таблицы дескрипторов <tt>GDTR</tt>
</td>
</tr>
<tr>
<td>
<tt>LLDT</tt>
</td>
<td>
Загрузка регистра локальной таблицы дескрипторов <tt>LDTR</tt>
</td>
</tr>
<tr>
<td>
<tt>LIDT</tt>
</td>
<td>
Загрузка регистра таблицы дескрипторов прерываний <tt>IDTR</tt>
</td>
</tr>
<tr>
<td>
<tt>LTR</tt>
</td>
<td>
Загрузка регистра задачи <tt>TR</tt>
</td>
</tr>
<tr>
<td>
<tt>LMSW</tt>
</td>
<td>
Загрузка слова состояния машины <tt>MSW</tt>
</td>
</tr>
<tr>
<td>
<tt>CLTS</tt>
</td>
<td>
Сброс флага переключения задачи
</td>
</tr>
<tr>
<td>
<tt>HLT</tt>
</td>
<td>
Останов процессора
</td>
</tr>
</table>

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

<p>Перед тем, как переключить процессор в защищённый режим, надо выполнить
некоторые подготовительны действия, а именно:</p>
<ol>
<li>Подготовить в оперативной памяти глобальную таблицу дескрипторов <tt>GDT</tt>. В
этой таблице должны быть созданы дескрипторы для всех сегментов, которые будут
нужны программе сразу после того, как она переключится в защищённый режим.
Впоследствии, находясь в защищённом режиме, программа может модифицировать <tt>GDT</tt>
(если, разумеется, она работает в нулевом кольце защиты). Программа может
модифицировать имеющиеся дескрипторы или добавить новые, загрузив заново
регистр <tt>GDTR</tt>.</li>

<li>Для обеспечения возможности возврата из защищённого режима в реальный
необходимо записать адрес возврата в реальный режим в область данных BIOS по адресу
<tt>0040h:0067h</tt>, а также записать в CMOS-память в ячейку <tt>0Fh</tt> код <tt>5</tt>. Этот код
обеспечит после выполнения сброса процессора передачу управления по адресу,
подготовленномунами в области данных BIOS по адресу <tt>0040h:0067h</tt>.</li>

<li>Запретить все маскируемые и немаскируемые прерывания.</li>

<li>Открыть адресную линию <tt>A20</tt>.</li>

<li>Запомнить в оперативной памяти содержимое сегментных регистров, которые
необходимо сохранить для возврата в реальный режим, в частности, указатель
стека реального режима.</li>

<li>Загрузить регистр <tt>GDTR</tt>. </li>
</ol>

<p>В терминах языка ассемблера структура дескриптора может
быть описана следующим образом (здесь и далее рассматриваеются тексты на языке
ассемблер для TASM 5.0 взятые из статьи [1]:</p>


STRUC desc_struc
     limit     dw 0
         ; предел сегмента
     base_lo   dw 0
         ; младшее слово 24-битового физического адреса сегмента
     base_hi   db 0
         ; старший байт 24-битового физического адреса сегмента
     access    db 0
         ; поле доступа
     reserved  dw 0
         ; зарезервировано для сегментов процессора i80286 должно быть равно нулю
ENDS desc_struc


<p>Тогда мы можем определить таблицу <tt>GDT</tt> как набор дескрипторов со структурой
<tt>desc_struc</tt>:</p>


GDT_BEG = $                       ; отмечаем начало GDT

LABEL gdtadr WORD

  gdt_0   desc_struc <0,0,0,0,0>  ;первый элемент не используется
  gdt_gdt desc_struc 
  gdt_ds  desc_struc 
  gdt_cs  desc_struc 
  gdt_ss  desc_struc 

GDT_SIZE = ($ - GDT_BEG)          ; вычисляем размер GDT



<p>Нам необходимо также замаскировать все маскируемые и
немаскируемые прерывания:</p>



  cli
  mov al,8f
  out CMOS_PORT,al
  jmp next1            ; небольшая задержка

next1:
  mov al,5
  out CMOS_PORT+1,al



<p>Открытие адресной линии <tt>A20</tt> - необходимо в том случае, если
ваша программа будет обращаться к оперативной памяти, лежащей за пределами
первого мегабайта:</p>



;---------------------------------------
; Процедура открывает адресную линию A20
;---------------------------------------
PROC  enable_a20  NEAR
   
   mov al,A20_PORT
   out STATUS_PORT,al
   mov al,A20_ON
   out KBD_PORT_A,al
   ret
   
ENDP  enable_a20



<p>Эта магическая последовательноть команд выдаёт команду <tt>A20_ON</tt> клавиатурному
процессору 8042, к которому подключены схемы управления адресной линией <tt>A20</tt>. После начального сброса
линия <tt>A20</tt> закрыта, и расширенная память за границами первого мегабайта
недоступна. </p>

<p>Следующий этап - запоминание содержимого сегментных
регистров, которые будут нужны при возврате в реальный режим. Это сегментные
регистры <tt>SS</tt> и <tt>ES</tt>:</p>



mov [real_ss],ss     ; запоминаем указатель стека
mov [real_es],es     ; для реального режима



<p>На последнем перед переключением в защищённый режим этапе мы
загружаем регистр <tt>GDTR</tt> адресом подготовленной заранее
<tt>GDT</tt>:</p>



lgdt [QWORD gdt_gdt]



<p>Всё! Можно переключаться в защищённый режим! </p>

Послесловие

<p>Данная статья была в основном написана под впечатлением от книги
"Защищенный режим процессоров Intel 80286/80386/80486" Александр
Фролов, Григорий Фролов. Приведенные здесь примеры кода нетрудно переписать как
под <a href='http://fasm.sourceforge.net'>FASM</a> так и под <a href='http://www.cryogen.com/Nasm'>Nasm</a>. Если вы закачеете файл по ссылке, то вместе с html-вариантом
книги Александра Фроловa вы получите архив с примерами программ для работы в
защищенном режиме. </p>

<p>Вот теперь все. Всех благ! С вами был commrade. </p>

Список использованной при подготовке
материала литературы и ссылки в интернет:


<ol>
<li>
<a href='http://stratum11.pstu.ac.ru/~leonid/base/fv06.zip'>"Защищенный режим процессоров Intel 80286/80386/80486" Александр Фролов, Григорий </a>
</li>
<li>
<a href='http://www.citforum.ru/hardware/'>http://www.citforum.ru/hardware/</a> - море информации по различным
апаратным платформам
</li>
<li>
<a href='http://www.nondot.org/sabre/os/articles'>http://www.nondot.org/sabre/os/articles</a> - информация по различным аспектам написания ОС, правда все на английском
</li>
<li>
<a href='http://lib.prm.ru/'>http://lib.prm.ru/</a> - электронная библиотека
</li>
</ol>

Послесловие от Khimov Roman

<p>
Очередной выпуск. Надеюсь, вы начали читать его не отсюда и уже прочитали <br>
Теперь немного о грустном: некоторое (и довольно длительное) время рассылка будет существовать без основателя, то есть
Wanderer'a. О причинах мы и сами многого не знаем, но ничего не попишешь. В принципе, это не повод расстраиваться,
мы приложим максимум усилий, чтобы рассылка по прежнему выходила раз в неделю.<br>
На время отсутствия Wanderer'а "главным " рассылки остаюсь я, Химов Роман (ну надо же! - по-русски написал! . Так как на этой должности я только осваиваюсь, то вчера вы получили письмо с темой "Test", я проверял как работает рассылка . Дайджест-режим я выключил для всех - так выпуски будут доходить быстрее и менее вероятны глюки
mailman'a (этот товарищ не очень любит дайджесты... . Вопросы, связанные с этим выпуском направляйте выпускающему, то есть <a href='mailto:sergo92@yandex.ru'>commrade</a>. Общие вопросы направляйте мне, на <a href='mailto:khimov@osrc.info?subject=WriteYourOwnOS'>khimov@osrc.info</a>.
</p>
<p>
Следующий выпуск будет посвящен файловым системам, тема обширная, возможно растянем на два выпуска, чтобы поподробнее. Готовить выпуск будет Doberman. Не пропустите!
</p>


Комментарии доступны только авторизованным пользователям, авторизуйтесь или зарегистрируйтесь на сайте здесь

© OSRC.info, 2004-2010.
Авторские права на любые материалы, авторы которых явно указаны, принадлежат их авторам. По вопросам публикации таких материалов обращайтесь к авторам.
Авторские права на любые другие материалы принадлежат OSRC.info.
Сайт является помещением библиотеки. Копирование, сохранение на жестком диске или иной способ сохранения произведений осуществляются пользователями на свой риск.
При использовании материалов сайта ссылка на OSRC.info обязательна.