OSDev http://osdev.su/ |
|
Страничная адресация на практике http://osdev.su/viewtopic.php?f=6&t=3737 |
Страница 1 из 4 |
Автор: | FreeProger [ 24 май 2019, 20:41 ] |
Заголовок сообщения: | Страничная адресация на практике |
Помогите разобраться со страничной адресацией. Принцип её работы я вроде понял, а вот как на практике прикрутить её к своему ядру, додуматься не получается. 1) Когда её лучше включать, до перехода в PM или после? 2) Где лучше в памяти разместить каталог с таблицами? 3) Допустим мое ядро весит 16384 байт получается я должен описать 4 таблицы по 4 КБ? Но я не могу понять какие у страниц должны быть базовые физические адреса, такие же как у ядра? Ведь ядро должно как то в них попасть. И потом какой должна быть директива ORG после включения страничной адресации, если я задам виртуальные адреса страниц от нуля то ORG = 0 ? Ниже код из моего ядра, в котором я хочу реализовать страничную адресацию: Код: format binary
use16 ; Логический адрес ядра KERNEL_SEG_BASE equ 0x1000 ; Сегмент в который загруженно ядро KERNEL_OFFSET equ 0x0000 ; Смещение в сегменте с которого начинается код ядра ; Физический адрес ядра (физический адрес базы). KERNEL_BASE equ KERNEL_SEG_BASE * 16 ; При логической адресации для получения физического адреса процессор ; автоматически умножает адрес сегмента на 16 org KERNEL_OFFSET ; Для наглядности jmp init16 include "gdt.inc" ; Работа с глобальной таблицей дескрипторов ;-----Инициализация----- init16: cli ; запретить прерывания mov ax, KERNEL_OFFSET mov ss, ax mov sp, ax mov ax, KERNEL_SEG_BASE ; Заносим текуший адрес в AX mov ds, ax mov es, ax sti ; разрешить прерывания ; Скрыть курсор ; mov ah,01h ; уст. размер/форму курсора (текст). ; mov ch,20h ; подавить курсор ; int 10h ; Открыть адресную линию A20 (чтобы была доступна вся память). in al,0x92 ; Читаем содержимое порта 0х92 or al,2 ; Устанавливаем второй бит out 0x92,al ; Записываем обратно в порт 0х92 m_init_gdt GDT ; Подготавливаем глобальную таблицу дескрипторов и загружаем регистр GDTR ; Запрет всех прерываний cli ; Запретить аппаратные прерывания ; запрет NMI in al, 70h or al, 80h out 70h, al ; Переключаемся в защищенный режим. mov eax, cr0 or al, 1 ; устанавливаем 0-вой бит mov cr0, eax ; включаем PM ; Мы в защищенном режиме! jmp fword SL_CODE:Startup32 ; прыгаем в PM. ;--Данные---------------------------------------------------------------------------------------------------------- ; Глобальная таблица дескрипторов align 8 ; Процессор быстрее обращается с выравненной табличкой GDT: rb 5*8 ; Резервируем место под 5 дескрипторов (один дескриптор = 8 байт), максимум 8192 дескриптора ;---------------------32 БИТНАЯ СЕКЦИЯ--------------------------------------------------------------------------------- ;\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ ;---------------------------------------------------------------------------------------------------------------------- use32 org KERNEL_BASE+$ include "inc/sysmacro.inc" include "int.inc" ; Работа с прерываниями include "drivers/tty.inc" ; Драйвер терминала tty include "inc/convert.inc" Startup32: ; Точка входа в защащенный режим ;-----Инициализация----- init32: ; Инициализируем сегментные регистры, помещая в них селекторы mov ax, SL_DATA ; Сегмент данных mov ds, ax ; ds = SELECTOR_DATA mov fs, ax ; fs = SELECTOR_DATA mov ax, SL_STACK ; сегмент стека mov ss, ax ; ss = SELECTOR_STACK mov esp, KERNEL_BASE ; Стек start: InitInterrupts ; Подготавливаем таблицу векторов прерываний, ; загружаем регистр IDTR и разрешаем все прерывания ttyInit SL_VIDEO ttySetColor CL_BLACK, CL_WHITE ttyClear ttyPrints os_str ; печать строки .while: call tty_get_char ttyPrintc al jmp .while jmp $; бесконечное ожидание прерываний... ;--------Данные------------------------------------------------------------------------------------- os_str db "Operating System VaraniaOS, Version 0.35", 13, 10, "Copyright by Krasov V.A.", 13, 10, 0 buff db 255 dup(0) i db 0 ;------Заполнитель----------- times 16384 - ($-$$) db 0 ; $ = адрес текущей строки ; $$ = адрес 1-й инструкции |
Автор: | SII [ 25 май 2019, 03:34 ] |
Заголовок сообщения: | Re: Страничная адресация на практике |
FreeProger писал(а): Помогите разобраться со страничной адресацией. Принцип её работы я вроде понял, а вот как на практике прикрутить её к своему ядру, додуматься не получается. 1) Когда её лучше включать, до перехода в PM или после? 2) Где лучше в памяти разместить каталог с таблицами? 3) Допустим мое ядро весит 16384 байт получается я должен описать 4 таблицы по 4 КБ? 1) Страничная адресация возможна только в защищённом режиме, соответственно, до перехода в него Вы её включить попросту не сможете. 2) Без разницы, лишь бы память была реально свободна (часть ОЗУ используется тем, что традиционно именуется BIOS, поэтому нельзя полагаться на то, что те или иные адреса свободны, надо запросить у этого самого BIOSа перечень занятых областей как в нижней памяти -- до 640К включительно, так и в верхней -- от 1М и выше). 3) Ага, только описываются не только страницы, но и сущности более высокого уровня. В IA-32, если память не изменяет (этой архитектурой я много лет не занимаюсь, так что и подробностей не помню), в зависимости от разрядности адреса и установленных режимов таблицы переадресации имеют 2, 3 или 4 уровня иерархии. Если предположить, что используется 2-уровневая иерархия (для 32-разрядного физического адреса больше и не требуется), всего нужно заполнить две таблицы. В таблице верхнего уровня (не помню, как она называется в IA-32), чей адрес передаётся процессору в соответствующем регистре, заполняется один элемент, описывающий таблицу нижнего уровня -- т.е. таблицу страниц, а остальные элементы помечаются как недоступные для использования (чтобы при попытке обращения по соответствующим адресам возникало прерывание), а в единственной (в данном случае) таблице страниц -- четыре элемента, описывающих область физической памяти, выделенной для "ядра"; остальные элементы тоже должны быть помечены как недоступные для использования. FreeProger писал(а): Но я не могу понять какие у страниц должны быть базовые физические адреса, такие же как у ядра? Ведь ядро должно как то в них попасть. И потом какой должна быть директива ORG после включения страничной адресации, если я задам виртуальные адреса страниц от нуля то ORG = 0 ? Ну, вообще-то виртуальная память изобретена как раз для того, чтобы виртуальные (логические) адреса, которыми оперирует программа, могли не совпадать с физическими (реальными, абсолютными) адресами ячеек памяти. Совпадение виртуальных и физических адресов -- это частный случай. |
Автор: | abondarev [ 25 май 2019, 12:49 ] |
Заголовок сообщения: | Re: Страничная адресация на практике |
Цитата: Но я не могу понять какие у страниц должны быть базовые физические адреса, такие же как у ядра? Ведь ядро должно как то в них попасть. И потом какой должна быть директива ORG после включения страничной адресации, если я задам виртуальные адреса страниц от нуля то ORG = 0 ? обычно для перехода в режим трансляции адресов используется простой прыжок со смещением. Вы можете замепировать свое ядро один к одному и тогда прыжка не требуется. Но эти адреса могут пересекаться с аржесным пространством других процессов. Обычно ядро мепируется отображается) на какие нибудь старшие адреса. например 0xc0000000 физическая память лежит к примеру 0x40000000 тогда замепируйте ядро по адресу 0xc0000000. После включения mmu (код должен быть также замепирован один к одному), делается прыжок со смешением, и вы оказываетесь в виртуальных ардресах. конечно ядро должно быть собрано в позиционно независимом коде. |
Автор: | FreeProger [ 25 май 2019, 15:48 ] |
Заголовок сообщения: | Re: Страничная адресация на практике |
Спасибо. Буду пробовать. |
Автор: | FreeProger [ 26 май 2019, 13:48 ] |
Заголовок сообщения: | Re: Страничная адресация на практике |
Вот набросал код переводящий процессор в PM, пытаюсь реализовать страничную адресацию. Помогите, с проецировать физический адрес видео буфера 0xB8000 в виртуальный. Код: format Binary as "bin"
use16 ; 16-ти битный код SEG_P equ 1000000000000000b ; Бит присутствия SEG_DPL_0 equ 0000000000000000b ; Уровень привелегий - 0 (наивысший) SEG_DPL_1 equ 0010000000000000b ; Уровень привелегий - 1 SEG_DPL_2 equ 0100000000000000b ; Уровень привелегий - 2 SEG_DPL_3 equ 0110000000000000b ; Уровень привелегий - 3 (низший) SEG_DATA_R equ 0001000000000000b ; Сегмент данных, только считывание SEG_DATA_RW equ 0001001000000000b ; Сегмент данных, считывание и запись SEG_STACK_R equ 0001010000000000b ; Сегмент стека, только считывание SEG_STACK_RW equ 0001011000000000b ; Сегмент стека, считывание и запись SEG_CODE_X equ 0001100000000000b ; Сегмент кода, только выполнение SEG_CODE_RX equ 0001101000000000b ; Сегмент кода, считывание и выполнение SEG_P_CODE_X equ 0001110000000000b ; Подчиненный сегмент кода, только выполнение SEG_P_CODE_RW equ 0001111000000000b ; Подчиненный сегмент кода, только выполнение и считывание SEG_G equ 0000000010000000b ; Гранулярность. 1 - 4КБ, 0 - 1 байт SEG_32 equ 0000000001000000b ; Битность кода в сегменте. 1 - 32 бита, 0 - 16 бит SL_CODE equ 08 ; Селектор сегмента кода (1-ый дескриптор в GDT) SL_STACK equ 16 ; Селектор сегмента стека (2-ый дескриптор в GDT) SL_DATA equ 24 ; Селектор сегмента данных (3-ий дескриптор в GDT) SL_VIDEO equ 32 ; Селектор сегмента видео-памяти (4-ий дескриптор в GDT) ; Описание регистра CR3. Старшие 20 бит это старшие разряды физического базового адреса каталога страниц, ; по скольку страница должна быть выровняна на 4 кб, младшие 12 разрядов считаются равными 0. ; Затем с лева на право, 7 бит резерв, 1 бит PCD (Запрет кэша уровня страниц), 1 бит PWT (Прозрачная запись в таблицы страниц). ; И младшие 0-2 биты сам не знаю что... Получаем 0b00000000000000000000 0000000 00 000 CR3_REG equ 00000000000000000001000000000000b ; Адрес каталога страниц 0x1000, атрибуты 0 ; Описание первого дескриптора таблиц в каталоге таблиц страниц, с лева на право ; 20 бит - начальный физический адрес таблицы страниц PTE ; 3 бита - Не используются, Можно задействовать в личных целях ; 1 бит - Global page. В каталоге таблиц страниц бит игнорируется. ; 1 бит - Page size. Бит задает размер страниц в каталоге. ; 1 бит - Reserved ; 1 бит - Accessed. Этот бит показывает был ли произведен доступ к каталогу ; 1 бит - Cache disable. Если бит выставлен, то кеширование страниц каталога запрещено. ; 1 бит - Write-throung. Включение, отключение сквозной записи ; 1 бит - User/Supervisor. Бит разрешает пользоваться страницами каталога обычным приложениям. ; 1 бит - Read/Write. Этот бит показывает, доступны ли данные в каталоге страницы для записи. ; 1 бит - Present. Если 0, то каталог не отображен на физическую память. PDE_0 equ 00000000000000000010000000000001b ; Адрес таблицы страниц 0x2000, атрибуты 0 ; Описание первого дескриптора страницы в каталоге страниц, с лева на право ; 20 бит - начальный физический адрес страницы ; 3 бита - Не используются, Можно задействовать в личных целях ; 1 бит - Global page. Когда бит выставлен, страница является глобальной. ; 1 бит - Page size. Бит задает размер страницы ; 1 бит - Dirty. Тоже самое что и бит A но устанавливается всякий раз при записи на страницу ; 1 бит - Accessed. Этот бит показывает был ли произведен доступ к странице ; 1 бит - Cache disable. Если бит выставлен, то кеширование страницы запрещено. ; 1 бит - Write-throung. Включение, отключение сквозной записи ; 1 бит - User/Supervisor. Бит разрешает пользоваться страницей обычным приложениям. ; 1 бит - Read/Write. Этот бит показывает, доступны ли данные в странице для записи. ; 1 бит - Present. Если 0, то страница не отображена на физическую память. PTE_0 equ 00000000000000001011000000000001b ; Используем смещение для расчёта меток программы org 0x7C00 jmp start ; Макрос добавления дескриптора в глобальную таблицу дескрипторов ; gdt_address - Адрес таблицы ; des_number - Номер дескриптора ; seg_base - Адрес базы сегмента ; seg_size - Размер сегмента ; attr - Бит присутствия, уровень привелегий, тип сегмента, гранулярность, ; разрядность кода в сегменте, macro m_add_desc_to_gdt gdt_address, des_number, seg_base, seg_size, attr { pushad mov esi,gdt_address mov edi,des_number mov ebx,seg_base ; 32 битный адрес базы сегмента mov edx,seg_size ; 20 битный размер сегмента mov cx,attr call add_desc_to_gdt popad } ; Подпрограмма добавления дескриптора в глобальную таблицу дескрипторов add_desc_to_gdt: mov word [esi + 8 * edi+2], bx ; base_l. Записываем младшую часть базы, 2 байта shr ebx, 16 ; Сдвигаем среднюю и старшую часть базы в регистр AX mov byte [esi + 8 * edi+4], bl ; base_m. Записываем среднюю часть базы, 1 байт mov byte [esi + 8 * edi+7], bh ; base_h. Записываем старшую часть базы, 1 байт dec edx mov word [esi + 8 * edi], dx ; size_l Записываем младшую часть размера, 2 байта shl edx, 12 ; Стираем 12 бит в старшей части регистра EAX, ; так как мы используем только 4 из 16 бит старшей части. Остольное должно быть = 0, shr edx, 12 ; что бы при сложении размера с атрибутами не было неверных данных shr edx, 16 ; Сдвигаем старшую часть размера в AX, теперь в al младшие 4 бита это старшая часть размера, ; остальные биты после стирания = 0 add dx, cx ; Добавим атрибуты к адресу (первый байт атрибутов содержит P,DPL,S,T,U. Второй быйт G,DB) rol dx, 8 ; Меняем местами байты, чтобы в начале записалсь P,DPL,S,T,U а затем G,DB mov word [esi + 8 * edi+5], dx ; Запишем 2 байта атрибутов ret disk_id db ? ; диск с которого произведена загрузка start: ; Инициализация сегментных регистров cli ; Запретить прерывания для смены адресов в сегментных регистрах ; cs=0 xor ax, ax ; ах = 0 mov ss, ax ; ss = 0 (Сегмент стека) mov sp,0x7C00 ; Указатель стека push ax pop es ; es = 0 (Дополнительный сегмент данных) push ax pop ds ; ds = 0 (Сегмент данных) sti ; Разрешить прерывания (после изменения адресов) mov [disk_id],dl ; Очистка экрана 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 0x7E00, 0, 0, 0, 0 ; Пустой m_add_desc_to_gdt 0x7E00, 1, 0, 0FFFFFh, SEG_P+SEG_CODE_X+SEG_G+SEG_32 ; Дескриптор кода m_add_desc_to_gdt 0x7E00, 2, 0x7C00, 512, SEG_P+SEG_STACK_RW+SEG_32 ; Дескриптор стека m_add_desc_to_gdt 0x7E00, 3, 0, 0FFFFFh, SEG_P+SEG_DATA_RW+SEG_G+SEG_32 ; Дескриптор данных m_add_desc_to_gdt 0x7E00, 4, 0B8000h, 4096, SEG_P+SEG_DATA_RW+SEG_G+SEG_32 ; Дескриптор видеопамяти ; Заняли 40 байт 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 ;Описание глобальной таблицы дескрипторов gdtr: .size dw (5*8)-1 ; Размер таблицы в байтах. 5 дескрипторов по 8 байт, минус один байт .addres dd 0x7E00 ; Физический адрес таблицы, сразу после загрузчика ; ==================================================================================================================================== use32 start32: ; Инициализируем сегментные регистры, помещая в них селекторы mov ax, SL_DATA ; Сегмент данных mov ds, ax ; ds = SELECTOR_DATA mov fs, ax ; fs = SELECTOR_DATA mov ax, SL_STACK ; сегмент стека mov ss, ax ; ss = SELECTOR_STACK mov esp, 0x7C00 ; Стек mov ax,SL_VIDEO mov gs,ax mov dword [0x1000],PDE_0 mov dword [0x2000],PTE_0 mov eax,CR3_REG mov cr3,eax jmp page page: 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 ; ===================================================================================================================================== ;-----Заполнитель----- ; Заполняем оставшееся место до 510 байт нулями times 510 - ($ - $$) db 0 ; $ = адрес текущей инструкции ; $$ = адрес 1-й инструкции ;Последние два байти 511-тый и 512-тый dw 0xAA55 ; сигнатура загрузочного сектора |
Автор: | FreeProger [ 26 май 2019, 14:43 ] |
Заголовок сообщения: | Re: Страничная адресация на практике |
И еще не пойму почему этот код работает. Ведь после загрузки cr3 должна включиться страничная адресация. Но я не описал страницы для этого кода. Разве всё что идёт после загрузки cr3 не должно быть расположено в каких то страницах? И что происходит с GDT и сегментными регистрами с загруженными в них селекторами, после включения страничной адресации, они становиться не нужны? |
Автор: | FreeProger [ 26 май 2019, 14:55 ] |
Заголовок сообщения: | Re: Страничная адресация на практике |
Оказывается для включения страничной адресации не достаточно было загрузить каталог таблиц страниц в CR3, нужно было после этого изменить регистр CR0: Код: ; включить страничную адресацию mov eax,cr0 or eax,80000000h mov cr0,eax Теперь всё в порядке, код перестал работать ) |
Автор: | FreeProger [ 26 май 2019, 15:54 ] |
Заголовок сообщения: | Re: Страничная адресация на практике |
Сделал так. Загружаю ядро по физическому адресу 0х10000, создаю каталог таблиц страниц по адресу 0x11000, в первом дескрипторе (PDE) записываю адрес первой таблицы страниц 0х12000. В первой таблице страниц описываю дескриптор на страницу (PTE) ссылающийся на физический адрес 0х10000 в котором расположено ядро. Но не работает не чего Без включения MMU всё работает. Код с ядром: Код: format Binary as "bin"
use16 ; 16-ти битный код org 0 jmp start include "gdtr.inc" CR3_REG equ 00000000000000010001000000000000b ; Адрес каталога страниц 0x11000 PDE_0 equ 00000000000000000010000000000001b ; Адрес таблицы страниц 0x12000 PTE_0 equ 00000000000000010000000000000001b ; Страница для кода 0x10000 PTE_1 equ 00000000000000001011000000000001b ; Страница видео буфера 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, 0x10000, 512, SEG_P+SEG_STACK_RW+SEG_32 ; Дескриптор стека m_add_desc_to_gdt GDT, 3, 0, 0FFFFFh, SEG_P+SEG_DATA_RW+SEG_G+SEG_32 ; Дескриптор данных m_add_desc_to_gdt GDT, 4, 0B8000h, 4096, SEG_P+SEG_DATA_RW+SEG_G+SEG_32 ; Дескриптор видеопамяти ; Заняли 40 байт 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 5*8 ; Резервируем место под 5 дескрипторов (один дескриптор = 8 байт), максимум 8192 дескриптора ;Описание глобальной таблицы дескрипторов gdtr: .size dw (5*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_STACK ; сегмент стека mov ss, ax ; ss = SELECTOR_STACK mov esp, 0x10000 ; Стек mov ax,SL_VIDEO mov gs,ax mov dword [0x11000],PDE_0 ; Каталог таблиц страниц mov dword [0x12000],PTE_0 ; Первый дескриптор страницы с ядром mov dword [0x12004],PTE_1 ; Второй дескриптор страницы видеопамяти mov eax,CR3_REG mov cr3,eax ; включить страничную адресацию mov eax,cr0 or eax,80000000h mov cr0,eax jmp page page: 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 ; ===================================================================================================================================== ;-----Заполнитель----- ; Заполняем оставшееся место до 510 байт нулями times 512 - ($ - $$) db 0 ; $ = адрес текущей инструкции ; $$ = адрес 1-й инструкции |
Автор: | FreeProger [ 26 май 2019, 18:20 ] |
Заголовок сообщения: | Re: Страничная адресация на практике |
Ни чего не получается. Уже запутался совсем. Почему не работает ? Код: use32
org 0x10000+$ start32: ; Инициализируем сегментные регистры, помещая в них селекторы mov ax, SL_DATA ; Сегмент данных mov ds, ax ; ds = SELECTOR_DATA mov fs, ax ; fs = SELECTOR_DATA mov ax, SL_STACK ; сегмент стека mov ss, ax ; ss = SELECTOR_STACK mov esp, 0x10000 ; Стек mov ax,SL_VIDEO mov gs,ax mov dword [0x11000],00000000000000010010000000000001b ; Адрес таблицы страниц 0x12000 mov dword [0x12000],00000000000000010000000000000001b ; Страница для кода 0x10000 mov dword [0x12004],00000000000010111000000000000001b ; Страница видео буфера 0xB8000 mov eax,00000000000000010001000000000000b ; Адрес каталога страниц 0x11000 mov cr3,eax ; включить страничную адресацию mov eax,cr0 or eax,80000000h mov cr0,eax page: mov esi,string ; Вывести сообщение из PM call print jmp $ ; ESI - адрес строки print: pushad xor ebx,ebx mov ah,07h puts: mov al,[esi+ebx] mov [0x1000+(ebx*2)],ax inc ebx test al,al jnz puts popad ret string db "Protected Mode - Enable", 0 |
Автор: | Himik [ 26 май 2019, 21:02 ] |
Заголовок сообщения: | Re: Страничная адресация на практике |
Ошибку не нашёл. Может быть проблема в стеке, т.к. он находится в другом блоке, который ты не отображаешь. И в сущности, не надо для стека делать отдельный сегмент, лучше STACK установить как DATA, чтобы адресация совпадала. Это нужно будет для локальных переменных в стеке. |
Страница 1 из 4 | Часовой пояс: UTC + 3 часа |
Powered by phpBB® Forum Software © phpBB Group http://www.phpbb.com/ |