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.bin

    Das 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.bin

    Angenommen, 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.bin

    Wenn ich jetzt z.B. die Datei test2.bin loesche, dann wuerde die Sektordatei so aussehen:

    11
    26
    test.bin
    33
    40
    test3.bin

    Und 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.bin

    sektoren:
    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, ax

    mov 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 13h

    jmp 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




Anmelden zum Antworten