Lowlevel
Lowlevel => Lowlevel-Coding => Thema gestartet 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
-
...
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.
-
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.
-
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 ...
-
so, der BootLoader ladet den Kernel und führt ihn auch aus, jtzt liegt der Fehler beim Kernel ...
http://pastebin.de/9270
-
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
-
danke
MfG thetrue