Lowlevel
Lowlevel => Lowlevel-Coding => Thema gestartet von: ST-225 am 15. June 2006, 14:18
-
So, nachdem ich eure (wirklich gelungenen) Lowlevel-Tuts alle gelesen hab möchte ich nun auch mit meinem eigenem OS beginnen. Ich habe mich entschlossen, gleich alles im PMode zu proggen und paging sowie softwaretasking zu benutzen. Mit dem Bootloader bin ich jetzt fertig und habe jetzt mit dem kernel begonnen. In diesem wird zuerst der PMode und daraufhin Paging aktiviert. Mit dem Paging bin ich für den Anfang mal Analog zum Tutorial aus dem lowlevel magazin #8 vorgegangen, jedoch gibt mein test-pc nie "PAGING" (Videotextspeichertest) aus. Hier der Code:
[BITS 16]
mov ax, 0x1000
mov ds, ax
mov es, axcli
call enableA20
lgdt [gdtr]
mov eax, cr0
or al, 1
mov cr0, eax
jmp codesel:PMode
[BITS 32]
PMode:
mov ax, datasel
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
mov esp, 0x90000
Paging:
.init
mov eax, 0
mov ecx, 4096*3
mov edi, 0x8000
rep stosd
.writepagedir
mov DWORD[0x8000+0],(0x9000 | 000000000111b)
mov DWORD[0x8000+3072],(0xA000 | 000000000111b)
.map0
xor ebx,ebx
xor edx,edx
.Loop1:
mov eax,edx
or eax,000000000111b
mov [0x9000+ebx],eax
add ebx,4
add edx,4096
cmp edx,4096*1024
jne .Loop1
.map768
mov DWORD[0xA000],(0xB8000 | 000000000111b)
.activate
mov eax, 0x8000
mov cr3, eax
mov eax, cr0
or eax,10000000000000000000000000000000b
mov cr0, eax
PMODETEST:
mov BYTE[0xC0000000],'P'
mov BYTE[0xC0000002],'A'
mov BYTE[0xC0000004],'G'
mov BYTE[0xC0000006],'I'
mov BYTE[0xC0000008],'N'
mov BYTE[0xC000000A],'G'
retn
enableA20:
.stage1
in al, 0x64
test al, 00000010b
jnz .stage1
.stage2
mov al, 0xD0
out 0x64, al
.stage3
in al, 0x64
test al, 00000001b
jz .stage3
.stage4:
in al, 0x64
test al, 00000010b
jnz .stage4
.stage5
mov al, 0xD1
out 0x64, al
.stage6
in al, 0x64
test al, 00000010b
jnz .stage6
.stage7
pop eax
out 0x60, al
retn
gdtr: ; Desktiptortabelle
dw gdt_end-gdt-1 ; Limit
dd gdt ; Basisadresse
gdt:
dd 0,0 ; Null-Deskriptor
codesel equ $-gdt
dw 0xFFFF; Segmentgröße 0..15
dw 0x0000; Segmentadresse 0..15
db 0x00 ; Segmentadresse 16..23
db 0x9A ; Zugriffsberechtigung und Typ
db 0xCF ; Zusatzinformationen und Segmentgr??e 16...19
db 0x00 ; Segmentadresse 24..31
datasel equ $-gdt
dw 0xFFFF; Segmentgröße 0..15
dw 0x0000; Segmentadresse 0..15
db 0x00 ; Segmentadresse 16..23
db 0x92 ; Zugriffsberechtigung und Typ
db 0xCF ; Zusatzinformationen und Segmentgr??e 16...19
db 0x00 ; Segmentadresse 24..31
gdt_end
Ich hoffe es kann mir jemand helfen !
Vielen Dank schonmal im Vorraus !
-
mov ax, 0x1000
mov ds, ax
mov es, axcli
das cli muss in die nächste Zeile,
und ich denke da sollte auch noch sti drüber
das wird aber wohl nur ein kopierfehler sein...
-
Ja, das Problem ist, dass der Protected Mode Code davon ausgeht, dass er an die Basis 0 geladen wird. In Wirklichkeit ist er anscheinend bei 0x1000:0x0000 also 0x10000 linear. Damit geht der Sprünge in den Protected Mode daneben.
jmp codesel:PMode
muss also
jmp dword codesel:PMode
heissen.
Außerdem gehört die routine enableA20 in den [bit 16] Teil.
Die ganze Sache mit den unterschiedlichen Basen im Real und Protected Mode könnte sich lösen lassen, wenn du org 0x10000 an den Anfang schreibst, was allerdings unsauber ist. Die bessere Möglichkeit wäre, noch im Bootloader in den Protected Mode zu schalten und im Kernel nur 32 Bit Code zu nehmen.
-
@scales of justice: Ja, war natürlich ein Kopierfehler, weil ich ein paar comments weggelassen hab :wink:
@PortChicken: Danke für deine Ratschläge, hat aber trotzdem nicht gefunzt. Ich werde jetzt einen Bootloader mit PMode-Switch proggen. Dazu aber jetzt eine Frage: Wie mache ich das mit der load-Funktion, im PMode kann ich ja keine Hardware-Interrupts mehr verwenden. Oder kann ich das einfach vor dem Switch machen, aber dann stimmen ja die Speicheradressen nicht mehr :?
-
Nein, ich denke nicht, dass es dann ein Problem gibt. Der Bootloader müsste grob so aussehen:
org 0x7c00
[bits 16]
xor ax, ax
mov ds, ax
; lade kernel an die adresse 0x1000:0x0000
mov ax, 0x1000
mov es, ax
mov bx, 0
call load_kernel
; gdt laden
lgdt [gdt_ptr]
; protected mode einschalten
mov eax, cr0
inc eax
mov cr0, eax
mov ax, datasel
mov ds, ax
; es, fs, gs, ss und esp auch mit known-good-werten laden
jmp codesel:0x10000
gdt db ... ; deine gdt
und der kernel so:
[bits 32]
org 0x10000
; a20, paging, etc. initialisieren
-
great thx. Fang' ich gleich morgen früh damit an :idea: :D