Welches Programm belegt welchen Sektor und wie gross (Dateisystem)
-
Ich habe 3 Dateien in der os.bin gespeichert (boot.bin, kernel.bin und test.bin).
Der Bootloader liegt auf dem 1. Sektor, der Kernel auf dem 2. und das Testprogramm auf dem 3., da alle 3 Programme nicht groesser als 512 Bytes sind und ein Sektor aus 512 Bytes besteht.
Der Quelltext wuerde dementsprechend so aussehen.
Bootloader:
mov cl, 1 (Sektor 1 = Bootloader)
mov al, 1 (nur 1 Sektor laden, da nicht groesser als 512 Bytes)
Kernel:
mov cl, 2 (Sektor 2 = Kernel)
mov al, 1 (nur 1 Sektor laden, da nicht groesser als 512 Bytes)
testprogramm:
mov cl, 3 (Sektor 3 = Testprogramm)
mov al, 1 (nur 1 Sektor laden, da nicht groesser als 512 Bytes)Aber angenommen, mein Kernel waere jetzt 600 Bytes gross, dann wuerde es ja bedeuten, dass er sich ueber 2 Sektoren hinwegzieht.
Dann wuerde es so aussehen.
Bootloader:
mov cl, 1 (Sektor 1 = Bootloader)
mov al, 1 (nur 1 Sektor laden, da nicht groesser als 512 Bytes)
Kernel:
mov cl, 2 (Sektor 2 = Kernel)
mov al, 2 (2 Sektoren laden, da 600 Bytes auf mindestens 2 Sektoren passt)
testprogramm:
mov cl, 3 (Sektor 3 = Testprogramm, noch nicht Sektor 4, da Sektor 3 noch nicht vollgeschrieben ist)
mov al, 1 (nur 1 Sektor laden, da nicht groesser als 512 Bytes)Hab ich das richtig verstanden? Und wenn der Kernel also 1024 Bytes gross waere, dann wuerde das Testprogramm erst beim 4. Sektor anfangen, da auch der 3. Sektor schon vollgeschrieben ist. Stimmt es? Wenn nein, wie ist es dann richtig?
-
Bei Verwendung eines Dateisystems wird in der Regel ein neuer Block begonnen, wenn eine neue Datei beginnt. Wenn Du allerdings einfach nur Rohdaten irgendwie (mittels dd oder '+' in der DOS-Shell, o.ä.) auf einen (unformatierten) Datenträger schreibst, werden die alle hintereinanderweg geschrieben.
-
Und dann hab ich es mir so vorgestellt, dass nachdem das Programm gebootet hat, eine Sektordatei gelesen wird, die nach dem Bootloader geschrieben ist.
Dort steht z.B. drin:
11
26
test.binDas heisst, wenn man im Kernel die Prozedur Exec aufruft mit dem Parameter test.bin oder sobald man in der Shell(Eingabeaufforderung) test.bin eingibt, wird in der Sektordatei nach test.bin gesucht, dann wird gesucht, was 2 Zeilen druebersteht(11) und was 1 Zeile druebersteht (26) und das Programm zwischen diesen Sektoren wird ausgefuehrt.
Kann man das so machen?
-
Das klingt machbar, wenn auch nicht besonders sinnvoll (Wie kann man dort neue Dateien hinzufügen? Muss dann im ganzen Dateisystem alles verschoben werden, damit in der Liste Platz entsteht?). Schau dir mal richtige Dateisysteme an, z.B. FAT als einfaches Beispiel.
-
Ne, eigentlich so...
11
26
test.binAngenommen, der Sektor 26 ist der letzte belegte Sektor... Ich erstelle jetzt eine Datei test2.bin. Die beginnt ab dem Sektor 27 und geht solange, wie die Datei gross ist. Allerdings hab ich noch keinen Schimmer, wie ich mit dem BIOS-Interrupt eine Dateilaenge ausmessen soll, muss ich mir eben was anderes einfallen lassen. Sagen wir die geht bis zum Sektor 32, dann erstellen wir test 3.bin von Sektor 33 bis Sektor 40.
Dann sieht es so aus.
11
26
test.bin
27
32
test2.bin
33
40
test3.binWenn ich jetzt z.B. die Datei test2.bin loesche, dann wuerde die Sektordatei so aussehen:
11
26
test.bin
33
40
test3.binUnd damit man die Luecken flickt, wird es ein Programm namens defrag geben, das dann sagt, aha die 33 kommt aber nun nicht nach der 26, also beginnt nun test3.bin ab 27 und endet bei 34.
Also, es sucht sich in der Datei eine Zeile, wo Text (ein String) dasteht und kein Integer. Dann sucht es, was eine Zeile drueber steht (26) und was eine Zeile drunter steht (33). Dann sagt es, die Zeile, wo die 33 steht, ist nicht 26+1, also schreibe dort 26+1=27 hin.Also, wie man sieht, soll es nur ein Spass-OS werden.
Aber jetzt mal eine andere Frage: Bisher laeuft ja alles noch in NASM. Wie kann ich die Prozeduren von kernel.bin exportieren und in einer anderen asm-datei wieder aufrufen? Ich meine mal gehoert zu haben, dass man dazu ein anderes Format braucht, weiss da jemand was?
-
Das Problem, das ich sehe, ist ein Größenwachstum der Liste, das dadurch begrenzt ist, wo die erste Datei auf der Festplatte beginnt. Angenommen, die Liste beginnt in Sektor 2 und die erste Datei liegt in Sektor 4. Dann kannst Du also maximal 2 Sektoren (1024 Bytes) als Dateiliste haben. Brauchst Du mehr Dateiliste, musst Du alle Dateien dahinter, also potentiell mehrere GB, verschieben - nur um eine neue Datei hinzuzufügen. Außerdem erlaubt dein Verfahren natürlich keine Fragmentierung (des Datenbereichs).
Wie kann ich die Prozeduren von kernel.bin exportieren und in einer anderen asm-datei wieder aufrufen? Ich meine mal gehoert zu haben, dass man dazu ein anderes Format braucht, weiss da jemand was?
Man kann natürlich ein richtiges Executable-Format wie PE oder ELF nehmen. Aber das geht auch mit rohen Binaries. Du musst nur wissen, wohin Du springen musst, um eine Funktion aufzurufen. Du lädst die Datei an die gewünschte Stelle und rufst die Adresse/den Einsprungpunkt dann mit asm auf. Eine MAP-Datei kann dir die Adressen der Funktionen in der Binärdatei anzeigen.
-
ok, danke, zum letzten werde ich mich nochmal hierher wenden , falls ich fragen habe...
aber zu der liste... man kann es vielleicht auch so machen, dass der bootloader erstmal die groesse dieser datei misst und der wert am anfang der datei gespeichert wird.
so stelle ich mir dann die liste vor...
statt
11
26
test.binsektoren:
8
dateien:
11
26
test.bin
27
30
test2.bin
31
36
test3.bin
...wenn ich exec und test.bin aufrufe, wird das programm ab sektoren (8) + testanfang (11) ausgefuehrt.
Allerdings scheint es nach meiner bisherigen Entwicklung eher so auszusehen, dass die Datei erst nach dem Kernel geladen wird, aber das ist ja erstmal nebensaechlich.
-
ok, wie kann man eine map datei erzeugen?
-
OK, ich hab's jetzt mal probiert...
Hier die MAP-File:
- NASM Map file ---------------------------------------------------------------
Source file: kernel.asm
Output file: kernel.bin-- Symbols -------------------------------------------------------------------- ---- Section .text ------------------------------------------------------------ Real Virtual Name 1000 1000 main 1014 1014 exec 102E 102E restart 1030 1030 mem_pos 1032 1032 sect_start 1033 1033 sect_count
Und hier der Aufruf:
Funktion restart soll geladen werden.
mov ax, 0x102E mov es, ax mov ah, 02h mov al, 1 mov ch, 0 mov cl, 2 ; Boot-Loader=1 Kernel=2 Test=3 mov dh, 0 mov dl, 00h int 13h jmp 0x1000:0x102E
in restart steht nur int 19h (reboot) drin...
Ich weiss zwar, dass es falsch ist, aber wie waere es richtig?
-
mov ax, 0x102E mov es, ax
Das sieht falsch aus. Ich denke, die Daten müssen nach 0x1000 geladen werden. Dann könnte es klappen.
EDIT: Und der Jump ist irgendwie falsch. eher 0x1:0x2E oder 0x00:0x102E. Hab die Berechnungsweise gerade nicht im Kopf.
-
Ja, ich habs schon durch bisschen Probieren geschafft.
mov ax, 0x1000 mov es, ax mov ah, 02h mov al, 1 mov ch, 0 mov cl, 2 ; Boot-Loader=1 Kernel=2 Test=3 mov dh, 0 mov dl, 00h int 13h jmp 0x1000:0x002E
So geht es.
Danke trotzdem
-
Wenn ich ein Programm oeffne, mach ich es ja so...
mov ax, 0x2000
mov es, axmov ah, 02h
mov al, 1
mov ch, 0
mov cl, 3 ; Boot-Loader=1 Kernel=2 Test=3
mov dh, 0
mov dl, 00h
int 13hjmp 0x2000:0x0000
Aber wie kann ich das Programm wieder schliessen? (Also, wie kann ich die Adresse 0x2000 vom Arbeitsspeicher freigeben?)
-
Du könntest Syscalls implementieren, mit denen das Programm signalisiert, dass es fertig ist.
-
Ne, ich will ja das Programm intern beenden (also von dem Programm selber aus beenden). Der Computer weiss ja dann, wann er das Programm beenden soll.
Aber ich suche sowas wie die Funktion 4Ch im DOS-Interrupt (21), nur dass ich eben auf BIOS-Ebene arbeiten will.
http://www.i8086.de/dos-int-21h/funktion-4c.html
Der RAM-Speicher, den das zu beendende Programm belegt, wird nach diesem Funktionsaufruf freigegeben.
Hier ein Beispiel.
kernel.asm ... mov ax, 0x2000 -> Programm test wird geladen in Adresse 0x2000 mov es, ax mov ah, 02h mov al, 1 -> test geht ueber 1 Sektor mov ch, 0 mov cl, 3 -> test liegt auf Sektor 3 mov dh, 0 mov dl, 00h int 13h jmp 0x2000:0x0000 -> springe zur main-funktion von 0x2000 (test) ...
test.asm ... exit: ;Jetzt soll die Adresse 0x2000, wo ja dieses Programm (test.asm) geladen worden ;ist, wieder freigegeben werden. ??? -> da brauche ich Hilfe ;Danach wird wieder zum Kernel zurueckgesprungen jmp 0x1000:0x0000
MfG
-
statt dem Jump dann halt:
int 0x90
dann wäre 0x90 dein Syscall für exit(). Die Zahl kannst Du dir natürlich aussuchen. Du müsstest dann einen Handler implementieren für den Syscall, der dann die Speicherfreigabe durchführt.
-
Danke
Aber das Problem ist, dass ich ja nicht weiss, wie man den Speicher freigibt. Der Rest ist klar.
Ich habs schon so versucht.
mov ax, 0x2000 mov es, ax mov ah, 02h mov al, 0 mov ch, 0 mov cl, 0 ; Boot-Loader=1 Kernel=2 Test=3 mov dh, 0 mov dl, 00h int 13h
Das heisst, dass ich dachte, wenn cl und al 0 ist, der Speicher in 0x2000 wieder freigegeben wird und 0x2000 fuer was anderes verwendet werden kann. Aber so sei es leider nicht
Wuensch dir einen schoenen Tag noch!
-
Das heisst, dass ich dachte, wenn cl und al 0 ist, der Speicher in 0x2000 wieder freigegeben wird und 0x2000 fuer was anderes verwendet werden kann. Aber so sei es leider nicht
Du hast ja keine Speicherverwaltung (weder physisch noch virtuell) in der man irgendwas freigeben könne... Such mal nach den Themen Segmentierung, Paging und Heap.
-
Ja, danke... Ich werde es mir mal ansehen und falls ich das durchsetze und Fragen habe, frag ich eben nochmal...
Mein Betriebssystem wird sich allerdings wiedermal nach meinen Vorstellungen richten wie alles andere was ich tue auch.
Ansonsten wird jetzt erstmal vom Real Mode zum Protected Mode umgeschalten... Das ist erstmal dringend notwendig.
-
Wenn man im Protected Mode ist, stehen einem ja keine BIOS-Funktionen mehr zur Verfuegung, also verwendet man VMM-Funktionen soweit ich gehoert habe.
Aber gibt es zu den VMM-Funktionen eine genauso gute Beschreibung wie im folgenden Link zu den BIOS-Interrupts?
https://www.tu-chemnitz.de/informatik/RA/lehre/mop/dos_stuff/int.html
-
Es gibt die Wikis osdev.org und lowlevel.eu:
http://www.lowlevel.eu/wiki/Heap
http://www.lowlevel.eu/wiki/Paging
http://wiki.osdev.org/Paging