Lowlevel
Lowlevel => Lowlevel-Coding => Thema gestartet von: sebi2020 am 05. November 2009, 08:41
-
Wie steuert man eigentlich wo der Kernel am Ende im RAM landet. im Magazin tutorial steht iwo jmp 0x1000. Woher weiß man, dass der Kernel auch dort im RAM gelandet ist?! (Bootloader aus Magazin ausgabe 1).
mfg Sebi
-
Bei einem eigenen Bootloader lädst du doch selbst den Kernel von der Diskette? Insofern landet er genau dort, wo ihn dein Code hinlädt.
-
Habe mal den code vom Tut hier eingefügt und kommentare von mir großgeschrieben, wo ich was nicht verstehe. Vielleicht versteht ihr jetzt besser was ich nicht versteh ^^ sorry
org 0x7C00 ; Unsere Startadresse
; -----------------------------------------
; Unser Bootloader
; -----------------------------------------
jmp 0x0000:start
start:
; Erst brauchen wir einen Stack.
cli ; Keine Interrupts!
mov ax, 0x9000 ; Stackadresse
mov ss, ax ; SS = 0x9000 (unser Stack)
mov sp, 0 ; SP = 0x0000 (der Stackpointer)
sti ; Interrupts zulassen
; Segmentregister initialisieren (für Zugriff auf bootdrv notwendig)
mov ax, 0x0000
mov es, ax
mov ds, ax
; BIS HIER VERSTEH ICH ALLES
; Bootlaufwerk aus DL speichern
mov [bootdrv], dl ; WARUM [bootdrv] und nicht bootdrv?
;warum von dl?
; von bios vorbelegt?
;Lade unseren Kernel
call load
;Springe zu diesem Kernel
mov ax, 0x1000 ; Die Adresse des Programms
mov es, ax ; Segmentregister updaten
mov ds, ax
jmp 0x1000:0x0000
; ----------------------------------------------
; Funktionen und Variablen
; ----------------------------------------------
bootdrv db 0 ;Das Bootlaufwerk
loadmsg db "Laden...",13,10,0
; Einen String ausgeben:
putstr:
lodsb ; Byte laden
or al,al
jz short putstrd ; 0-Byte? -> Ende!
mov ah,0x0E ; Funktion 0x0E
mov bx,0x0007 ; Attribut-Byte (wird nicht benötigt)
int 0x10 ; schreiben
jmp putstr ; Nächstes Byte
putstrd:
retn
; Lade den Kernel vom Bootlaufwerk
load:
; Diskdrive reset (Interrupt 13h, 0)
mov ax, 0 ; Die gewünschte Funktion (reset)
mov dl, [bootdrv] ; Dieses Laufwerk ist gewünscht
int 13h ; Den Interrupt ausführen
jc load ; Geht nicht? -> Noch mal!
load1:
mov ax,0x1000 ; ES:BX = 0x10000
mov es,ax
mov bx, 0 ; IST DIES FÜR DEN BIOS INTERUPT, dass die
;gelesenen daten nach 0x1000 geschrieben werden?
; Sektoren lesen (Interrupt 13h, 2)
mov ah, 2 ; Funktion 2 (Lesen)
mov al, 5 ; Lese 5 Sektoren
mov cx, 2 ; Cylinder=0, Sector=2
mov dh, 0 ; Head=0
mov dl, [bootdrv] ; Laufwerk aus Vorgabe
int 13h ; ES:BX = Daten vom Laufwerk
jc load1 ; Fehler? Noch mal!
mov si,loadmsg
call putstr ; Meldung ausgeben
retn
times 512-($-$$)-2 db 0 ; Dateilänge: 512 Bytes
dw 0AA55h ; Bootsignatur
-
Meiner Meinung fehlt dir ein Crashkurs in Assembler...und sowieso funktioniert der Bootloader im Artikel afaik nicht richtig.
Mach's doch lieber anders: Falls nicht schon getan, les' dir erstmal das hier (http://lowlevel.brainsware.org/wiki/index.php/OS-Dev_f%C3%BCr_Einsteiger) durch. Wenn du dann immer noch Lust auf's OS-Dev hast, les dir das hier (http://lowlevel.brainsware.org/wiki/index.php/Teil_1_-_Entwicklungsumgebung) durch und arbeite dich durch die Artikel.
Wenn du eben etwas fertiges haben möchtest um damit herumzuspielen, schau' dir diesen (http://lowlevel.brainsware.org/wiki/index.php/C-Kernel_mit_GRUB) Artikel an.
Ansonsten zu den obigen Erklärungen:
- [bootdrv] kopiert den Inhalt der Speicherstelle namens bootdrv in das Register bzw. daraus zurück. Bei manchen Assemblern wie dem MASM kann die Klammer auch weggelassen werden, was aber aus Gründen der Kompatibilität nicht gemacht werden sollte. Und übrigens: Ja, das BIOS kopiert die Nummer des Laufwerks nach DL, das ist so vorgegeben.
- Nein, die Addresse, nach welcher der Kernel geladen werden soll, wir in ax kopiert:
mov ax, 0x1000
Der Kernel landet somit an Addresse 0x1000
-
- Nein, die Addresse, nach welcher der Kernel geladen werden soll, wir in ax kopiert:
mov ax, 0x1000
Der Kernel landet somit an Addresse 0x1000
Nicht, dass ich wüsste, welche Parameter die BIOS-Funktion erwartet, aber ax ist die Adresse nicht. Das wird nämlich weiter unten durch 0x205 überschrieben. Die Kommentare im Code sagen, es wird nach es:bx gelesen, und wenn sie nicht lügen wird der Kernel nach 0x1000:0x0 geladen, also linear 0x10000 (eine Null mehr!)
-
also dass heißt im grunde, dass die adresse vom bios, wo hingeschrieben wird aus es:bx ließt?
Also wenn ich nach dem Intel Syntax geh, würde:
mov [bootdrv],dl
bedeuten, dass dl nach bootdrv kopiert wird und nicht anderum.
mov ziel, quelle
ich versteh nur nicht was die eckigen klammern solln. soweit ich weiß zeigen die eckigen klammern an, dass der inhalt und nicht die adresse gemeint ist, oder?
Assembler kann ich ja einigermaßen, bei mir haperts mehr an C.
Ich denk das 0x1000 nach ax kopiert wird ist nur, um dann von ax nach es zu kopieren. direkt darunter folgt der befehl:
mov es, ax
Nur ich versteh nicht warum 0x1000:0x0 = 0x10000. Ich dachte die lineare Adresse setzt sich im Real Mode aus Segementadresse und Offset Adresse (Also Segment + Offset = lineare Adresse) zusammen. Wenn ich jetzt die Segmentadresse 0x1000 habe und nen Offset von 0x0 müsste sich doch eigentlich nichts daran änder, man müsste doch weiterhin bei 0x1000. Irgendwie irretiert mich das.
Was ich mich gerade Frage ist, in wie fern Funktioniert der Bootloader nicht. also ich hab denn bootloader und den beispiel kernel kompiliert und nen image geschrieben, bei mir klappt das prima unter bochs...
-
ich versteh nur nicht was die eckigen klammern solln. soweit ich weiß zeigen die eckigen klammern an, dass der inhalt und nicht die adresse gemeint ist, oder?
Eben drum. bootdrv selbst ist die Adresse des Labels. In eine konstante Zahl kann man schlecht was reinkopieren.
Ich denk das 0x1000 nach ax kopiert wird ist nur, um dann von ax nach es zu kopieren.
Ja, weil man Immediatewerte nicht direkt in Segmentregister moven kann.
Nur ich versteh nicht warum 0x1000:0x0 = 0x10000. Ich dachte die lineare Adresse setzt sich im Real Mode aus Segementadresse und Offset Adresse (Also Segment + Offset = lineare Adresse) zusammen
Segment * 16 + Offset. Sonst wärst du ja auch mit Segmentierung immer noch auf die 64k Adressraum beschränkt. Es sind aber 16 * 64k = 1M.
-
ah okay, da weiß ich jetzt bescheid. Ich weiß nur nicht, ob die adresse in es:bx jetzt für das bios da reingeschrieben werden oder nciht?! Bin leider noch unwissend.
-
ah okay, da weiß ich jetzt bescheid. Ich weiß nur nicht, ob die adresse in es:bx jetzt für das bios da reingeschrieben werden oder nciht?! Bin leider noch unwissend.
Ja es:bx ist die Zieladresse die das Bios zum ablegen der Daten nutzen soll. Zu den oft genutzten Interrupts findet man eigentlich ganz gut Übersichten, z.B. http://de.wikibooks.org/wiki/Interrupts_80x86/_INT_13#Funktion_2h:_Sektoren_lesen
-
hm, da frag ich mich aber noch was an diesem bootloader nicht funktioniert... also unter bochs funktioniert er... Ich weiß ja jetzt nicht wie es auf nem richtigen Computer aussieht.