为什么在启用分页之前切换到保护模式后,地址范围0xC0000000〜0xFFFFFFFF总是给出0x00或0xFF?

时间:2019-06-27 03:56:26

标签: x86 nasm memory-address bootloader osdev

我正在制作一个自定义的引导加载程序,目前正处于切换到保护模式后启用分页的阶段。我试图检查所有可用内存范围(从0x00000000到0xFFFFFFFF),以确保我的内核可以完全控制内存。通过将值复制到存储器地址并通过视频存储器(0xB8000)打印该值来进行检查。但是,从0xC0000000到0xFFFFFFFF的地址范围始终包含0x00(如果由QEMU执行)或0xFF(如果是通过旧版引导在实际硬件中执行)。

过去3周,我一直在寻找原因,但是找不到明确的答案。通过搜索,我发现了一些线索,例如物理-虚拟地址转换,内核模式和用户模式,MMU,保留的硬件内存范围。

  • 该现象是由于物理-虚拟地址转换引起的。
      

    引导加载程序处于保护模式,并且未启用分页。因此,代码中的地址(即虚拟(=线性)地址)通过1:1映射进行翻译。

虚拟地址:0x12345678->物理地址:0x12345678

似乎与现象特别的地址范围始终包含0x00或0xFF无关。

  • 该现象是由于内核模式和用户模式引起的。
      

    关于内核模式和用户模式,特别是关于Linux的文章很多。但是我的引导加载程序尚未完成启用分页的操作。

因此,没有定义任何规则,例如 -用户/内核空间范围 例如) 用户存储空间:0x00000000至0xBFFFFFFF 内核内存空间:0xC0000000至0xFFFFFFFF -如何映射虚拟内存 虚拟内存0x00010000-> 0xC0010000 -页数

  • 此现象是由于MMU造成的

      

    似乎与翻译有关,与包含0x00或0xFF的特定内存范围无关。

  • 此现象是由于保留内存所致。

      

    我认为这很可能是主要原因,并通过BIOS中断0x15 eax 0xE820执行了内存检测。结果“不是”。   另外,请查看英特尔数据表。

现在,我不知道为什么会这样。

为什么从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

enter image description here

enter image description here

enter image description here

enter image description here

0 个答案:

没有答案