Eigenes OS?


  • Mod

    Ich habe das OS auf einem alten PC (AMD 1400 MHz) getestet. Dort rebootet er bei Eingabe "pm", während bochs das OS brav von Diskette schluckt. Weiß jemand, wo der "real wirksame" Fehler liegt?

    Didaktisch steckt das "OS" momentan im Schlamm, da ich momentan nicht sicher bin, wie man das Ganze am besten in kleine Häppchen verpacken kann. Was würdet ihr in welche inc-Dateien packen? Man kann das ja auch kaum noch sinnvoll hier posten (warum gibt es keine scroll-Funktion für solche Dateien wie in anderen Foren?).

    lgdt [gdt] findet man in google 216 mal.
    lgdt [gdtr] findet man in google 740 mal.
    Letzteres ist ja auch richtiger, werde das anpassen.

    Jemand hatte auch nach Einstieg in x86-64 gefragt. Hier sind Links dazu:
    http://wiki.osdev.org/Entering_Long_Mode_Directly
    http://en.wikipedia.org/wiki/Long_mode



  • Ok, mal der Reihe nach abarbeiten...

    Erhard Henkes schrieb:

    Ich hoffe zumindest, dass ich Dich so richtig verstanden habe.
    Wie hättest Du dies mit 'test op,op' (AND-Verknüpfung ohne Speicherung, nur Flags setzen) gemacht? Das nimmt man doch eher, um zu testen, ob ein bestimmtes Bit gesetzt ist? z.B. test AL, 64 (check auf Bit 6)

    Ja, so war das gedacht, sieht ok. 🙂
    "test" kannst du sowohl, wie du schreibst, benutzen, um einzelne Bits zu testen, allerdings erzielst du mit "test al, al" praktisch das gleiche Ergebnis wie mit "or al, al" (oder wohl auch "and al, al", wenn wir schon dabei sind), ist aber IMHO zumindest konsequenter. 🙂

    Erhard Henkes schrieb:

    Welchen offset würde man da mittels org wählen und warum?

    Das offset, an den du den Code im RAM bzgl. Segment 0 kopierst. Da bietet sich IMHO zB. 8000h an...

    Erhard Henkes schrieb:

    Mir ist noch nicht klar, warum die meisten den Kernel (oder ersten Teil des Kernels) nach 10000h setzen.

    ...aus dem selben Grund, aus dem wohl auch viele Frickler ihren Code nach 10000h laden: Es ist einfach eine schoene runde Adresse. Und bei 10000h laeuft man praktisch auch keine Gefahr mehr, irgendwo mit den Untiefen der BDA in Konflikt zu geraten. 8000h sollte da AFAIK aber auch sicher und "rund" genug sein.

    Erhard Henkes schrieb:

    Ich habe das OS auf einem alten PC (AMD 1400 MHz) getestet. Dort rebootet er bei Eingabe "pm", während bochs das OS brav von Diskette schluckt. Weiß jemand, wo der "real wirksame" Fehler liegt?

    Ohne zu testen, kommt mir folgendes eigenartig vor:

    ;z234-237, kernel.asm
      mov    WORD [CODE_Desc+2], 0    ; code segment base address = 0
      mov    WORD [DATA_Desc+2], 0    ; data segment base address = 0
      mov    BYTE [CODE_Desc+4], 0    ; code segment base address = 0
      mov    BYTE [DATA_Desc+4], 0    ; data segment base address = 0
    

    Halte ich durchaus fuer problematisch, mit den RM-Segmenten im PM auf den Speicher zuzugreifen. -> Mein Tipp waere, das Ganze als initialisierte Daten anzulegen, dann kannst du dir diesen Code (wie die restliche Initialisierung in z 104 eigentlich auch) sparen.

    Ausserdem bekommst du potentiell Probleme, wenn du auf Speicher >1MB zugreifst (stack), ohne die A20 eingeschaltet zu haben.

    ...

    Erhard Henkes schrieb:

    Vielleicht kann Nobuo T seine Idee daneben stellen zum Vergleich.

    ...seufz... Das wuerde einiges an Arbeit, da ich deinen Code erst recht nicht ohne Testen umfangreich umschreiben und hier einstellen will. Mal sehen, ob ich heute Abend Zeit und Nerv finde.

    Zu deinem clearscreen32:
    32Bit loop und rep benutzen ecx... Vielleicht liegt es daran.


  • Mod

    Zu test op,op:
    Ich dachte, Du würdest dies als Ersatz für cmp op,op einsetzen wollen.

    Ich habe leider noch nicht genau verstanden, wie Du das mit den initialisierten Daten als Vereinfachung meinst. Ein konkreter Vorschlag würde hier echt helfen.

    Wie kann man in Bochs eigentlich die Belegung des Speichers visualisieren?
    Kenne bisher nur den Bochs Debugger mit der Register-Visualisierung.
    Ist das biedere Bochs eigentlich das ideale Tool bezüglich Visualisierung oder hat jemand bessere Erfahrung mit anderen Emulationen gemacht? Einer der didaktischen Probleme ist ja, dass man überhaupt nicht "sieht", in welchem Mode (RM, PM) man sich befindet, ob A20 aktiviert ist, usw. Da ist eines der Probleme beim Einstieg in die OS-Entwicklung.


  • Mod

    ...seufz... Das wuerde einiges an Arbeit, da ich deinen Code erst recht nicht ohne Testen umfangreich umschreiben und hier einstellen will. Mal sehen, ob ich heute Abend Zeit und Nerv finde.

    Hier ist noch eine andere ältere (Okt. 1996) Quelle für dieses Vorgehen:
    http://www.fh-zwickau.de/doc/prmo/pmtutor/code/pmode/pm_01.asm (einfach)
    http://www.fh-zwickau.de/doc/prmo/pmtutor/code/pmode/pm_07_03.asm (komplex mit multitasking)

    Dies war wahrscheinlich auch Vorbild für die bereits o.g. Vorgehensweise, die Dir nicht sonderlich gefällt:
    http://lowlevel.brainsware.org/wiki/index.php/Protected_Mode

    Erklärbar ist es auf jeden Fall ganz gut.
    Mich irritiert momentan, dass es in Bochs läuft, aber auf einem alten PC von Floppy nicht bootet. 🙄


  • Mod

    Ich habe als Vorbereitung etwas zu RM und PM geschrieben:
    http://www.henkessoft.de/OS_Dev/OS_Dev1.htm#mozTocId362977

    Es ist wichtig, dass man die Erklärungen und Zeichnungen möglichst einfach und richtig versteht. Ansonsten versteht man die praktische Abfolge hinterher falsch. Könnt ihr das bitte mal checken?

    Die nächste geistige Reihefolge wäre dann z.B.:

    1. Selektor (hier kommen GDT und LDT sowie die Privilege Levels 0-3 ins Spiel)
    2. Aufbau GDT
    3. Welche Deskriptoren gibt es noch?
    4. Interrupts
    5. Programmablauf in PM
    6. Multitasking


  • Ich habe deine Quellcodes mal etwas umgebaut. Um die Scrollerei einzudaemmen, habe ich die Dateien mal hier hochgeladen.
    Waere praktisch, wenn du die Quellcodes in deinem Tutorial auch direkt als Downloads haettest (habe sie zumindest nicht gefunden).
    Eine aufschlussreiche Seite zum A20-Kram ist zB. hier zu finden.

    Zu deinem Text:
    Begriffe im Deutschen werden meist ziemlich nach Lust und Laune verwendet, aber
    lineare und physikalische Adresse ist AFAIK nicht das Gleiche. Spaetestens beim Paging nicht: Da wird aus der linearen (zT. dann auch logische Adresse genannt) Adresse mit der PageTable erst die physikalische Adresse gewurstet.

    IMHO koenntest du noch etwas ausfuehrlicher darauf eingehen, warum fuer Multitasking nun auf einmal Schutzmechanismen noetig sind, und warum fuer DOS nicht, bzw. was unter Multitasking grob zu verstehen ist.

    Ansonsten bin ich mir nicht sicher, ob das so schon "leicht verstaendlich" ist.
    IMHO ist dein Fazit noch etwas verwirrend und deinen "5)" in der praktischen Umsetzung kann nicht mal ich so nachvollziehen.


  • Mod

    lineare und physikalische Adresse ist AFAIK nicht das Gleiche.

    Ja, da hast Du ab dem 386er völlig Recht. Man findet in der Literatur ständig einen Mischmasch aus 286er 16-Bit-Protected-Mode und 386er 32-Bit-Protected-Mode. Beim 286er ist die "lineare" Adresse identisch mit der physikalischen Adresse, beim 386er muss letztere aus der ersten wegen des Pagings berechnet werden. Auch die Deskriptoren sind beim Sprung vom 286er zum 386er von sechs auf acht Byte gewachsen. Erst durch direkten Vergleich beider Systeme versteht man, warum das heute so chaotisch angeordnet ist.

    Nobuo, vielen Dank für Deinen Quellcode! Ich werde eine Seite mit Download-Links einbauen. Dort wird es dann auch einen Bereich "Erlkönig" geben, wo wir alphas und betas ablegen können.


  • Mod

    IMHO koenntest du noch etwas ausfuehrlicher darauf eingehen, warum fuer Multitasking nun auf einmal Schutzmechanismen noetig sind, und warum fuer DOS nicht, bzw. was unter Multitasking grob zu verstehen ist.

    Akzeptiert.

    Das "Fazit" werde ich ebenfalls überdenken.


  • Mod

    Feedback bezüglich Code von Nobuo T:

    Test 1: Auf Floppy schreiben und "echt" booten.
    Resultat: Perfekt! 👍

    Erstes Code-Studium:
    Kernel auf 0x08000 gesetzt wie diskutiert,
    buffer weg,
    A20 eingeschaltet (die berühmte 21. Adressleitung),
    ansprechende Ausgabe der Meldung im PM

    @Nobuo T: Danke für die fundierte Unterstützung! 🙂

    @all: bitte den Code checken, gute Ideen werden sofort angenommen. Vielleicht kann man auch im Real Mode noch etwas Interessantes ergänzen, z.B. den CPUID-Befehl?!

    Waere praktisch, wenn du die Quellcodes in deinem Tutorial auch direkt als Downloads haettest (habe sie zumindest nicht gefunden).

    http://www.henkessoft.de/OS_Dev/Downloads/20090321_eh_os.zip

    Ich werde diesen m.E. gelungenen Einstieg in den PM nun didaktisch aufarbeiten, damit das Tutorial Einsteigern das Leben so leicht wie möglich macht. Da fehlen noch einige gute Abbildungen. Die Unterscheidung zwischen 16-Bit- und 32-Bit-Protected Mode ist didaktisch wichtig. Paging, Unterschied lineare/phys. Adresse ebenso.



  • Erhard Henkes schrieb:

    Vielleicht kann man auch im Real Mode noch etwas Interessantes ergänzen

    Vielleicht folgendes:

    Wenn man im PM ein Segmentregister initialisiert und dann wieder in den RM wechselt, bleibt die Segmentgröße des Selektors für das initialisierte Segmentregister erhalten. Dadurch hat man über dieses Segmentregister Zugriff auf die gesamte Segmentgröße auch im RM.

    Was heißt, die Begrenzung auf 1MB RAM im RM kann relativ einfach außer Kraft gesetzt werden. Das Segmentregister darf nur nicht im RM wieder verändert werden. Sonst ist der Spaß vorbei. Aber man ja beliebig oft hin und her wechseln. 🙂


  • Mod

    @+gjm+:
    Das klingt ja echt abenteuerlich! 😃
    Findet man dazu bereits einen Link im Internet oder ist das Geheimwissen?
    Wie läuft denn da die genaue Adressierung im zurück geschalteten RM ab?

    @abc.w: Hast Du den neuen Code bereits ausprobiert?
    http://www.henkessoft.de/OS_Dev/Downloads/20090321_eh_os.zip

    @Nobuo T: Deine konstruktiven Vorschläge wurden aufgenommen und hoffentlich weitgehend umgesetzt. Multitasking und A20 Gate wird jetzt auch breiter besprochen. Das ist schon ganz schön viel Text, hoffentlich brauchbare Abbildungen und ziemlich viele Zeilen Assembler, nur um die Basis PM zu erreichen. Didaktisch ist es wirklich nicht ganz einfach die x86 Historie verständlich zu erklären, ohne allzu langatmig zu werden. 😉


  • Mod

    Eine Frage zum Bootloader-Code:
    http://www.henkessoft.de/OS_Dev/OS_Dev1.htm#mozTocId80121

    Wir schreiben den Offset der Sprung-Adresse des Kernels nachs BX.
    Später springen wir ohne Verwendung dieses Registers.

    mov bx, 0x8000     ; set up start address of kernel
    ;...
    jmp 0x0000:0x8000   ; address of kernel
    

    ES:BX ist notwendig für int 0x13 als "Buffer Address Pointer".
    So läuft es auf jeden Fall auch:

    mov bx, 0x8000     ; set up start address of kernel
    ;...
    jmp bx   ; address of kernel
    

    Wäre letzteres o.k.? Ist das didaktisch nicht besser? Man verwendet BX auch im Sprungbefehl sofort sofort.

    Das erscheint ja auch etwas merkwürdig:

    mov [bootdrive], dl ; boot drive from DL
    ...
    mov dl,[bootdrive] ; select boot drive
    

    Man könnte den Kernel wohl auch von anderer Stelle laden?
    Da unser System dies nicht macht, könnte man [bootdrive] doch auch völlig weg lassen?

    Label load_kernel1 kann jetzt ja auch entfallen nach Nobuos Änderung?



  • ^^mannomann. ist das ein grausames gefrickel hier!


  • Mod

    ist das ein grausames gefrickel hier!

    Destruktive (Troll-)Beiträge werden mich nicht aufhalten oder irritieren. 😃
    Bessere Ideen bezüglich der Umsetzung oder Gesasmtkonstruktion sind dennoch gerne gesehen. 🙂
    Begründe mir lieber mal jemand, warum IBM das Boot-Programm genau nach 7C00h gesendet hat. Die exakte Erklärung habe ich bisher noch nirgends gefunden.



  • Naja, mit dem Wegoptimieren muss man immer aufpassen. Das ist sehr oft auch ein Kompromiss zwischen Stabilitaet, Kompatibilitaet und Optimierung, der einen gewisser "Verhaeltnisbereich" IMHO nicht verlassen sollte.

    Erhard Henkes schrieb:

    Wir schreiben den Offset der Sprung-Adresse des Kernels nachs BX.
    Später springen wir ohne Verwendung dieses Registers.

    mov bx, 0x8000     ; set up start address of kernel
    ;...
    jmp 0x0000:0x8000   ; address of kernel
    

    ES:BX ist notwendig für int 0x13 als "Buffer Address Pointer".
    So läuft es auf jeden Fall auch:

    mov bx, 0x8000     ; set up start address of kernel
    ;...
    jmp bx   ; address of kernel
    

    Wäre letzteres o.k.? Ist das didaktisch nicht besser? Man verwendet BX auch im Sprungbefehl sofort sofort.

    Im Code vor dem long jump zum Kern, kommen wir ganz gut zurecht, ohne genau zu wissen, welchen Wert cs hat, da alle Spruenge etc. nur relativ zum aktuellen Offset (IP) adressieren. Wenn du aber den Sprung ueber bx machst, hast du ein absolutes Offset zu CS und musst dir daher sicher sein, dass cs auch 0 ist. Sonst schiesst du am Ziel vorbei. 😉
    Kann also sein, dass das funktioniert. Die Chancen stehen aber auch nicht schlecht, dass es das auf anderen PCs nicht tut.

    Erhard Henkes schrieb:

    Das erscheint ja auch etwas merkwürdig:

    mov [bootdrive], dl ; boot drive from DL
    ...
    mov dl,[bootdrive] ; select boot drive
    

    Man könnte den Kernel wohl auch von anderer Stelle laden?
    Da unser System dies nicht macht, könnte man [bootdrive] doch auch völlig weg lassen?

    Bei der ersten Verwendung hatte ich die Sache in deinem alten Code auch auskommentiert (z. 16). Beim 2. Mal bin ich nicht sicher, ob dl vom Interrupt nicht geschrottet wird.

    Ansonsten ist das wieder eine Kompatibilitaetsfrage. Du kannst natuerlich die Info des BIOS wegschmeissen, dl einfach immer auf 0 (fdd A:) setzen und damit ausschliessen, dass jemand den Code jemals von was Anderem (2. Floppy, USB oder was auch immer) startet, aber IMHO sind es diese 2 Zeilen irgendwie nicht wert.
    Deshalb habe ich sie drin gelassen.

    Erhard Henkes schrieb:

    Label load_kernel1 kann jetzt ja auch entfallen nach Nobuos Änderung?

    Da hast du allerdings recht.

    Erhard Henkes schrieb:

    @+gjm+:
    Das klingt ja echt abenteuerlich! 😃
    Findet man dazu bereits einen Link im Internet oder ist das Geheimwissen?
    Wie läuft denn da die genaue Adressierung im zurück geschalteten RM ab?

    Nunja, IMHO eher ein glitch denn ein echtes feature. Gelegentlich findet man die Sache als "Flat Real Mode", "Unreal Mode" oder auch "Voodoo Mode" bezeichnet und in alten, frickeligen DOS-Spielen oder Demos verwendet.
    Hier gibt es etwas darueber zu lesen.

    Erhard Henkes schrieb:

    Begründe mir lieber mal jemand, warum IBM das Boot-Programm genau nach 7C00h gesendet hat. Die exakte Erklärung habe ich bisher noch nirgends gefunden.

    Vermutung:
    Historische Ursachen. Es war einfach das obere Ende des RAMs (32kb).


  • Mod

    Hallo Nobuo T, danke für deine Antwort. Bei mir wurde DL nicht geschrottet (sind die BIOS-Interrupts nicht gleich realisiert?), der Sprung mit BX alleine klappte ebenfalls. OK, ich werde auf Dich hören und das nur als Kommentar angeben. Load_kernel1 wird gestrichen. Danke für die Links! Voodoo ... 😃

    So sieht der bootloader nun (endgültig) aus:
    http://www.henkessoft.de/OS_Dev/OS_Dev1.htm#mozTocId80121

    Ich bitte um Check des Kernels:
    http://www.henkessoft.de/OS_Dev/OS_Dev1.htm#mozTocId412221
    (@Nobuo T: Abfrage eines Keystroke vor Reboot bei 'exit' wurde bereits eingebaut. Danke für den Hinweis!)

    Noch eine andere didaktische Frage: Die Bezeichnungen KB, MB etc. sind ja inzwischen nicht mehr eindeutig, vor allem bei MB, GB. Würdet ihr auf KiB, MiB, GiB etc. umsteigen? Die Akzeptanz dieses neuen Vorschlages ist ja noch gering.
    http://de.wikipedia.org/wiki/Kibibyte#IEC-Pr.C3.A4fixe_zur_Basis_2



  • Erhard Henkes schrieb:

    Als kleine Belohnung für die, die hier mitlesen:
    http://bazonline.ch/digital/games/bildstrecke.html?id=18752&pageID=1&n=1
    (sehr schöne nostalgische Fotostrecke zum Thema Computer und Werbung)

    hihi, uralt-computer passen schon irgendwie zu diesem thread.
    hier gibts übrigens noch mehr davon: http://www.computerhistory.org/collections/marketingbrochures/
    🙂



  • Hallo,
    Das Tutorial gefällt mir sehr gut 🙂

    Als Alternative zu Bochs und VirtualPC kann ich noch VirtualBox empfehlen (kostenlos).
    Funktionierte bei mir auf Anhieb. Um die Bootdiskette einzubinden muss diese nochnichtmal in ein Image verpackt sein...

    mfg
    Mr X


  • Mod

    Mr X schrieb:

    ... Das Tutorial gefällt mir sehr gut 🙂 ... Als Alternative zu Bochs und VirtualPC kann ich noch VirtualBox empfehlen (kostenlos). Funktionierte bei mir auf Anhieb. Um die Bootdiskette einzubinden muss diese noch nicht mal in ein Image verpackt sein ...

    Danke für das positive Feedback 🙂 und den Tipp mit VirtualBox. Das werde ich mir anschauen. Denn gerade diese Dinge sind didaktisch wichtig, denn jedes Emulations-Programm hat seine Schwächen und Stärken. Nur wenn Theorie, Praxis und Tools Hand in Hand gehen, macht die Sache Freude und treibt die Kreativität vorwärts.

    Nun habe ich auch die gtd.inc beschrieben, ein echtes Bit-Gefrickel.
    http://www.henkessoft.de/OS_Dev/OS_Dev1.htm#mozTocId398766
    Bitte schaut mal drüber, ob ich keinen Fehler gemacht habe.

    Jetzt fehlt noch die Erklärung des Kernel-Codes.


  • Mod

    @Nobuo T: An dem Punkt bin ich auch schon ins Grübeln gekommen, weil dies alles andere als intuitiv ist. Hier kam genau dazu eine Frage aus einem anderen internationalen Forum:
    http://forum.osdev.org/viewtopic.php?f=1&t=19451&p=152668#p152668

    One thing that caught my eye is this:

    Code:
    xor ax, ax
    [...]
    mov ss, ax
    mov sp, ax
    [...]
    call print_string

    You zero SS and SP and then you use the stack (implicitly by CALL). That looked strange first. It's not broken, but it is not very intuitive. Maybe you want to consider to note this in your text (I didn't see anything about that, maybe I just missed it) and explain why and how that works.

    Vielleicht kannst Du da noch etwas zu Deiner Idee erläutern. Da klafft noch eine "didaktische Lücke". 😃
    Das Thema Stack würde ich gerne auch noch beschreiben (Prinzip, SS, SP, Nutzung durch call, ...). Ich war allerdings über deine Lösung so verblüfft, dass ich erst mal genauer hinschauen wollte.

    Auch diese Zeile wirkt auf den ersten Blick merkwürdig.
    add sp, -0x40 ; make room for input buffer (64 chars)


Anmelden zum Antworten