OSDev http://osdev.su/ |
|
Страничная адресация на практике http://osdev.su/viewtopic.php?f=6&t=3737 |
Страница 2 из 4 |
Автор: | FreeProger [ 26 май 2019, 22:09 ] |
Заголовок сообщения: | Re: Страничная адресация на практике |
Переделал так. Не работает Код: 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 ; Стек mov ax,SL_VIDEO mov gs,ax mov dword [0x11000],00000000000000010010000000000001b ; Адрес таблицы страниц 0x12000 mov dword [0x12000],00000000000000001111000000000001b ; Страница для стека 0xF0000 mov dword [0x12004],00000000000000010000000000000001b ; Страница для кода 0x10000 mov dword [0x12008],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 [0xB8000+(ebx*2)],ax inc ebx test al,al jnz puts popad ret string db "Protected Mode - Enable", 0 |
Автор: | FreeProger [ 26 май 2019, 22:45 ] |
Заголовок сообщения: | Re: Страничная адресация на практике |
Полный код ядра: Код: format Binary as "bin"
use16 ; 16-ти битный код org 0 jmp start include "gdtr.inc" SL_CODE equ 08 ; Селектор сегмента кода (1-ый дескриптор в GDT) SL_DATA equ 16 ; Селектор сегмента данных (3-ий дескриптор в GDT) SL_VIDEO equ 24 ; Селектор сегмента видео-памяти (4-ий дескриптор в 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 ; Дескриптор данных m_add_desc_to_gdt GDT, 3, 0B8000h, 4096, SEG_P+SEG_DATA_RW+SEG_G+SEG_32 ; Дескриптор видеопамяти ; Заняли 32 байт 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 4*8 ; Резервируем место под 5 дескрипторов (один дескриптор = 8 байт), максимум 8192 дескриптора ;Описание глобальной таблицы дескрипторов gdtr: .size dw (4*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 ; Стек mov ax,SL_VIDEO mov gs,ax mov dword [0x11000],00000000000000010010000000000001b ; Адрес таблицы страниц 0x12000 mov dword [0x12000],00000000000000001111000000000001b ; Страница для стека 0xF0000 mov dword [0x12004],00000000000000010000000000000001b ; Страница для кода 0x10000 mov dword [0x12008],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 ; ===================================================================================================================================== ;-----Заполнитель----- ; Заполняем оставшееся место до 510 байт нулями times 512 - ($ - $$) db 0 ; $ = адрес текущей инструкции ; $$ = адрес 1-й инструкции |
Автор: | FreeProger [ 27 май 2019, 10:19 ] |
Заголовок сообщения: | Re: Страничная адресация на практике |
Кто подскажет в правильном ли я направлении двигаюсь. Я хочу создать таблицы страниц адрес в адрес. То есть виртуальные адреса должны совпадать с физическими. Понимаю что особого толку в этом нет. Но хочу хотя бы включить страничную адресацию без сбоев процессора. Я думаю что для этого необходимо описать 4гб памяти, хранить каталог таблиц буду по адресу 0x11000, каталог будет содержать 1024 дескриптора PDE, указывающих на 1024 таблицы. Таким образом каталог займет адреса с 0x11000 по 0x12000. С 0x12000 адреса я буду хранить таблицы их будет 1024, в одной таблице будет содержаться 1024 дескриптора PTE описывающие 1024 страницы. Все таблицы займут адреса с 0x12000 по 0x412000 и опишут все 4гб. Алгоритм примерно такой: 1) Вписать по адресу 0x11000 дескриптор первой таблицы укащывающмй на адрес 0x12000 1.1) Вписать по адресу 0x12000 1024 дескрипторауказывающие на 1024 страницы, которые опишут одреса от 0 байт до 4194304 байт. 2) Увеличить адрес начала каталога таблиц на 4 байта, таким образом мы перейдем к адресу следующей таблицы. 2.1) Увеличить адрес таблицы на 0x1000, был 0x12000 станет 0x13000. 2.2) Описать по полученному адресу 1024 странмцы, от 4194305 байт до 8388608 И так повторять 1024 раза, пока не опишу 1024 таблицы по 1024 страницы. Таким образом после включения mmu виртуальные адреса Ядра должны совпать с физическими |
Автор: | FreeProger [ 27 май 2019, 11:09 ] |
Заголовок сообщения: | Re: Страничная адресация на практике |
Наконец что то получилось. Я не стал описывать 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-й инструкции |
Автор: | FreeProger [ 27 май 2019, 11:33 ] |
Заголовок сообщения: | Re: Страничная адресация на практике |
А так я изменил виртуальный адрес видео буфера с 0xB8000 на 0x0 Код: 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 eax,00000000000010111000000000000111b mov [0x12000],eax mov esi,string ; Вывести сообщение из PM call print jmp $ ; ESI - адрес строки print: pushad xor ebx,ebx mov ah,07h puts: mov al,[esi+ebx] mov [0x0+(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 |
Автор: | Himik [ 27 май 2019, 23:33 ] |
Заголовок сообщения: | Re: Страничная адресация на практике |
Да, правильно. Есть ещё интересный фокус с таблицами. Как ты заметил, структура PDE и PTE в принципе одинакова. Что если в качестве дескриптора PTE указать адрес PDT? Тогда в адресном пространстве данной таблицы отобразятся все PTE. |
Автор: | FreeProger [ 29 май 2019, 22:31 ] |
Заголовок сообщения: | Re: Страничная адресация на практике |
Himik писал(а): Да, правильно. Есть ещё интересный фокус с таблицами. Как ты заметил, структура PDE и PTE в принципе одинакова. Что если в качестве дескриптора PTE указать адрес PDT? Тогда в адресном пространстве данной таблицы отобразятся все PTE. Не совсем пойму как это сделать и что получится. Допустим мы заполнили каталог PDE дескрипторами. Нулевой дескриптор указывает на нулевую таблицу, в ней нулевой PTE дескриптор указывает не на физ. адрес страницы а на виртуальный адрес PDE дескриптора, который перенаправит нас на другую таблицу и мы получим доступ к другой таблице через PTE дескриптор первой? |
Автор: | Himik [ 30 май 2019, 23:20 ] |
Заголовок сообщения: | Re: Страничная адресация на практике |
В директории таблиц, где-нибудь повыше (не с нуля), указываем физический адрес таблицы страниц. В качестве адреса таблицы указываем адрес самой директории таблиц (содержимое регистра CR3 плюс атрибут Present), которая на втором уровне будет интерпретироваться процессором как таблица страниц. В этом 4-мегабайтном виртуальном регионе будет отображаться содержание все существующих таблиц страниц. 4 мегабайта это общий размер всех таблиц для 4ГБ пространства. Таблицы отображаются линейным списком, хотя в физической памяти могут быть разбросаны хаотично. |
Автор: | FreeProger [ 31 май 2019, 18:22 ] |
Заголовок сообщения: | Re: Страничная адресация на практике |
Теперь вроде понял. Спасибо, я даже не представляю где бы мог вычитать про такие фокусы. Совет со стеком тоже учел. Сейчас пытаюсь написать минимальный менеджер физической и логической памяти. Но трудно пока что сообразить в каком направлении двигаться, что он вообще должен делать. Думаю начать с менеджера физической памяти. BIOS будет при загрузке ядра передавать объём ОЗУ, менеджер памяти будет иметь битовый массив свободных/занятых страниц. Будут функции, инициализации менеджера, затем функция выделения свободной физической страницы, она будет проходить по всем битам в битовой карте и возвращать номер первого попавщегося нулевого бита. По номеру будет выясняться физический адрес страницы, он и будет возвращаться, а бит будет устанавливаться в единицу. При освобождении страницы передаётся её физический адрес, по нему определяется номер в битовой карте и бит сбрасывается. А вот как сделать выделения блока страниц не совсем пока понимаю. Допустим выделение будет происходить так: Передаем размер в страницах, ищется первая страница, заносится в массив, вторая и т.д. затем возвращается адрес массива. Ну и освобождение тоже толжно при этом быть хитрее. Или есть более нормальные методы? Вот прототип который я начал делать: Код: ; Аллокатор ОС Varania memory_size dd ? ; Размер физической памяти bitmap_all_pages rb 131072 ; 128КБ Битовая карта, описывает каждую физическую страницу, занята она или свободна ; Инициализация аллокатора init_allocator: ; Заполняем каталог таблиц страниц PDE дескрипторами mov eax,DIR_TABLES_PAGES ; Адрес каталога таблиц страниц mov esi,DIR_TABLES_PAGES+1000h ; Адрес первой таблицы mov edi,11b ; Атрибуты mov ecx,1024 ; Количество таблиц call create_desc ; Создать дескрипторы ; Заполняем таблицы PTE дескрипторами mov eax,DIR_TABLES_PAGES+1000h ; Адрес начала таблиц mov esi,0 ; Физический адрес первой страницы mov edi,11b ; Атрибуты mov ecx,1024 ; Количество страниц call create_desc ; Создать дескрипторы mov eax,DIR_TABLES_PAGES mov cr3,eax ; Включить страничную адресацию mov eax,cr0 or eax,80000000h mov cr0,eax ret ; Функция выделения одной физической страницы ; Возвращает физический адрес первой попавшейся свободной страницы, помечает ее как занятую alloc_page: mov eax, dword [bitmap_all_pages] mov ecx,1024 @@: ret ; Функция выделения нескольких физических страниц alloc_pages: ret ; Функция освобождения ранее выделенной физической страницы ; Принимает адрес страницы и помечает ее как свободную free_page: ret ; Создает каталог таблиц и запоняет его PDE дескрипторами ; EAX - адрес первого дескриптора ; ESI - физический адрес на который указывает дескриптор ; EDI - атрибуты ; ECX - колличество дескрипторов create_desc: pushad mov ebx,0 ; Номер дескриптора add esi,edi @@: mov [eax+ebx],esi ; Запишем дескриптор add ebx,4 ; Переход к следующему дескриптору shr esi,2 ; Перед сложением сотрем атрибуты shl esi,2 add esi,1000h ; Прибавляем адрес следующей таблицы и атрибуты add esi,edi loop @b popad ret Ещё нужно будет при инициализации пометить первый мегабайт как занятый. Что бы не затереть области BIOS и видеобуфер. |
Автор: | Himik [ 31 май 2019, 21:31 ] |
Заголовок сообщения: | Re: Страничная адресация на практике |
Да, можно пока сделать именно так, с помощью битовой карты. Как для физических, так и для виртуальных страниц. Битовая карта физических страниц должна размещаться в общей памяти, а карту виртуальной памяти нужно размещать в объекте каждой задачи. Каталог таблиц тоже должен размещаться в объекте задачи. Тоесть, надо начинать описывать структуру задачи. |
Страница 2 из 4 | Часовой пояс: UTC + 3 часа |
Powered by phpBB® Forum Software © phpBB Group http://www.phpbb.com/ |