Рассылка закрыта
При закрытии подписчики были переданы в рассылку "Для бухгалтера: программы, новости, советы" на которую и рекомендуем вам подписаться.
Вы можете найти рассылки сходной тематики в Каталоге рассылок.
Разработка операционных систем - для начинающих и не только!
Информационный Канал Subscribe.Ru |
Разработка операционных систем
Выпуск 6 от 2003-05-20
Сегодня в номере:
- Intro
- Обзор архитектуры IA-32
- Введение в защищенный режим IA-32
- Переключение процессора в защищенный режим (практическая часть)
Intro
Начиная с этого выпуска, уважаемые подписчики, мы по мере надобности будем изучать архитектуру системного уровня процессоров IA-32. Тема очень сложная, поэтому - пишите, если что-нибудь будет непонятно изложено.
Обзор архитектуры IA-32
Напомню, что архитектуру IA-32 (Intel Architecture 32-bit) имеют все 32-разрядные процессоры Intel от Intel386 до Pentium 4 и Xeon. Все они являются обратно совместимыми вплоть до процессора 8086 (который даже к IA-32 не относится, хотя иногда Intel называет его 16-битным IA-32 процессором - получается что-то вроде 16-разрядный представитель семейства 32-разрядных процессоров :)). Другое название этой архитектуры (которое очень любит фирма AMD) - x86 или 80x86.
Эта архитектура занимает лидирующее положение на рынке процессоров для персональных компьютеров. Но за это лидирование фирме Intel пришлось заплатить большую цену - по выражению Энди Танненбаума, при разработке Pentium II основополагающими были 3 фактора:
- Совместимость с предыдущими моделями процессоров
- Совместимость с предыдущими моделями процессоров
- Совместимость с предыдущими моделями процессоров
Необходимость совместимости наложила огромный отпечаток на архитектуру - система команд процессора очень сложна и запутанна, программисту предоставляется слишком мало регистров (и, вследствие чего, зачастую для временного хранения данных приходится использовать оперативную память). По некоторым расчетам, избавившись от вороха старья, тянущегося еще со времен 8080 и 8086, инженеры Intel могли бы повысить производительность процессора на 20-30%.
Тем не менее, нам эту несовершенную архитектуру придется воспринимать как должное, ибо первый аппаратно-зависимый слой нашей ОС будет предназначен именно для нее.
Процессоры IA-32 могут функционировать в двух основных режимах: режиме реальных адресов (или реальном режиме) и защищенном режиме. Так же имеется псевдо-режим виртуального 8086 и режим SMM (system management mode).
В реальном режиме процессор функционирует практически также как 8086, за исключением возможности использовать 32-битные регистры и появившиеся в последующих процессорах новые непривилегированные команды. Еще одна особенность - находясь в реальном режиме, процессор может быть переведен в защищенный режим. Реальный режим предназначен только для совместимости с предыдущими моделями процессоров и механизмов защиты в нем нет
Защищенный режим - основной режим процессора, который должны использовать современные операционные системы, и который позволяет использовать все возможности процессора (включая 32-битную адресацию памяти, все инструкции, аппаратную многозадачность, механизмы защиты и пр.). Впервые защищенный режим появился в процессоре 80286 (тогда он еще был 16-битным) и принял современный вид в процессоре 80386. Процессоры 80386 и все последующие, в отличие от 80286, предоставляют возможность перехода из защищенного режима обратно в реальный
Задача защищенного режима (при условии использования аппаратной многозадачности) может выполняться в режиме виртуального 8086 (VM86) - т.е. в режиме эмуляции 8086, который очень похож на реальный режим. Таким образом, например, осуществляется эмуляция MS-DOS в системе Windows
Режим SMM предназначен для более полного контроля аппаратуры, энергопотребления и пр. Вход в него осуществляется только при получения сигнала на входе #SMI (system management interrupt) процессора. Он предоставляет изолированную среду выполнения (которая не пересекается с другими режимами, в каком бы из них процессор не находился при получении #SMI). Этот режим нам не понадобится и рассматривать его подробно мы не будем
Напоследок добавлю, что при включении компьютера процессор оказывается в реальном режиме (опять же в целях совместимости) и загрузчик операционной системы должен перевести его в защищенный режим.
Введение в защищенный режим IA-32
Для поддержки различных функциональных возможностей процессора (многозадачность, виртуальная память, мультипроцессорность, обработка прерываний и др.), IA-32 предоставляет набор системных регистров и различных управляющих структур.
Основная структура данных защищенного режима - дескриптор
, который представляет из себя 8 байт данных. Дескрипторы используются для контроля сегментации, аппаратной многозадачности, обработки прерываний.
Находясь в защищенном режиме, процессор всегда использует сегментацию - т.е. все доступное адресное пространство (т.е. память, к которой процессор может обратиться; физически же эта память может и не присутствовать) процессора разделяется на защищенные части, которые называются сегментами и в дальнейшем каждое обращение к памяти осуществляется через один из сегментов. В дескрипторе сегмента хранится информация о типе сегмента (кода или данных), его базе (адресе с которого сегмент начинается), лимите (размере сегмента), уровне привилегий сегмента и др. Более подробно структуру дескриптора мы рассмотрим на практике.
В чем смысл применения сегментации? Она позволяет реализовать механизм защиты на уровне сегментов. Например ядро операционной системы можно (и нужно) разместить в сегменте с уровнем привилегий 0, а пользовательскую программу - в сегменте с уровнем привилегий 3. В результате пользовательская программа не сможет вмешаться в работу ядра ОС.
В большинстве других процессоров сегментов не существует, а значит сегментация непортабельна. Следовательно делать упор на сегментацию мы будем, а попытаемся скрыть сегментированность от ядра и приложений (отнеся ее к аппаратно-зависимой части системы)
Переключение процессора в защищенный режим (практическая часть)
Размер сегментных регистров в защищенном режиме - 10 байт. Из них 8 недоступны для пользователя и называются теневой частью или кэшем дескриптора. Доступные 2 байта сегментных регистров содержат селектор, формат которого таков:
биты 16-3: номер дескриптора сегмента в таблице (от 0 до 8191)
бит 2: используемая таблица (0 - глобальная, 1 - локальная)
биты 1-0: запрашиваемый уровень привилегий (RPL)
При загрузке селектора в сегментный регистр, в его теневую часть загружается дескриптор, на который указывает селектор, благодаря этому процессору не требуется при каждом обращении к памяти запрашивать таблицу дескрипторов.
Для того, чтобы перевести процессор в защищенный режим нам понадобится глобальная таблица дескрипторов. Она содержит по одному восьмибайтному дескриптору для каждого сегмента. Дескриптор содержит 32-разрядный адрес начала сегмента (База), 20-битный размер сегмента (Лимит) и 12 бит описывающих тип сегмента. Ниже приводится полный формат дескриптора:
бит 7 бит 6 бит 5 бит 4 бит 3 бит 2 бит 1 бит 0 +-------+-------+-------+-------+-------+-------+-------+-------+ байт 0 | <--------------- биты 7-0 лимита сегмента ------------------> | +-------+-------+-------+-------+-------+-------+-------+-------+ +-------+-------+-------+-------+-------+-------+-------+-------+ байт 1 | <--------------- биты 15-8 лимита сегмента -----------------> | +-------+-------+-------+-------+-------+-------+-------+-------+ +-------+-------+-------+-------+-------+-------+-------+-------+ байт 2 | <--------------- биты 7-0 базы сегмента --------------------> | +-------+-------+-------+-------+-------+-------+-------+-------+ +-------+-------+-------+-------+-------+-------+-------+-------+ байт 3 | <--------------- биты 15-8 базы сегмента -------------------> | +-------+-------+-------+-------+-------+-------+-------+-------+ +-------+-------+-------+-------+-------+-------+-------+-------+ байт 4 | <--------------- биты 23-16 базы сегмента ------------------> | +-------+-------+-------+-------+-------+-------+-------+-------+ +-------+-------+-------+-------+-------+-------+-------+-------+ байт 5 | P | DPL | S | <------ Тип сегмента -------> | +-------+-------+-------+-------+-------+-------+-------+-------+ P - бит присутствия сегмента. Пока мы не реализовываем виртуальную память, он должен быть всегда установлен в 1 DPL - уровень привилегий дескриптора (Descriptor Privelege Level) Пока мы используем только нулевой (высший) уровень привилегий S - указывает является ли дескриптор системным (0) или обычным дескриптором сегмента кода или данных (1) Формат четырехбитного поля "тип сегмента" зависит от типа дескриптора. Более подробно мы рассмотрим его в следующий раз, ну а пока используем такие значения: 0010 - для дескриптора сегмента данных 1010 - для дескриптора сегмента кода 7 6 5 4 3 2 1 0 +-------+-------+-------+-------+-------+-------+-------+-------+ байт 6 | G | B | 0 | AVL | биты 19-16 лимита сегмента | +-------+-------+-------+-------+-------+-------+-------+-------+ G - бит гранулярности лимита. Если он установлен в 0, то лимит измеряется в байтах (мы помним, что на лимит отводится 20 бит) и составляет от 0 до одного мегабайта. Если же установлен в 1, то лимит измеряется в 4-килобайтных единицах и составляет тогда от 0 до 4 гигабайт. B - бит разрядности сегмента (0 - 16-битный сегмент, 1 - 32-битный) Бит 5 должен быть установлен в 0 Бит 4 не используется процессором и, следовательно, может использоваться операционной системой +-------+-------+-------+-------+-------+-------+-------+-------+ байт 7 | <--------------- биты 31-24 базы сегмента ------------------> | +-------+-------+-------+-------+-------+-------+-------+-------+
Фактически, за вход в защищенный режим отвечает нулевой бит регистра CR0, который также называется битом PE (Protection Enable). Но перед включением защищенного режима шестибайтная структура, состоящая из 32-разрядного линейного адреса таблицы дескрипторов (GDT) и 16-битного лимита таблицы (количества элементов таблицы; можно указывать 8192), должна быть загружена в регистр GDTR.
Также во время этого процесса должны быть отключены прерывания, поскольку сразу после перехода в защищенный режим процессор не будет знать, как их обрабатывать
И еще один момент - необходимо включить адресную линию A20, которая для совместимости с 80186 отключена при старте компьютера. Если мы этого не сделаем, то все обращения к нечетным мегабайтам памяти будут отображаться на четные, т.е. обращение, допустим, по адресу 1.5 мб на самом деле произойдет по адресу 0.5 мб.
Итак, наша задача такова:
- Построить GDT с двумя дескрипторами: сегмента кода и данных. Каждый сегмент будет иметь базу 0 и лимит 4 Гб, что покроет всю адресуемую процессором память
- Включить адресную линию A20
- Установить бит PE регистра CR0 в 1
- Выполнить длинный прыжок в 32-битный сегмент
[BITS 16] [ORG 0x7c00] _start: cli mov ax, cs mov ds, ax mov ss, ax mov sp, _start ;; Загрузка регистра GDTR: lgdt [gd_reg] ;; Включение A20: in al, 0x92 or al, 2 out 0x92, al ;; Установка бита PE регистра CR0 mov eax, cr0 or al, 1 mov cr0, eax ;; С помощью длинного прыжка мы загружаем ;; селектор нужного сегмента в регистр CS ;; (напрямую это сделать нельзя) ;; 8 (1000b) - первый дескриптор в GDT, RPL=0 jmp 0x8: _protected [BITS 32] _protected: ;; Загрузим регистры DS и SS селектором ;; сегмента данных mov ax, 0x10 mov ds, ax mov ss, ax mov esi, msg_hello call kputs ;; Завесим процессор hlt jmp short $ cursor:dd 0 %define VIDEO_RAM 0xB8000 ;; Функция выполняет прямой вывод в память видеоадаптера ;; которая находится в VGA-картах (и не только) по адресу 0xB8000 kputs: pusha .loop: lodsb test al, al jz .quit mov ecx, [cursor] mov [VIDEO_RAM+ecx*2], al inc dword [cursor] jmp short .loop .quit: popa ret gdt: dw 0, 0, 0, 0; Нулевой дескриптор db 0xFF; Сегмент кода с DPL=0 db 0xFF; Базой=0 и Лимитом=4 Гб db 0x00 db 0x00 db 0x00 db 10011010b db 0xCF db 0x00 db 0xFF; Сегмент данных с DPL=0 db 0xFF; Базой=0 и Лимитом=4Гб db 0x00 db 0x00 db 0x00 db 10010010b db 0xCF db 0x00 ;; Значение, которое мы загрузим в GDTR: gd_reg: dw 8192 dd gdt msg_hello:db "Hello from the world of 32-bit Protected Mode",0 times 510-($-$$) db 0 db 0xaa, 0x55
Эту программу необходимо откомпилировать с помощью NASM в чистый бинарный формат и записать в загрузочный сектор дискеты (точно также как мы делали это во втором выпуске)
Outro
На сегодня все, уважаемые подписчики
Как всегда, мой почтовый ящик открыт для вас: lonesome@lowlevel.ru
Также вы можете задавать интересующие вас вопросы в форуме lowlevel.ru
Предыдущие выпуски рассылки вы можете найти по этому адресу:
http://subscribe.ru/archive/comp.soft.prog.osdev
Всего наилучшего!
Lonesome
http://subscribe.ru/
E-mail: ask@subscribe.ru |
Отписаться
Убрать рекламу |
В избранное | ||