OSDev

для всех
Текущее время: 29 мар 2024, 09:41

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




Начать новую тему Ответить на тему  [ Сообщений: 34 ]  На страницу 1, 2, 3, 4  След.
Автор Сообщение
 Заголовок сообщения: Страничная адресация на практике
СообщениеДобавлено: 24 май 2019, 20:41 

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


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

Зарегистрирован: 28 окт 2007, 18:33
Сообщения: 1418
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 ?


Ну, вообще-то виртуальная память изобретена как раз для того, чтобы виртуальные (логические) адреса, которыми оперирует программа, могли не совпадать с физическими (реальными, абсолютными) адресами ячеек памяти. Совпадение виртуальных и физических адресов -- это частный случай.


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

Зарегистрирован: 16 апр 2019, 17:15
Сообщения: 11
Цитата:
Но я не могу понять какие у страниц должны быть базовые физические адреса, такие же как у ядра? Ведь ядро должно как то в них попасть. И потом какой должна быть директива ORG после включения страничной адресации, если я задам виртуальные адреса страниц от нуля то ORG = 0 ?


обычно для перехода в режим трансляции адресов используется простой прыжок со смещением. Вы можете замепировать свое ядро один к одному и тогда прыжка не требуется. Но эти адреса могут пересекаться с аржесным пространством других процессов. Обычно ядро мепируется отображается) на какие нибудь старшие адреса. например 0xc0000000 физическая память лежит к примеру 0x40000000 тогда замепируйте ядро по адресу 0xc0000000. После включения mmu (код должен быть также замепирован один к одному), делается прыжок со смешением, и вы оказываетесь в виртуальных ардресах. конечно ядро должно быть собрано в позиционно независимом коде.


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

Зарегистрирован: 22 май 2019, 12:08
Сообщения: 34
Спасибо. Буду пробовать.


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

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


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

Зарегистрирован: 22 май 2019, 12:08
Сообщения: 34
И еще не пойму почему этот код работает. Ведь после загрузки cr3 должна включиться страничная адресация. Но я не описал страницы для этого кода. Разве всё что идёт после загрузки cr3 не должно быть расположено в каких то страницах? И что происходит с GDT и сегментными регистрами с загруженными в них селекторами, после включения страничной адресации, они становиться не нужны?


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

Зарегистрирован: 22 май 2019, 12:08
Сообщения: 34
Оказывается для включения страничной адресации не достаточно было загрузить каталог таблиц страниц в CR3, нужно было после этого изменить регистр CR0:
Код:
  ;  включить страничную адресацию
  mov eax,cr0
  or    eax,80000000h
  mov cr0,eax

Теперь всё в порядке, код перестал работать )


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

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


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

Зарегистрирован: 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_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


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

Зарегистрирован: 21 сен 2007, 17:24
Сообщения: 1088
Откуда: Балаково
Ошибку не нашёл. Может быть проблема в стеке, т.к. он находится в другом блоке, который ты не отображаешь.
И в сущности, не надо для стека делать отдельный сегмент, лучше STACK установить как DATA, чтобы адресация совпадала. Это нужно будет для локальных переменных в стеке.


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

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


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

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


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

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