Eigenes OS?



  • @Erhard Henkes:
    Die Screenshots auf deiner Webseite würde ich eher im PNG-Format abspeichern und nicht als JPEG. Das hätte folgende Vorteile gegenüber JPEG:

    1. Keine unscharfen Kanten, Text bleibt daher gut lesbar.
    2. Oft kleinere Dateigröße.

  • Mod

    Die Screenshots auf deiner Webseite würde ich eher im PNG-Format abspeichern und nicht als JPEG

    Danke für den Tipp 👍
    EDIT: Ist deutlich performanter als JPG. Werde mich wohl umgewöhnen müssen. 😉



  • Noch etwas zur Integer-Arithmetik (signed/unsigned Addition vs. Subtraktion).
    Weitergeführt bis zum "Ende" würde die "RealMode" dann in etwa aussehen wie folgt:

    RealMode:
     add sp, -0x40     ; space for input buffer (64 chars)
    (...)
     add sp,  0x40     ; clean it, please
     ret
    

    Besser wäre da die "klassische" (und verständliche) Logik:

    RealMode:
     sub sp,  0x40     ; space for input buffer (64 chars)
    (...)
     add sp,  0x40     ; clean it, please
     ret
    


  • Ob nun sub oder add ist in diesem Fall wohl reine Geschmackssache. Ich versuche sub wenn moeglich aus dem Weg zu gehen, da ich das uebersichtlicher finde (es gehen auch Mythen ueber einen Geschwindigkeitsvorteil um...).
    Und wer nicht erkennt, dass
    +(-40) == -(+40)
    ist, hat noch andere Probleme als sich mit OS-Entwicklung zu befassen. 😃
    Was hat das mit "klassischer Logik" zu tun?

    Was das "clean please" betrifft: Hast natuerlich prinzipiell recht. So wuerde/koennte man das sauber in einer Prozedur mit lokalen Variablen loesen. Evtl. koennte man einen entsprechenden Kommentar platzieren.
    Der Code fuer den Prompt (was du wohl "RealMode" nennst?) ist allerdings keine klassische Prozedur und hat deshalb auch keinen Ausgang, bei dem das irgendwie sinnvoll unterzubringen waere. Anders ausgedrueckt: Wenn der Prompt verlassen und der angelegte Puffer damit nicht mehr gebraucht wird, also freigegeben werden koennte, wird jedes Mal der RM-Stack unmittelbar danach eh eingestampft.
    Assembler ist in der Hinsicht nun mal einfach keine Sprache fuer Sauberkeitsfanatiker. 😃



  • wann geht's denn nun endlich mit dem OS los?
    🙂


  • Mod

    wann geht's denn nun endlich mit dem OS los?

    Zunächst habe ich die Code-Abschnitte erklärt, z.B. die "Zeigermechanik" bezüglich des Selektors auf die Deskriptoren-Tabelle. In vielen anderen Artikeln findet man

    jmp [b]0x8[/b]:ProtectedMode
    

    und

    mov    ax, [b]0x10[/b]
        mov    ds, ax      ; data descriptor --> data, stack and extra segment
        mov    ss, ax            
        mov    es, ax
    

    , und niemand erklärt, woher die 0x8 oder 0x10 eigentlich kommen, fallen einfach vom Himmel. Die Berechnung habe ich mittels Abbildung zum Selektoraufbau und Linksshift mit dem wissenschaftlichen "Calculator" nun hoffentlich klar genug dargestellt.
    http://www.henkessoft.de/OS_Dev/OS_Dev1.htm#mozTocId533818 please check 😉

    Didaktisch bin ich noch nicht völlig zufrieden, da muss noch einiges klarer gezeichnet und umgestellt werden.
    Von dieser Seite ( http://forum.osdev.org/viewtopic.php?f=1&t=19451 ) kommen auch noch einge Randbemerkungen.

    Nun ist aber immerhin eine ansprechende Basis mit eingeschaltetem A20 Gate und Protected Mode entstanden, die sich allerdings noch völlig autistisch verhält. 😃
    Die nächsten Schritte werden dem Kernel die Innen- und Außenwelt systematisch öffnen. Ich denke hier gerade über das Was, Wie, Wann und ASM vs C und die Aufgliederung der Module nach. Auf jeden Fall möchte ich den didaktischen Aspekt ganz vorne sehen. Daher würde mich interessieren, wie Einsteiger ohne Erfahrungen in OS Development das Tutorial bisher einschätzen.



  • Erhard Henkes schrieb:

    Die nächsten Schritte werden dem Kernel die Innen- und Außenwelt systematisch öffnen. Ich denke hier gerade über das Was, Wie, Wann und ASM vs C und die Aufgliederung der Module nach.

    ok, als faustformel: alles was in C nicht so toll geht, machste in asm (z.b. umschaltung der tasks), alles andere in C. weil du ja x86 benutzt, sollteste dann auch auf die 'task state segmente' eingehen.
    🙂


  • Mod

    @+fricky: Danke für Deine Ratschläge. 🙂



  • Erhard Henkes schrieb:

    @+fricky: Danke für Deine Ratschläge.

    keine ursache. es gibt übrigens auch kernels, die ganz ohne asm auskommen. such mal nach protothreads/contiki und das hier:
    http://www.nilsenelektronikk.no/nenesos.html
    🙂


  • Mod

    Contiki is designed for microcontrollers with small amounts of memory. A typical Contiki configuration is 2 kilobytes of RAM and 40 kilobytes of ROM.

    Ist mir schon klar, wo ich mich bei dem x86-Gerödel befinde. Das Programm oder OS wird dann eben ins EEPROM geflasht (mache ich beim Asuro oder Nibo auch: http://www.henkessoft.de/Roboter/Bilder/Nibo_mit_STK500_flashen_Ausschnitt_small.jpg ) anstelle von Floppy oder Hard Disk gebootet. Übrigens sehe ich ASM nicht als Nachteil für den bisherigen OS Start.

    Mal eine andere Frage: Kennt sich jemand mit Qemu aus? Ich habe es bisher nicht geschafft, das OS damit zu booten. Lohnt es sich, sich damit herum zu quälen?

    Zum Debuggen erscheint mir der Bochs Debugger momentan ideal.
    @Nobuo T: Wie debuggst Du bei solchen Entwicklungen genau?



  • Im Abschnitt über die A20-Leitung ist mir folgendes aufgefallen:

    Es fehlt der definitive Grund, warum sie unbedingt im PM aktiviert sein muß. Ich will es mal so formulieren: Im PM kann ich auf die paar Byte, die die A20-Leitung adressiert, auch gerne verzichten. Aber warum sollte ich das lieber nicht? 🙂



  • Erhard Henkes schrieb:

    Contiki is designed for microcontrollers with small amounts of memory. A typical Contiki configuration is 2 kilobytes of RAM and 40 kilobytes of ROM.

    Ist mir schon klar, wo ich mich bei dem x86-Gerödel befinde. Das Programm oder OS wird dann eben ins EEPROM geflasht (mache ich beim Asuro oder Nibo auch: http://www.henkessoft.de/Roboter/Bilder/Nibo_mit_STK500_flashen_Ausschnitt_small.jpg ) anstelle von Floppy oder Hard Disk gebootet.

    naja, das waren ja nur beispiele, für nicht-preemptive kernels, die entweder continuations oder state machines für's task-switching benutzen. sowas muss nicht unbedingt ins flash, man kann's auch vom laufwerk booten.

    Übrigens sehe ich ASM nicht als Nachteil für den bisherigen OS Start.

    nachteil ist, je mehr asm du einsetzt, desto mehr nagelst du dein OS auf einen spezifischen prozessor fest. und wenn du so, wie bis jetzt, weiter machst, kannste dein tutorial bald in 'die geheimen tricks der x86-assembler gurus' umtaufen.
    🙂


  • Mod

    Es fehlt der definitive Grund, warum sie unbedingt im PM aktiviert sein muß. Ich will es mal so formulieren: Im PM kann ich auf die paar Byte, die die A20-Leitung adressiert, auch gerne verzichten. Aber warum sollte ich das lieber nicht?

    Im Protected Mode kann man problemlos mit 32 Bit arbeiten. Daher muss man das A20-Gate wieder aktivieren, da ansonsten bei bestimmten Speicherzugriffen Fehler auftreten, da die 21. Adressleitung deaktiviert ist. Das bedeutet, das man auf eine andere Speicherstelle zugreifen kann als beabsichtigt. Daher schaltet man A20 ein, bevor man den Kernel und weitere Programmteile startet. Ist das so o.k.?


  • Mod

    wenn du so, wie bis jetzt, weiter machst, kannste dein tutorial bald in 'die geheimen tricks der x86-assembler gurus' umtaufen.

    Ja, da hast Du evtl. Recht.



  • @Erhard Henkes: Inwiefern nervt Sund VirtualBox eigentlich bei dir mit Werbung?
    Bei mir erscheinen nur gelegentlich Tipps und Hinweise auf Updates, ich finde diese Passage zur Werbung daher etwas übertrieben...



  • Erhard Henkes schrieb:

    wenn du so, wie bis jetzt, weiter machst, kannste dein tutorial bald in 'die geheimen tricks der x86-assembler gurus' umtaufen.

    Ja, da hast Du evtl. Recht.

    Ich denke, jeder verfolgt beim Programmieren seine eigene Philosophie. Und in Assembler ist es irgendwie so, je länger man sich damit beschäftigt, desto verschwommener wird die Grenze "tricks" und "normal".
    Zum Beispiel einfache Zeile aus kernel.asm:

    xor cx, cx
    

    Warum nicht einfach:

    mov cx, 0
    

    Oder noch eine Zeile:

    or cl, cl     ; zero? (start of the string)
    

    Warum nicht einfach:

    cmp cl, 0
    

    Und man braucht nicht einmal ein Kommentar dazu. Jeder, der es liest, sieht sofort: compare irgendwas mit Null.
    Ich habe bei mir persönlich festgestellt, je "idiotensicherer" der Code geschrieben, desto weniger Kommentare und noch weniger Zeit beim Debuggen. Aber das ist wiederum meine "Philosophie".



  • IMHO, wer mit so einer Philosophie anfaengt (x86)Asm zu programmieren, kann irgendwo nicht wirkliche viel Ahnung von der Plattform haben, fuer die er da programmiert und ist daher wohl besser beraten, es bleiben zu lassen und auf eine abstrakte Hochsprache umzusteigen, in der derart "idiotensichererer Code" in der Performance nicht so kontraproduktiv, und auch allgemein viel effektiver uebersichtlicher zu gestalten ist.
    So ist das doch einfach eine billige Ausrede fuer schlechten Code.

    edit: Ack volkard. Auch ein guter Vergleich. 🙂



  • wer

    xor cx, cx
    

    verschmäht, weil es angeblich unleserlich wäre, und

    mov cx, 0
    

    vorzieht, der muß in der hochsprache auch

    ++c;
    

    meiden und immer brav

    c = c + 1;
    

    schreiben.


  • Mod

    Bei mir erscheinen nur gelegentlich Tipps und Hinweise auf Updates, ich finde diese Passage zur Werbung daher etwas übertrieben...

    Akzeptiert, werde dies abmildern. Möchte sachlich bleiben, hat mich aber schon ziemlich genervt.


  • Mod

    Wir haben einen noch etwas ausbaubaren Real Mode, auch im PM könnte man in Assembler noch etwas machen, aber ich denke, nun ist es an der Zeit, zu einem in C geschriebenen Kernel zu wechseln.

    Als Compiler unter Windows verwende ich den allseits bekannten Compiler DJGPP (2.03 ohne C++). Ist dies das richtige Werkzeug? (Download bei Bona Fide OS Dev.) http://www.osdever.net/downloads/compilers/DJGPP-Installer-nocpp.exe

    Dazu habe ich eine technische Frage:

    Ich habe boot.bin (aufgefüllt auf 512 Byte mit Bootsignatur) und kernel.bin (aufgefüllt auf 1024 Byte).

    Dann habe ich ein k(ernel)_entry.asm und ckernel.asm, das via k_entry.o und ckernel.o mittels linker ld zu ckernel.bin gelinkt wird.

    Dann packe ich alles zu einer einzigen Binärdatei zusammen, die dann auf Floppy geschrieben wird: copy /b boot.bin + kernel.bin + ckernel.bin MyOS.bin

    Der Bootloader lädt sich selbst nach 0x7C00 und den Rest nach 0x8000. Der gelinkte Part mit dem C-Kernel fängt durch die HLT-Auffüllung ab 0x8400 an.

    so sieht k_entry.asm aus:

    [BITS 32]
    
    [global start]
    [extern _main] ; this is in the c file
    hlt
    hlt 
    hlt
    start:
      call _main
      jmp $
    

    Ich kann im bin-Format nicht [extern start] angeben und dann nach start springen: jmp 0x8:0x8000+start

    Daher habe ich mir erst mal die drei HLT vor start gebaut, dann kann ich die Startadresse im Hexeditor hinter den "f4f4f4" leicht finden 😃 und direkt anspringen, z.B.: jmp 0x8:0x86e3; goto C-Kernel (0x8400 + 0x02e3 ist natürlich eine variable Zielscheibe).
    Finde das didaktisch interessant, weil man hier zeigen kann, wie die Zusammenhänge im Speicher ganz genau sind und warum man eine Objektdatei benötigt, denn "start" kann man nur dort als externes Label verwenden.

    Was ist hier eurer Meinung nach der sauberste Weg?
    Benötigt man überhaupt noch eine Zwischen-Datei k(ernel)_entry.asm? (16/32-Bit-Problematik beim ersten Kernel? Außerdem haben wir im ersten Kernel "org 0x8000" verwendet, was wiederum nur im Binär-Format geht)

    Gibt es irgendwie einen Trick (außer dem Spicken nach einer optischen Erkennungsmarke in der Binärdatei), dass man aus kernel.bin nach "start" springen kann, also wie gesagt "extern start" klappt nicht im Binär-Format.

    Der Sprung von _main nach _main() {...} innerhalb der Objektdateien ist natürlich problemlos.

    Wie überwindet man die Grenze bin -> obj mit einem Sprung am saubersten?

    EDIT: Inzwischen über Linker und Linkerscript gelöst.


Anmelden zum Antworten