Наконец что то получилось. Я не стал описывать 4гб описал первые 4мб одну таблицу с 1024 мя страницами по 4кб. Код заработал.
Код:
format Binary as "bin"
use16 ; 16-ти битный код
org 0
jmp start
include "gdt.inc"
SL_CODE equ 08 ; Селектор сегмента кода (1-ый дескриптор в GDT)
SL_DATA equ 16 ; Селектор сегмента данных (2-ий дескриптор в GDT)
start:
cli ; запретить прерывания
mov ax, 0
mov ss, ax
mov sp, ax
mov ax, 0x1000 ; Заносим текуший адрес в AX
mov ds, ax
mov es, ax
sti ; разрешить прерывания
; Очистка экрана
mov ax,02h ; Очищаем экран - функция 02h прерывания 10h
int 10h
; Открыть адресную линию A20 (чтобы была доступна вся память).
in al,0x92 ; Читаем содержимое порта 0х92
or al,2 ; Устанавливаем второй бит
out 0x92,al ; Записываем обратно в порт 0х92
; Заполняем таблицу GDT
; GDT_address, (DW)des_number, (DD)seg_base, (20bit)seg_size, (DW) attr - present,seg_dpl,seg_type,seg_granular,seg_bitDepth
m_add_desc_to_gdt GDT, 0, 0, 0, 0 ; Пустой
m_add_desc_to_gdt GDT, 1, 0, 0FFFFFh, SEG_P+SEG_CODE_X+SEG_G+SEG_32 ; Дескриптор кода
m_add_desc_to_gdt GDT, 2, 0, 0FFFFFh, SEG_P+SEG_DATA_RW+SEG_G+SEG_32 ; Дескриптор данных
; Заняли 24 байт
lgdt [gdtr] ; загружаем регистр GDTR.
; Запрет всех прерываний
cli ; Запретить аппаратные прерывания
; запрет NMI
in al,70h
or al,80h
out 70h,al
; Переключаемся в защищенный режим.
mov eax,cr0
or al,1 ; устанавливаем 0-вой бит
mov cr0,eax ; включаем PM
; Перейдём на 32-битный код
jmp fword SL_CODE:start32
; Глобальная таблица дескрипторов
align 8 ; Процессор быстрее обращается с выравненной табличкой
GDT:
rb 3*8 ; Резервируем место под 5 дескрипторов (один дескриптор = 8 байт), максимум 8192 дескриптора
;Описание глобальной таблицы дескрипторов
gdtr:
.size dw (3*8)-1 ; Размер таблицы в байтах. 5 дескрипторов по 8 байт, минус один байт
.addres dd 0x10000+GDT ; Физический адрес таблицы, сразу после загрузчика
; ====================================================================================================================================
use32
org 0x10000+$
start32:
; Инициализируем сегментные регистры, помещая в них селекторы
mov ax, SL_DATA ; Сегмент данных
mov ds, ax ; ds = SELECTOR_DATA
mov fs, ax ; fs = SELECTOR_DATA
mov ax, SL_DATA ; сегмент стека
mov ss, ax ; ss = SELECTOR_STACK
mov esp, 0x10000 ; Стек
call create_PDE
; включить страничную адресацию
mov eax,cr0
or eax,80000000h
mov cr0,eax
mov esi,string ; Вывести сообщение из PM
call print
jmp $
; ESI - адрес строки
print:
pushad
xor ebx,ebx
mov ah,07h
puts:
mov al,[esi+ebx]
mov [0xb8000+(ebx*2)],ax
inc ebx
test al,al
jnz puts
popad
ret
string db "Protected Mode - Enable", 0
DIR_TABLE_ADDRESS equ 00000000000000010001000000000000b
TABLES_PAGES_ADDRESS equ 00000000000000010010000000000111b
create_PDE:
mov eax,TABLES_PAGES_ADDRESS
mov [0x11000],eax
mov eax,0x12000
mov ecx,1024
mov esi,0000000000000000000000000000111b
@@:
mov [eax],esi
add eax,4
shr esi,3
shl esi,3
add esi,00000000000000000001000000000111b
loop @b
mov eax,DIR_TABLE_ADDRESS ; Адрес каталога страниц 0x11000
mov cr3,eax
ret
; =====================================================================================================================================
;-----Заполнитель-----
; Заполняем оставшееся место до 510 байт нулями
times 512 - ($ - $$) db 0 ; $ = адрес текущей инструкции
; $$ = адрес 1-й инструкции