Lowlevel

Lowlevel => Lowlevel-Coding => Thema gestartet von: thetrue am 18. July 2006, 22:47

Titel: Sprung in PMode geht nicht
Beitrag von: thetrue am 18. July 2006, 22:47
moin, habe en problem,dass ich nicht lösen kann:

boot.asm:


org 0x7C00h ;Unsere Startadresse


;-----------------------------------------------------;
; Erst brauchen wir einen Stack    ;
;-----------------------------------------------------;
cli
mov ax, 0x9000   ;Stacksegment
mov ss, ax ;Stapelsegment
mov sp, 0 ;Stapelzeiger
sti

;-----------------------------------------------------;
; V A R I A B L E N        ;
;-----------------------------------------------------;
[bits 16]
bootdrv db 0 ;Das Bootlaufwerk
loadmsg db "loading trueOS-kernel v.0.1 ....",13,10,0  ;Die Load-Nachricht
sectors db 14 ;14 Sectors


;-----------------------------------------------------;
mov [bootdrv], dl ;Bootlaufwerk aus DL speichern
;-----------------------------------------------------;
call load ;Lade unseren Kernel
;-----------------------------------------------------;

;-----------------------------------------------------;
; Springe zu diesem Kernel    ;
;-----------------------------------------------------;

mov ax, 0x10000 ;Die Adresse des Programms
mov es, ax
mov ds, ax
push ax
mov ax, 0
push ax
retf

;-----------------------------------------------------;
; Einen String ausgeben        ;
;-----------------------------------------------------;
putstr:
lodsb ;Lade nächstes Zeichen nach AL ...
or al,al
jz short putstrd
mov ah,0x0E ;Die Function 0x0Eh
mov bx,0x0007
int 0x10 ;Den Interrupt 10h bitte
jmp putstr ;Nächste runde ...
putstrd:
retn

;-----------------------------------------------------;
; Lade den Kernel vom Bootlaufwerk          ;
;-----------------------------------------------------;
load:
push ds             ;Sichere DS
mov ax, 0x00           ;Die gewünschte Funktion (reset)
mov dl, [bootdrv]   ;Dieses Laufwerk ist gewünscht
int 0x13             ;Den Interrupt ausführen
pop ds             ;DS wiederherstellen
jc load             ;Geht nicht? -> Noch mal!

load1:
mov ax,0x10000 ;ES:BX = 10000 ...
mov es,ax ;...
mov bx, 0 ;...

;--------------------------------------;
; Sektoren lesen (Interrupt 13h, 2) ;
;--------------------------------------;

mov ah, 0x02       ;Funktion 2 (Lesen)
mov al, [sectors]       ;Lese n Sektoren
mov cx, 2       ;Cylinder=0, Sector=2
mov dx, 0       ;Head=0, Laufwerk=0
int 0x13         ;ES:BX =  Daten vom Laufwerk
jc load1         ;Fehler? Noch mal!

mov si,loadmsg ;Loadmsg nach SI
call putstr ;Nachricht ausgeben
retn             ;Ende!

times 512-($-$$)-2 db 0   ;die Datei soll 512 Bytes groß sein
dw 0AA55h                 ;Dieses Word muss am Ende stehen.


kernel.asm:


[Bits 16]
jmp start ;die Descriptors überschpringen

;-------------------------------------------------------;
; Descriptors ;
;-------------------------------------------------------;
NULL_Desc:
dd 0
dd 0

CODE_Desc:
dw 0xFFFF ;Segmentgröße Byte 0/1
dw 0 ;Segmentbasisadresse Byte 0/1
db 0 ;Segmentbasisadresse Byte 2
db 0x9A ;Zugriffsberechtigungen
db 0xCF ;Zusatz + Segmentgröße Bits 16 - 19
db 0 ;Segmentbasisadresse Byte 3


DATA_Desc:
dw 0xFFFF
dw 0
db 0
db 0x92
db 0xCF
db 0

gdt:
Limit dw 0 ;Größe der GDT (wird später eingetragen)
Base dd 0 ;Adresse der GDT (wird später eingetragen)

;-------------------------------------------------------;
; DER JUMP ETC ;
;-------------------------------------------------------;
start:
cli ;Keine Interrupts
mov eax, cs ;CS nach EAX
mov ds, ax ;AX nach DS

shl eax, 4 ;EAX um 4 Bits nach links verschieben
mov [CODE_Desc+2], ax ;Den ersten Teil der Linearen Adresse eintragen
mov [DATA_Desc+2], ax ;.....
shr eax, 16 ;EAY um 16 Bits nach rechts verschieben
mov [CODE_Desc+4], al ;Den zweiten Teil der Linearen Adresse eintragen
mov [DATA_Desc+4], al ;....

mov eax, cs ;EAX aktualisieren
shl eax, 4 ;Wieder um 4 Bits nach link verschieben
add eax, NULL_Desc ;Zu OFFSET von NULL_Desc adden
mov [Base], eax ;Die Segmentbasisadresse von EAX nach [Base]
mov [Limit], WORD gdt - NULL_Desc - 1 ;Die Größe

lgdt [gdt] ;Die GDT laden ...

;-------------------------;
; PMode einschalten      ;
;-------------------------;
mov eax, cr0 ;Das CR0 Register in EAX laden
or eax, 1 ;Das erste Bit (PE Bit) auf 1 setzen
mov eax, cr0 ;Das CR0 Register mit dem neuen Wert laden
;-------------------------;
; FAR-JUMP      ;
;-------------------------;
db 0xea ;Bitmuster für einen FAR JUMP
dw MAIN_F ;Angabe des Offsets zu dem gesprungen werden soll
dw 0x8 ;Selektor zu dem gesprungen werden soll

[Bits 32]
;-------------------------------------------------------;
; DIE MAIN FUNCTION ;
;-------------------------------------------------------;
MAIN_F:
mov WORD [CODE_Desc+2], 0 ;Code Segmentstartaddresse auf 0 setzen
mov WORD [DATA_Desc+2], 0 ;Daten Segmentstartadresse auf 0 setzen
mov BYTE [CODE_Desc+4], 0 ;Code Segmentstartaddresse auf 0 setzen
mov BYTE [DATA_Desc+4], 0 ;Daten Segmentstartadresse auf 0 setzen

mov eax, 2 ;Selektor für das Datensegment erstellen
shl eax, 3

mov ds, ax ;Daten- Stack- und Extrasegment mit
mov ss, ax ;Datensegmentdeskriptor laden
mov es, ax
mov eax, 0 ;FS und GS mit Null-Deskriptor laden
mov fs, ax
mov gs, ax
mov esp, 0x1FFFFF ;Stack auf unterhalb der 2 MB Grenze setzen

jmp 0x8:0x10000 + MAIN ;Sprung in das "neue" Codesegment

MAIN:
mov esi, 0
text:
;-----text ausgabe-----;
mov [0xB8000+esi], byte '*'
inc esi
mov [0xB8000+esi], byte 1Bh
inc esi
cmp esi, 3840
jl text
cli
hlt

times 512-($-$$) db 0;



das problem ist, es pasier nix ^^, aber eigentlich sollte ja * ausgegebenn werden ... viele male :D
Titel: Re: Sprung in PMode geht nicht
Beitrag von: Jidder am 18. July 2006, 23:12
Zitat von: thetrue
...

mov ax, 0x10000                               ;Die Adresse des Programms

...

load1:
   mov ax,0x10000                            ;ES:BX = 10000 ...


Erstmal alle 0x10000 im 16 Bit Code durch 0x1000 ersetzen, denn du lädst da Segmentregister, die 16 Bit groß sind. Die lineare Adresse 0x10000 ergibt sich durch Segment * 16 + Offset = ES * 16 + BX = 0x1000 * 16 + 0 = 0x10000. Wenn das noch unklar ist, solltest du dir noch ein wenig über die Programmierung im Real Mode informieren.
Titel: Sprung in PMode geht nicht
Beitrag von: DarkThing am 18. July 2006, 23:14
Hi,
ein Problem ist auf jeden Fall, dass du die Variablen im Bootsector da erstellst, wo sie auch ausgeführt werden. Du solltest den Variablen-Teil also ans Ende, direkt vor den times-Befehl verschieben.
Evtl. musst du dich auch noch um die Segment Register kümmern. Wobei das anscheinend nicht immer nötig ist.
Titel: Sprung in PMode geht nicht
Beitrag von: thetrue am 18. July 2006, 23:46
ok, nun kommt die nachricht ans licht, doch der kernel wird komischerweise nicht geladen ...
die Adresse ist nun 0x1000
und die Variablen vor dem Times ...
Titel: Sprung in PMode geht nicht
Beitrag von: thetrue am 19. July 2006, 00:38
so, der BootLoader ladet den Kernel und führt ihn auch aus, jtzt liegt der Fehler beim Kernel ...
http://pastebin.de/9270
Titel: Sprung in PMode geht nicht
Beitrag von: bitmaster am 19. July 2006, 00:53
paar Fehler gefunden:

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


sollte doch wohl eher heißen:

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


Und noch was:

jmp 0x8:0x1000 + MAIN

sollte doch wohl eher heißen:

jmp 0x8:0x10000 + MAIN

bitmaster
Titel: Sprung in PMode geht nicht
Beitrag von: thetrue am 19. July 2006, 00:55
danke

MfG thetrue