Адресация в защищенном режиме

Я пробую учебники по разработке загрузчиков. Я могу читать загрузчик stage2, используя соглашения FAT12. Сейчас я пытаюсь загрузить ядро ​​в реальном режиме, а затем скопировать его по адресу 0x0100000.

Я получаю тройную ошибку при копировании + переход на 0x0100000. В основном я не могу понять, как получить доступ или перейти к 0x0100000.

Мой код работает, когда я использую

IMAGE_PMODE_BASE equ 0x1000
IMAGE_RMODE_BASE equ 0x1000

krnl32.bin: boot/kernel_entry.o ${OBJ}
    i386-elf-ld -o $@ -Ttext 0x01000 $^ --oformat binary

Что мне не хватает? Я читал о дескрипторе: смещение адресации в защищенном режиме, там написано: DESC: OFFSET(16 бит). Также смещение умножается на 4 КБ, используя настройку гранулярности в GDT.

Я настроил GDT, как это:

gdt_start: 
    dd 0                ; null descriptor
    dd 0 

; gdt code:             ; code descriptor
    dw 0FFFFh           ; limit low
    dw 0                ; base low
    db 0                ; base middle
    db 10011010b        ; access
    db 11001111b        ; granularity
    db 0                ; base high

; gdt data:             ; data descriptor
    dw 0FFFFh           ; limit low (Same as code)10:56 AM 7/8/2007
    dw 0                ; base low
    db 0                ; base middle
    db 10010010b        ; access
    db 11001111b        ; granularity
    db 0                ; base high

end_of_gdt:
toc: 
    dw end_of_gdt - gdt_start - 1   ; limit (Size of GDT)
    dd gdt_start            ; base of GDT

; give the descriptor offsets names

NULL_DESC equ 0
CODE_DESC equ 0x8
DATA_DESC equ 0x10

Я связываю ядро, как показано ниже:

krnl32.bin: boot/kernel_entry.o ${OBJ}
    i386-elf-ld -o $@ -Ttext 0x0100000 $^ --oformat binary

Стадия 2 загрузчик

[bits 16]
[org 0x500]

jmp main

%include "boot/stage2/print16.s"
%include "boot/stage2/print32.s"
%include "boot/stage2/floppy16_driver.s"
%include "boot/stage2/fat12.s"
%include "boot/stage2/gdt.s"
%include "boot/stage2/a20.s"

;*******************************************************
;   Data Section
;*******************************************************

msgFailure db 0x0D, 0x0A, "Failed", 0x00
welcomeMessage db 0x0D, 0x0A, "Landed in STAGE TWO...", 0x00
enableA20Msg db 0x0D, 0x0A, "Enabled A20. Installed GDT", 0x00
ImageName     db "KRNL32  BIN"
ImageSize     db 0
IMAGE_PMODE_BASE equ 0xffff
IMAGE_RMODE_BASE equ 0x1000


main:
    ;-------------------------------;
    ;   Setup segments and stack    ;
    ;-------------------------------;

    cli                    ; clear interrupts
    xor     ax, ax             ; null segments
    mov     ds, ax
    mov     es, ax
    mov     ax, 0x0000         ; stack begins at 0x9000-0xffff
    mov     ss, ax
    mov     sp, 0xFFFF
    sti                    ; enable interrupts

    mov si, welcomeMessage
    call Print16

    call    _EnableA20
    call    InstallGDT
    sti
    mov si, enableA20Msg
    call Print16

    call    LoadRoot
    mov     ebx, 0
    mov     ebp, IMAGE_RMODE_BASE
    mov     esi, ImageName
    call    LoadFile        ; load our file
    mov     dword [ImageSize], ecx
    cmp     ax, 0
    je      EnterStage3
    mov     si, msgFailure
    call    Print16
    mov     ah, 0
    int     0x16                    ; await keypress
    int     0x19                    ; warm boot computer

    jmp $;

EnterStage3:

    cli   
    mov eax, cr0
    or  eax, 1
    mov cr0, eax

    jmp CODE_DESC:Stage3           


[bits 32]
Stage3:
    mov ax, DATA_DESC       ; set data segments to data selector (0x10)
    mov ds, ax
    mov ss, ax
    mov es, ax
    mov esp, 90000h     ; stack begins from 90000h

CopyImage:
    mov eax, dword [ImageSize]
    movzx   ebx, word [bpbBytesPerSector]
    mul ebx
    mov ebx, 4
    div ebx
    cld
    mov    esi, IMAGE_RMODE_BASE
    mov edi, IMAGE_PMODE_BASE
    mov ecx, eax
    rep movsd                   ; copy image to its protected mode address
    jmp IMAGE_PMODE_BASE
    jmp $; 

1 ответ

Решение

Вы устанавливаете GDT, который имеет 32-битный дескриптор для кода и 32-битный дескриптор для данных. В защищенном режиме регистры CS/DS/ES/SS/FS/GS больше не являются сегментными регистрами в том смысле, в каком они были видны в реальном режиме. В защищенном режиме они содержат селектор, который указывает на запись в GDT (или LDT). Этот код загружает регистры данных:

mov ax, DATA_DESC       ; set data segments to data selector (0x10)
mov ds, ax
mov ss, ax
mov es, ax

Вы не можете установить регистр CS таким образом. FAR jmp может установить желаемый селектор кода и установить смещение в одной инструкции. Вот что делает эта инструкция:

jmp CODE_DESC:Stage3

Ваш GDT настроен с помощью дескрипторов кода и данных, которые представляют собой модель с 4 ГБ плоской памяти, где базовое значение равно 0x00000000, а ограничение равно 0xffffffff. Это означает, что один раз в защищенном режиме, и вы используете селекторы, которые указывают на эти дескрипторы, вы можете получить доступ ко всей памяти напрямую от 0x00000000 до 0xffffffff. Это означает, что все, что вам нужно сделать, это jmp 0x100000 перейти к адресу памяти 0x100000. В вашем коде вы захотите использовать 0x100000 как не только место для перехода, но и место памяти, которое ваша копия памяти использует в качестве своей базы.

Имея это в виду, простое решение состоит в том, чтобы изменить:

IMAGE_PMODE_BASE equ 0x1000

чтобы:

IMAGE_PMODE_BASE equ 0x100000
Другие вопросы по тегам