OSDev

для всех
Текущее время: 28 мар 2024, 12:52

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 34 ]  На страницу Пред.  1, 2, 3, 4  След.
Автор Сообщение
СообщениеДобавлено: 26 май 2019, 22:09 

Зарегистрирован: 22 май 2019, 12:08
Сообщения: 34
Переделал так. Не работает
Код:
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:39, всего редактировалось 1 раз.

Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 26 май 2019, 22:45 

Зарегистрирован: 22 май 2019, 12:08
Сообщения: 34
Полный код ядра:
Код:
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-й инструкции
                         
                         
                         


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 27 май 2019, 10:19 

Зарегистрирован: 22 май 2019, 12:08
Сообщения: 34
Кто подскажет в правильном ли я направлении двигаюсь. Я хочу создать таблицы страниц адрес в адрес. То есть виртуальные адреса должны совпадать с физическими. Понимаю что особого толку в этом нет. Но хочу хотя бы включить страничную адресацию без сбоев процессора.
Я думаю что для этого необходимо описать 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 виртуальные адреса
Ядра должны совпать с физическими


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 27 май 2019, 11:09 

Зарегистрирован: 22 май 2019, 12:08
Сообщения: 34
Наконец что то получилось. Я не стал описывать 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-й инструкции
 


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 27 май 2019, 11:33 

Зарегистрирован: 22 май 2019, 12:08
Сообщения: 34
А так я изменил виртуальный адрес видео буфера с 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



Последний раз редактировалось FreeProger 30 май 2019, 20:05, всего редактировалось 1 раз.

Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 27 май 2019, 23:33 

Зарегистрирован: 21 сен 2007, 17:24
Сообщения: 1088
Откуда: Балаково
Да, правильно. Есть ещё интересный фокус с таблицами. Как ты заметил, структура PDE и PTE в принципе одинакова. Что если в качестве дескриптора PTE указать адрес PDT? Тогда в адресном пространстве данной таблицы отобразятся все PTE.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 29 май 2019, 22:31 

Зарегистрирован: 22 май 2019, 12:08
Сообщения: 34
Himik писал(а):
Да, правильно. Есть ещё интересный фокус с таблицами. Как ты заметил, структура PDE и PTE в принципе одинакова. Что если в качестве дескриптора PTE указать адрес PDT? Тогда в адресном пространстве данной таблицы отобразятся все PTE.


Не совсем пойму как это сделать и что получится. Допустим мы заполнили каталог PDE дескрипторами. Нулевой дескриптор указывает на нулевую таблицу, в ней нулевой PTE
дескриптор указывает не на физ. адрес страницы а на виртуальный адрес PDE дескриптора, который перенаправит нас на другую таблицу и мы получим доступ к другой таблице через PTE дескриптор первой?


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 30 май 2019, 23:20 

Зарегистрирован: 21 сен 2007, 17:24
Сообщения: 1088
Откуда: Балаково
В директории таблиц, где-нибудь повыше (не с нуля), указываем физический адрес таблицы страниц. В качестве адреса таблицы указываем адрес самой директории таблиц (содержимое регистра CR3 плюс атрибут Present), которая на втором уровне будет интерпретироваться процессором как таблица страниц. В этом 4-мегабайтном виртуальном регионе будет отображаться содержание все существующих таблиц страниц. 4 мегабайта это общий размер всех таблиц для 4ГБ пространства. Таблицы отображаются линейным списком, хотя в физической памяти могут быть разбросаны хаотично.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 31 май 2019, 18:22 

Зарегистрирован: 22 май 2019, 12:08
Сообщения: 34
Теперь вроде понял. Спасибо, я даже не представляю где бы мог вычитать про такие фокусы. Совет со стеком тоже учел. Сейчас пытаюсь написать минимальный менеджер физической и логической памяти. Но трудно пока что сообразить в каком направлении двигаться, что он вообще должен делать. Думаю начать с менеджера физической памяти. 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 и видеобуфер.


Последний раз редактировалось FreeProger 31 май 2019, 22:57, всего редактировалось 1 раз.

Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 31 май 2019, 21:31 

Зарегистрирован: 21 сен 2007, 17:24
Сообщения: 1088
Откуда: Балаково
Да, можно пока сделать именно так, с помощью битовой карты. Как для физических, так и для виртуальных страниц. Битовая карта физических страниц должна размещаться в общей памяти, а карту виртуальной памяти нужно размещать в объекте каждой задачи. Каталог таблиц тоже должен размещаться в объекте задачи. Тоесть, надо начинать описывать структуру задачи.


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 34 ]  На страницу Пред.  1, 2, 3, 4  След.

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 3


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
cron
Создано на основе phpBB® Forum Software © phpBB Group
Русская поддержка phpBB