Переход в защищенный режим
Ниже приведен пример программы (вторичного загрузчика), выполняющей
инициализацию GDT и переход в защищенный режим. Вторичный загрузчик
предполагает, что он был загружен с дискеты при помощи первичного
загрузчика
BITS16
ORG 0x7E00 ;Вторичный загрузчик
;исполняется по адресу 0x7E00
section .text
_entry:
cli ;Отключение прерываний
;Установка базового вектора прерывания в 0x20:
mov al,00010001b
out 0x20,al
mov al,0x20
out 0x21,al
mov al,00000100b
out 0x21,al
;ручной EOI:
mov al,00000001b
out 0x21,al
;Включение адресной линии A20:
in al, 0x92
or al, 2
out 0x92, al
;Загрузка глобальной таблицы дескрипторов (GDT):
lgdt [gd_reg]
;Обнуление регистра флагов:
push byte 2
popf
;Включение защищенного режима (бит PE в регистре CR0):
mov eax, cr0
or al, 1
mov cr0, eax
;Загрузка селектора сегмента кода в CS путем длинного прыжка
;в 32-битный сегмент
jmp 16:_protected
;=======================================================;
BITS 32
_protected:
;Этот код исполняется в защищенном режиме
;Загрузка сегментных регистров нужными селекторами:
mov ax, 1000b
mov es, ax
mov ds, ax
mov ss, ax
mov [$], byte 0
mov [0xB8000], byte 'S'
xor eax, eax
xor ecx, ecx
;===========================================;
;Копирование ядра по адресу 0x200000 (2 мб):
mov ecx, _kernel
mov eax, 0x200000
.loop:
mov bl, [ecx]
mov [ecx], byte 0
mov [eax], bl
inc ecx
inc eax
cmp ecx, _kernel+0x10000
jl .loop
;===========================================;
jmp 16:0x200000 ;Переход на ядро
;===============================================;
BITS 16
gd_table: ;Глобальная таблица дескрипторов
dw 0xFFFF,0x0000,0x9200,0x00CF ;Дескриптор данных
dw 0xFFFF,0x0000,0x9A00,0x00CF ;Дескриптор кода
db 0x67, 0,0,0,0 ,10001001b, 01000000b, 0 ;сегмент состояния задачи
gd_reg:
dw 255 ;Лимит GDT
dd gd_table-8 ;Линейный адрес GDT
BITS32
TIMES 0x1000-($-$$) db 0 ;Размер вторичного загрузчика - 0x1000 байт
_kernel:
incbin 'kernel.bin' ;Вставка бинарника ядра
TIMES 20000-($-$$) db 0