Я делаю кастомный загрузчик, и в данный момент на стадии включения подкачки после перехода в защищенный режим Я попытался проверить, используется ли весь диапазон памяти от 0x00000000 до 0xFFFFFFFF, чтобы убедиться, что мое ядро полностью контролирует память. Проверка выполняется путем копирования значения в адрес памяти и печати значения через видеопамять (0xB8000). Но диапазон адресов от 0xC0000000 до 0xFFFFFFFF всегда содержит 0x00 (если выполняется QEMU) или 0xFF (если выполняется на реальном оборудовании с помощью устаревшей загрузки).
Я искал причину последние 3 недели, но не смог найти четкого ответа. В результате поиска я обнаружил некоторые подсказки, такие как преобразование физического-виртуального адреса, режим ядра и пользовательский режим, MMU, зарезервированный диапазон аппаратной памяти.
- Это явление связано с физически-виртуальной трансляцией адресов.
Загрузчик находится в защищенном режиме, и подкачка не включена. Таким образом, адрес в коде, который является виртуальным (= линейным) адресом, переводится как 1: 1.
Виртуальный адрес: 0x12345678 -> Физический адрес: 0x12345678
Кажется, он не связан с конкретным диапазоном адресов, всегда содержащим 0x00 или 0xFF.
- Это явление связано с режимом ядра и режимом пользователя.
Было множество статей о режиме ядра и пользовательском режиме, особенно о Linux. Но мой загрузчик еще не включил подкачку.
Следовательно, не существует определенного правила, такого как
- диапазон пространства пользователя / ядра
ех)
Область памяти пользователя: от 0x00000000 до 0xBFFFFFFF
Область памяти ядра: от 0xC0000000 до 0xFFFFFFFF
- как будет отображаться виртуальная память
виртуальная память 0x00010000 -> 0xC0010000
- страницы
Теперь я понятия не имею, почему это происходит.
Почему диапазон памяти от 0xC0000000 до 0xFFFFFFFF всегда содержит 0x00 или 0xFF? (Описывая «всегда содержать 0x00 или 0xFF», потому что я не уверен,
- память недоступна
- память не доступна для записи
- память не читается
- так далее
)
Результат и коды приведены ниже.
■ BootLoader.asm
%include "MBR.asm"
%include "BootSector2.asm"
■ MBR.asm
[ORG 0x0000]
[BITS 16]
; ──────────────────────────────────────────────────
; EQU
; ──────────────────────────────────────────────────
MBRBaseAddress: equ 0x7C00
ReadSectorCount: equ 0x0001
; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
; Code Section
; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
SECTION .text
MBR:
; ──────────────────────────────────────────────────
; Initialize Registers
; ──────────────────────────────────────────────────
jmp 0x0000:(MBRBaseAddress + 0x0005) ; Initialize CS (Code Segment) Register / Absolute Far Jump / set cs = 0x0000, jump to 0x07C05 (0x7C00 + 0x0005)
mov ax, word 0x0000
mov ds, ax ; Initialize DS (Data Segment) Register
mov ss, ax ; Initialize SS (Stack Segment) Register
mov ax, word 0x1000
mov es, ax ; Initialize ES (Extra Segment) Register
mov ax, word 0xB800
mov fs, ax ; Initialize FS Register
mov ax, word 0x0000 ; Initialize AX (Accumulator) Register
mov bx, word 0x0000 ; Initialize BX (Base) Register
mov cx, word 0x0000 ; Initialize CX (Count) Register
mov dx, word 0x0000 ; Initialize DX (Data) Register
mov si, word 0x0000 ; Initialize SI (Source Index) Register
mov di, word 0x0000 ; Initialize DI (Destination Index) Register
mov sp, word 0xFFFE ; Initialize SP (Stack Pointer) Register
mov bp, word 0xFFFE ; Initialize BP (Base Pointer) Register
; ──────────────────────────────────────────────────
; Clear Screen
; ──────────────────────────────────────────────────
.Clear1Digit:
mov [fs:di], word 0x0A00 ; [0xB800:di] 0x00 / [0xB800:di + 1] 0x0A / 0 -> 0000 (Background Attribute) / A -> 1010 (Text Attribute)
add di, 2
cmp di, 2 * 80 * 25 ; Compare di to 2 * 80 * 25 (= 4000 = 0x0FA0)
jl .Clear1Digit
mov di, word 0x0000 ; Clear di
; ──────────────────────────────────────────────────
; Print String : Real Mode String
; ──────────────────────────────────────────────────
push RealModeString
push 0
call .PrintString
mov sp, bp
; ──────────────────────────────────────────────────
; Print String : Start Reading Sectors String
; ──────────────────────────────────────────────────
push StartReadingSectorsString
push 1 * 2 * 80
call .PrintString
mov sp, bp
; ──────────────────────────────────────────────────
; Read Sectors (via BIOS interrupt)
; ──────────────────────────────────────────────────
.ReadSectors:
mov si, word 0x0000 ; Initialize si (Read sector count)
mov al, 1 ; Initialize read sector count (1)
mov dl, byte 0x80 ; Initialize drive to read from (Hard Disk C:)
mov bx, word 0x0000 ; Offset to read to
mov ah, byte 0x02 ; BIOS interrupt : Read sector
.Read1Sector:
mov ch, byte [MBRBaseAddress + CylinderIndex] ; Set cylinder value to read from
mov dh, byte [MBRBaseAddress + HeadIndex] ; Set head value to read from
mov cl, byte [MBRBaseAddress + SectorIndex] ; Set sector value to read from
cmp si, ReadSectorCount ; Compare si to ReadSectorCount
jge .ReadSectorsEnd ; Jump to .ReadSectorsEnd if
int 0x13 ; Call BIOS interrupt
add si, 1
add cl, 1
mov [MBRBaseAddress + SectorIndex], cl
add bx, 512
jmp .Read1Sector
.ReadSectorsEnd:
; ──────────────────────────────────────────────────
; Print Value : Sectors Read Count
; ──────────────────────────────────────────────────
push si
push 2 * 2 * 80
call .PrintValue
mov sp, bp
; ──────────────────────────────────────────────────
; Print String : Sectors Read String
; ──────────────────────────────────────────────────
push SectorsReadString
push (2 * 2 * 80) + (2 * 5)
call .PrintString
mov sp, bp
; ──────────────────────────────────────────────────
; Switch to Protected Mode
; ──────────────────────────────────────────────────
cli
lgdt [MBRBaseAddress + GDT]
;mov eax, dword 0x4000003B
mov eax, cr0
or al, 1
mov cr0, eax
jmp dword 0x0008:0x00010000
; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
; Functions
; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
; ──────────────────────────────────────────────────
; Print Value
; ──────────────────────────────────────────────────
.PrintValue:
push bp ; Copy current bp to memory whose address is current sp
mov bp, sp ; Set new bp by current sp
mov cl, byte 12 ; Initialize cl (Shift right count)
mov di, [bp + 4] ; Initialize di (2nd argument / Video memory offset where to print)
.PrintValueLoop:
mov si, [bp + 6] ; Copy 1st argument (Value to print) to si
shr si, cl ; Shift right si cl times
and si, word 0x000F ; Keep last 4 bits and discard (fill) other bytes to 0
mov bl, byte [MBRBaseAddress + ASCIIString + si] ; Copy ASCII value, corresponding to si, to bl
mov [fs:di], bl ; [0xB800:di] bl / Copy 1 character to video memory
sub cl, 4
add di, 2
cmp cl, 0
jg .PrintValueLoop
mov si, [bp + 6] ; Copy 1st argument (Value to print) to si
and si, word 0x000F ; Keep last 4 bits and discard (fill) other bytes to 0
mov bl, byte [MBRBaseAddress + ASCIIString + si] ; Copy ASCII value, corresponding to si, to bl
mov [fs:di], bl ; [0xB800:di] bl / Copy 1 character to video memory
.PrintValueEnd:
pop bp ; Copy memory whose address is current sp to bp
ret
; ──────────────────────────────────────────────────
; Print String
; ──────────────────────────────────────────────────
.PrintString:
push bp ; Copy current bp to memory whose address is current sp
mov bp, sp ; Set new bp by current sp
mov bx, word [bp + 6] ; Initialize bx (1st argument / String offset)
mov si, 0 ; Initialize si (String index)
mov di, word [bp + 4] ; Initialize di (2nd argument / Video memory offset where to print)
.PrintStringLoop:
mov cl, byte [MBRBaseAddress + bx + si] ; Copy 1 character from memory (MBRBaseAddress + String offset + String index) to cl
cmp cl, 0 ; Compare cl to 0
je .PrintStringEnd
mov [fs:di], cl ; [0xB800:di] cl / Copy 1 character to video memory
add si, 1
add di, 2
jmp .PrintStringLoop
.PrintStringEnd:
pop bp ; Copy memory whose address is current sp to bp
ret
; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
; Data (Read Only)
; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
; ──────────────────────────────────────────────────
; ASCII String
; ──────────────────────────────────────────────────
ASCIIString:
db '0123456789ABCDEF', 0
; ──────────────────────────────────────────────────
; Strings
; ──────────────────────────────────────────────────
RealModeString:
db '[Current Mode : Real Mode]', 0
StartReadingSectorsString:
db 'Start Reading Sectors', 0
SectorsReadString:
db 'Sectors Read', 0
; ──────────────────────────────────────────────────
; Cylinder, Head, Sector Index
; ──────────────────────────────────────────────────
CylinderIndex:
db 0x00
HeadIndex:
db 0x00
SectorIndex:
db 0x02
; ──────────────────────────────────────────────────
; GDT (Global Descriptor Table)
; ──────────────────────────────────────────────────
GDTStart:
GDTNullDescriptor:
dq 0x0000000000000000
GDTCodeDescriptor:
dw 0xFFFF
dw 0x0000
db 0x00
db 0x9A
db 0xCF
db 0x00
GDTDataDescriptor:
dw 0xFFFF
dw 0x0000
db 0x00
db 0x92
db 0xCF
db 0x00
GDTEnd:
GDT:
dw GDTEnd - GDTStart
dd MBRBaseAddress + GDTStart
; ──────────────────────────────────────────────────
; Declare Zeros
; ──────────────────────────────────────────────────
times 510 - ($ - $$) db 0x00
; ──────────────────────────────────────────────────
; Boot Signature
; ──────────────────────────────────────────────────
dw 0xAA55
■ BootSector2.asm
[BITS 32]
; ──────────────────────────────────────────────────
; EQU
; ──────────────────────────────────────────────────
BootSector2BaseOffset: equ 0x0000FE00 ; ※ 0x00010000 (Read sector address) - 0x00000200 (Initial label offset) = 0x0000FE00 in order to use label as if it begins from 0x00000000 [ex) BootSector2Offset (0x0000FE00) + LABEL (0x000002XX) = 0x000100XX]
VideoMemory: equ 0x000B8000
BootSector2:
mov ax, word 0x0010
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
mov eax, dword 0x000B8000
mov ebx, dword 0x00000000
mov cl, 28
mov esi, dword 0x00000000
mov edi, dword VideoMemory + (3 * 2 * 80)
mov esp, dword 0xFFFC0004;0xBFFFFFFC;0xC0000000 + 0x00010000 + 0x000000E4
mov ebp, dword 0xFFFC0004;0xBFFFFFFC;0xC0000000 + 0x00010000 + 0x000000E4
.Loop1:
mov esi, esp
shr esi, cl
and esi, dword 0x0000000F
mov bl, byte [MBRBaseAddress + ASCIIString + esi]
mov [edi], bl
sub cl, 4
add edi, 2
cmp cl, 0
jg .Loop1
mov esi, esp
and esi, dword 0x0000000F
mov bl, byte [MBRBaseAddress + ASCIIString + esi]
mov [edi], bl
mov edi, dword VideoMemory + (4 * 2 * 80)
push dword 0xABCD1234
mov cl, 28
.Loop2:
mov esi, esp
shr esi, cl
and esi, dword 0x0000000F
mov bl, byte [MBRBaseAddress + ASCIIString + esi]
mov [edi], bl
sub cl, 4
add edi, 2
cmp cl, 0
jg .Loop2
mov esi, esp
and esi, dword 0x0000000F
mov bl, byte [MBRBaseAddress + ASCIIString + esi]
mov [edi], bl
mov edi, dword VideoMemory + (5 * 2 * 80)
mov cl, 28
.Loop3:
mov esi, dword [0xFFFC0000]
shr esi, cl
and esi, dword 0x0000000F
mov bl, byte [MBRBaseAddress + ASCIIString + esi]
mov [edi], bl
sub cl, 4
add edi, 2
cmp cl, 0
jg .Loop3
mov esi, dword [0xFFFC0000]
and esi, dword 0x0000000F
mov bl, byte [MBRBaseAddress + ASCIIString + esi]
mov [edi], bl
jmp $
; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
; Data (Read Only)
; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
ProtectedModeString:
db '[Current Mode : Protected Mode]', 0
SampleValue:
dd 0x12345678
times 1024 - ($ - $$) db 0x00
введите описание изображения здесь
введите описание изображения здесь
введите описание изображения здесь
введите описание изображения здесь