Создание операционной системы на ассемблере

         

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


Бутсектор не особо беспокоится об организации памяти в системе - это забота ядра. Для перехода в защищенный режим он описывает всего два сегмента: сегмент кода и сегмент данных. оба сегмента имеют базовый адрес - 0 и предел в 4 гигабайта (это нам пригодиться для проверки наличия памяти).

Перед переходом в защищенный режим нам необходимо включить адресную линию A20. По моим сведениям этот механизм ввели в пору 286 для предотвращения несанкционированных обращений к памяти свыше одного мегабайта (непонятно зачем?). Но поскольку это имеет место быть - нам это нужно обрабатывать, иначе каждый второй мегабайт будет недоступен. Делается это почему-то через контроллер клавиатуры (еще одна загадка).

mov al, 0xd1 out 0x64, al mov al, 0xdf out 0x60, al

После этого можно переходить в защищенный режим.

lgdt [gd_desc]

В регистр gdtr загружается дескриптор GDT.

push byte 2 popf

Очищается регистр флагов.

mov eax, cr0 or al, 1 mov cr0, eax

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

jmp 16:.epm

BITS 32 .epm:

16 в этом адресе перехода - это не сегмент. Это селектор сегмента кода.

mov ax, 8 mov ds, ax mov es, ax

; Ставим стек. mov ss, ax movzx esp, sp

После всего этого мы инициализируем сегментные регистры соответствующими селекторами, в том числе и сегмент стека, но указатель стека у нас не меняется, только теперь он становится 32-х битным.

...

gd_table: ; пеpвый дескpиптоp - данные и стек istruc descriptor at descriptor.limit_0_15, dw 0xffff at descriptor.base_0_15, dw 0 at descriptor.base_16_23, db 0 at descriptor.access, db 0x92 at descriptor.limit_16_19_a, db 0xcf at descriptor.base_24_31, db 0 iend

; втоpой дескpиптоp - код istruc descriptor at descriptor.limit_0_15, dw 0xffff at descriptor.base_0_15, dw 0 at descriptor.base_16_23, db 0 at descriptor.access, db 0x9a ; 0x98 at descriptor.limit_16_19_a, db 0xcf at descriptor.base_24_31, db 0 iend

Это GDT - Глобальная таблица дескрипторов. Здесь всего два дескриптора, но во избежание ошибок в адресации обычно вводится еще один дескриптор - нулевой, который не считается допустимым для использования. Мы не будем резервировать для него место специально, просто начало таблицы сместим на 8 байт выше.

gd_desc: dw 3 * descriptor_size - 1 dd gd_table - descriptor_size

А это содержимое регистра GDTR. Здесь устанавливается предел и базовый адрес дескриптора. обратите внимание на базовый адрес, здесь происходит резервирование нулевого дескриптора.

Теперь процессор находится в защищенном режиме и уже не оперирует сегментами, а оперирует селекторами. Селекторов у нас всего три. Нулевой - недопустим. восьмой является селектором данных и шестнадцатый - селектором кода.

После этого управление можно передать ядру. дальше со всем этим будет разбираться оно.



Содержание раздела