Obecnie gram z x86 Assember, aby wyostrzyć moje umiejętności programowania niskiego poziomu. Obecnie mam mały problem ze schematem adresowania w 32-bitowym trybie chronionym.Skok asemblera w trybie chronionym z GDT
Sytuacja jest następująca:
Mam program załadowany w 0x7e0 który przełącza procesor do trybu chronionego i przeskakuje do według etykiety w kodzie:
[...]
code to switch CPU in Protected Mode
[...]
jmp ProtectedMode
[...]
bits 32
ProtectedMode:
.halt:
hlt
jmp .halt
ten działa całkowicie w porządku tak daleko. "Jmp ProtectedMode" działa bez wyraźnego dalekiego przeskoku, aby usunąć kolejkę wstępnego pobierania - ponieważ program ten jest załadowany z przesunięciem 0 (org 0 na początku) - powodując segment kodu wskazujący właściwą lokalizację.
Mój obecny problem polega na tym, że w etykiecie "ProtectedMode" chcę przejść do innego programu, który jest ładowany pod 0x8000 (sprawdziłem to za pomocą zrzutu pamięci, funkcja ładowania działała poprawnie i program został załadowany poprawnie do 0x8000).
Ponieważ procesor jest już w trybie ProtectedMode, a nie RealMode, schemat adresowania jest inny. ProtectedMode używa selektorów deskryptorów do wyszukiwania adresu bazowego i limitu w tabeli deskryptorów, aby dodać dane przesunięcie i pobrać adres fizyczny (jak rozumiem). Dlatego konieczne było zainstalowanie GDT przed wejściem do ProtectedMode.
Kopalnia wygląda tak:
%ifndef __GDT_INC_INCLUDED__
%define __GDT_INC_INCLUDED__
;*********************************
;* Global Descriptor Table (GDT) *
;*********************************
NULL_DESC:
dd 0 ; null descriptor
dd 0
CODE_DESC:
dw 0xFFFF ; limit low
dw 0 ; base low
db 0 ; base middle
db 10011010b ; access
db 11001111b ; granularity
db 0 ; base high
DATA_DESC:
dw 0xFFFF ; data descriptor
dw 0 ; limit low
db 0 ; base low
db 10010010b ; access
db 11001111b ; granularity
db 0 ; base high
gdtr:
Limit dw 24 ; length of GDT
Base dd NULL_DESC ; base of GDT
%endif ;__GDT_INC_INCLUDED__
i jest ładowany do GDT zarejestrować poprzez
lgdt [gdtr]
Co nie rozumiałem tak daleko, jak mogę teraz przejść do fizycznego adres 0x8000 w ProtectedMode za pomocą GDT?
Moje pierwsze myśli polegały na wybraniu deskryptora kodu (CODE_DESC), który powinien wskazywać na 0x7e00 (jeśli aktualny program został załadowany) i użyć przesunięcia, które jest konieczne, aby uzyskać 0x8000 (512 bajtów), co skutkuje instrukcją skoku :
jmp CODE_DESC:0x200
Ale to nie działa.
jmp 0x7e0:0x200
nie działa albo ...
Czy masz jakiś pomysł, co ja tu brakuje? Może nie zrozumiałem czegoś istotnego w ramach 32-bitowego schematu adresowania ProtectedMode i użycia GDT.
[EDIT] Kompletny kod:
bits 16
org 0 ; loaded with offset 0000 (phys addr: 0x7e00)
jmp Start
Start:
xor ax, ax
mov ax, cs
mov ds, ax ; update data segment
cli ; clear interrupts
lgdt [gdtr] ; load GDT from GDTR (see gdt_32.inc)
call OpenA20Gate ; open the A20 gate
call EnablePMode ; jumps to ProtectedMode
;******************
;* Opens A20 Gate *
;******************
OpenA20Gate:
in al, 0x93 ; switch A20 gate via fast A20 port 92
or al, 2 ; set A20 Gate bit 1
and al, ~1 ; clear INIT_NOW bit
out 0x92, al
ret
;**************************
;* Enables Protected Mode *
;**************************
EnablePMode:
mov eax, cr0
or eax, 1
mov cr0, eax
jmp ProtectedMode ; this works (jumps to label and halts)
;jmp (CODE_DESC-NULL_DESC):ProtectedMode ; => does not work
;jmp 08h:ProtectedMode , => does not work
;***************
;* data fields *
;* &includes *
;***************
%include "gdt_32.inc"
;******************
;* Protected Mode *
;******************
bits 32
ProtectedMode:
;here I want to jump to physical addr 0x8000 (elf64 asm program)
.halt:
hlt
jmp .halt
Dziękuję za wyjaśnienie ... Właśnie dlatego robię to - i to nie jest takie proste, kiedy robisz to od podstaw po raz pierwszy, czytając referencje x86 :)! Btw: Czy jest jakaś świetna książka, którą możesz doradzić, która zajmuje się właśnie takimi tematami? –
Nie znam dobrych książek. Oficjalna dokumentacja od firmy Intel i AMD zawiera wszystkie informacje, nie jest to typowy rodzaj książki lub podręcznika, który można przeczytać od razu i zrozumieć wszystko (przy okazji, istnieje wiele literówek i okazjonalnych błędów w dokumentach Intela). Istnieje wiele artykułów i samouczków online. I zawsze możesz eksperymentować. Lub zobacz czyjś kod i zadawaj pytania. Zobacz te grupy: [alt.os.development] (http://groups.google.com/group/alt.os.development/topics), [comp.lang.asm.x86] (http://groups.google .com/group/comp.lang.asm.x86/topics). –
Dzięki za porady !! Popatrzę na to! –