Eigenes OS?



  • Eine andere Sache, wollte ein Paar Ausnahmen provozieren mit diesem Code:

    .global _k_zero_divide
    .global _k_undefined_op
    .global _k_null_pointer
    
    .section .text
    
    _k_zero_divide:
        movl $0, %eax
        div %eax
        ret
    
    _k_undefined_op:
        ud2
        ret
    
    _k_null_pointer:
        movl $0, %eax
        movl %eax, (%eax)
        ret
    

    Division durch 0 und undefinierter Op 👍
    Die Funktion k_null_pointer() wir aber ausgeführt und das System läuft 😕 Oder ist Zugriff mit Offset Null ok 😕



  • Erhard:
    Irgendwie habe ich inzwischen ein wenig den Ueberblick verloren. Kannst du mal irgendwie ein Verzeichnis oder eine Seite einrichten, wo man waehrend der Entwicklung immer mal die aktuellen Codes runterladen kann?

    Bei deinem ersten KB-Polling hat mich ehrlich gesagt schon etwas gewundert, dass das ueberhaupt funktionierte. Klassischerweise macht man das AFAIR so, dass man einen Handler fuer IRQ 1 installiert. Dort checkt man erstmal, ob etwas im input buffer ist (port 64h, Bit0). Falls was dran liegt, port 60h auslesen und irgendwie verarbeiten (scancodes oder evtl. sonstige spezial-codes).
    Zum Abschluss immer ACK an das keyboard, indem ein reset ausgefuehrt wird: Kurz aus- und wieder einschalten ueber Port 61h, Bit7. Zum Ende natuerlich noch EOI an den PIC. Ist dann zwar immer noch ziemlich primitiv, sollte so aber zumindest keine Probleme geben...

    abc.w:
    Ich kann nur vermuten, dass einfach (noch?) kein Paging aktiviert ist, mit dem eine Ausnahme beim Zugriff auf einen 0-Pointer ausgeloest wuerde. An der physikalischen Adresse 0 ist nun mal einfach normaler RAM, also an sich kein Problem.


  • Mod

    nasm, dann gcc, dann inline-gcc. Wäre vielleicht sinnvoll, wenn c-Datei, dann C, wenn Assembler-Datei, dann Assembler nasm. Und die Funktionen mit Assembler Inline-Code rein in Assembler implementieren?

    Du hast völlig Recht. Die bisherige "gemischte" Lösung liegt an meinen Problemen mit der AT&T Syntax. Auf der einen Seite ist es wichtig, dass Einsteiger sehen, wie einfach man zwischen C- und ASM-Code hin und her springen kann. Man benötigt nur global, extern und den führenden Unterstrich. Auf der anderen Seite führt dies zu einem Hin- und Hergehüpfe. Ich werde daher versuchen, Deine Idee aufzunehmen. Vielleicht kann Nobuo T da etwas unterstützen. 🙂

    ... statt nasm GNU as zu verwenden, weiss aber jetzt nicht genau, ob man 16-Bit Assembler Quellcode mit as assemblieren kann. Vorteil davon wäre noch, dass man nur ein Tool bräuchte: DJGGP. GNU as ist nämlich in DJGPP mitenthalten.

    Habe mir die Syntax von as bisher noch nicht angeschaut. AT&T?

    Kannst du mal irgendwie ein Verzeichnis oder eine Seite einrichten, wo man waehrend der Entwicklung immer mal die aktuellen Codes runterladen kann?

    @Nobuo T:
    Ja, wird sofort gemacht: Den letzten Code erhält man ab jetzt immer unter diesem Link (wurde aber im Tutorial noch nicht beschrieben, weil er sich im Entwicklungs-/Testzustand befindet; daher sind gute Ideen - wie oben von abc.w zum Thema Exception - immer gerne gesehen. Bitte ausreichend kommentieren.):

    ➡ ➡ ➡ Link zur jeweils aktuellsten Test-Version:
    http://www.henkessoft.de/OS_Dev/Downloads/PrettyOS_last_version.zip

    Was abc.w anspricht ist mein Hin- und Herhüpfen zwischen C-Code (vor allem zum Thema Interrupts) und isr.asm.


  • Mod

    Die Funktion k_null_pointer() wird aber ausgeführt und das System läuft 😕 Oder ist Zugriff mit Offset Null ok 😕

    Ich kann nur vermuten, dass einfach (noch?) kein Paging aktiviert ist, mit dem eine Ausnahme beim Zugriff auf einen 0-Pointer ausgeloest wuerde. An der physikalischen Adresse 0 ist nun mal einfach normaler RAM, also an sich kein Problem.

    Stimmt, Paging wurde noch nicht aktiviert. Das gehört sinnvollerweise als Vorteil zu Multitasking, wenn ich das richtig sehe.

    Klassischerweise macht man das AFAIR so, dass man einen Handler fuer IRQ 1 installiert.

    Richtig, klassischerweise. Aber es geht eben auch ohne Interrupt. Dieses ineffiziente Polling wollte ich zuerst zeigen, damit die Notwendigkeit der Interrupts verständlich wird.

    Diese beiden Punkte bestätigen mich in meiner Vorgehensweise. Ich versuche die didaktische Reihenfolge im Tutorial so aufzubauen, wie man Funktionen/Strukturen in ASM oder C für die beabsichtigte Umsetzung wirklich benötigt. Also pyramidal.

    Die bisherige Reihenfolge war deshalb:

    - Bootbarer Minikernel
    - Bootloader + nachgeladenem Kernel
    - Auf Instruktionen im RM reagieren (dank BIOS einfache Handhabung)
    - A20-Gate und PM aktivieren, GDT/GDTR (das gehört wohl als Minimum zusammen)
    - Sprung vom ASM- zum C-Kernel
    - Rudimentäre Textausgabe auf Bildschirm
    - Rudimentäre Texteingabe mit Tastatur
    - IDT/IDTR, Interrupts, Exceptions allgemein
    - IRQ 0 (System Clock Tick jede 18,22 sec)
    - IRQ 1 (Keyboard, durch Port 0x60 u. 0x64 etwas komplizierter)
    - ... (immer spannend halten) 😉

    Ich kann nur hoffen, dass dieses Konzept sinnvoll ist. 😕

    Was würdet ihr als notwendige nächste "Blöcke" auf die Pyramide wuchten?



  • Erhard Henkes schrieb:

    Klassischerweise macht man das AFAIR so, dass man einen Handler fuer IRQ 1 installiert.

    Richtig, klassischerweise. Aber es geht eben auch ohne Interrupt. Dieses ineffiziente Polling wollte ich zuerst zeigen, damit die Notwendigkeit der Interrupts verständlich wird.

    ehrlich gesagt, würde ich als noob nicht einsehen, wozu man einen dedizierten keyboard-interrupt braucht, wenn man die tastatur auch pollen kann (auch wenn ich verstanden habe, wie interrupts funktionieren). warum sollte polling ineffizient sein? so lange ich die tastatur häufig genug polle, so daß ich mit der tastenfrequenz eines schnellschreibers klar komme, ist die welt doch in ordnung. und wenn mir einer erzählen würde, dass die cpu beim pollen sinnlos zyklen verballert, würde ich antworten: "na und? dann polle ich eben in der timer-isr. ca. 18 anschläge/s als samplingrate sollte doch reichen".
    🙂



  • Erhard Henkes schrieb:

    Was würdet ihr als notwendige nächste "Blöcke" auf die Pyramide wuchten?

    schwer zu sagen. der vollständigkeit halber vielleicht weitere hardwarekomponenten eines 0815-pc's behandeln, wie z.b. ansteuerung/benutzung der RTC, des piezo-piepsers, bustreiber bauen usw. allerdings besteht die gefahr, dass das alles langwierig, kompliziert und langweilig werden kann. vielleicht, um die spannung zu erhalten, das os soweit ausbauen, dass die erste, einfache anwendung laufen kann, z.b ein tetris clone oder so.
    🙂



  • Naja, PIT (und damit auch den speaker) und PIC vielleicht mal kurz anschneiden. Das sollte zur Standard-Peripherie IMHO dann aber wirklich erstmal reichen. Was die OS-Thematik betrifft hast du ja bis jetzt eigentlich wirklich nur ganz vorsichtig an der Oberflaeche gekratzt, weitere Nebensaechlichkeiten wie die RTC oder irgendwelche BUS-Geschichten sollte man da IMHO vermeiden.

    Mein Vorschlag waere als Anschluss an deine Pyramide dann mal langsam in die abstrakteren, eigentlich interessanten Gefilde des OS-Designs einzusteigen. Da ist das Grundlegenste als naechstes vermutlich die dynamische Verwaltung des RAM: Knappe Einfuehrung in die Problematik und Vorstellung einfacher Loesungsansaetze wie Unterteilung des Speichers in Bloecke statischer Groesse (vielleicht praktischerweise gleich 4KB gross 😉 ) und Verwaltung in statischen Arrays, Bitmaps oder dynamischen Free-Lists, Reservierungsstrategie next fit, evtl. ganz knapp noch Wiedereingliederungsproblematik (das weiter auszuwaelzen waere dann IMHO wirklich eher Stoff fuer ein richtiges Buch).
    Weitermachen kannst du dann evtl. mit einer knappen Einfuehrung in Paging. Das spielt schliesslich eigentlich auf fast jeder Multitaskingmaschine eine Rolle.

    Danach koenntest du dich dann vorsichtig an den Komplex Programme, Prozesse und Multitasking herantasten, mit einem knappen Ueberblick zum Thema Prozesserzeugung und Kontextwechsel, Scheduling und Verdraengung.
    Dann vielleicht quasi zum Abschluss noch einen Abstecher zu Privilegien, Adressraumtrennung/Schutzmechanismen und Micro- vs Macro-Kern sowie IPC.


  • Mod

    "na und? dann polle ich eben in der timer-isr. ca. 18 anschläge/s als samplingrate sollte doch reichen".

    EDIT: Die korrekte Frequenz wurde eingefügt, um keinen Verwirrung zu stiften. (thanks to +fricky)
    Der Timer "feuert" mit einer Frequenz von 1193182 Hz / 65536 = 18,2065 Hz. Wenn man nichts anderes machen will als Tippen, ist das Polling sicher o.k. 😃
    Dann stößt man den Keyboard_handler einfach beim Timer_handler mit an. Ich habe das in der Tat genau so gemacht, als ich blöderweise den Tastaturpuffer nicht gelöscht hatte und dadurch kein IRQ1 kam, um zu sehen, ob der Keyboard_handler korrekt funktioniert. Ging tadellos. Von daher könnte man ein IRQ0-gesteuertes Keyboard-Polling als Alternative in Betracht ziehen.
    Wirklichen Sinn macht es aber keinen, weil der Interrupt am Master PIC bereits fest vergeben ist. 😉


  • Mod

    Ich fasse mal die wirklich interessante Taskliste von Nobuo T zusammen:

    - PIC (die beiden PICs wurden bereits beim remapping von IRQ 0-15 verarbeitet)
    - PIT (programmable interval timer)
    - Speaker (ja, BEEP (frequence)! Seit Win NT kaputt wegen Behinderung.)
    - (video.c vernünftig ausbauen, bisher nur rudimentär)
    - OS-Thematik (generell)
    - Dynamische RAM Verwaltung:
    - Unterteilung des Speichers in Blöcke statischer Groesse (4KB)
    - Verwaltung (stat. Arrays, Bitmaps, dynam. Free-Lists)
    - Reservierungsstrategie next fit
    - Wiedereingliederungsproblematik
    - Paging
    - Programme & Prozesse
    - Multitasking vs Singletasking
    - Prozesserzeugung, Kontextwechsel, Scheduling, Verdrängung
    - Privilegien / Schutzmechanismen / Adressraumtrennung
    - Micro- vs Macro-Kernel
    - inter-process communication

    Das wird aber noch einige Zeit brauchen, denn ich möchte dies ja auch praktisch fassbar machen.

    Kleines Übersichtsbild aus Internet:
    http://ezs.kr.hs-niederrhein.de/TreiberBuch/html/os_aufbau.png


  • Mod

    @Nobuo T: Könnte man die isr.asm komplett in die C-Module packen? Ich schaffe das leider syntax-mäßig nicht. Mir gefällt es eigentlich auch so, hier wurde aber mehr Ordnung verlangt. Wie siehst Du das?



  • Ich glaube, der vorrangigste Punkt wäre nun eine Diskussion über die Architektur des OS an sich - und ob und wie solch ein 'Wunsch-OS' auf dem PC realisierbar ist.

    Ich erinnere dabei an den absolut linearen Speicher eines guten alten 68000er-Systems, bei dem z.B. dem Videochip (des Atari) einfach zwei Adressen für den physikalischen und den logischen Bildschirmspeicher mitgeteilt wurden.
    Da gibt es einen massiven Unterschied zum Realmode-PC.
    (Über die Wichtigkeit eines VBL-interrupts möchte ich mich hier gar nicht auslassen - scheinen einige Grafikkartenhersteller immer noch nicht begriffen zu haben.)

    An dieser Stelle spielt nämlich durchaus bereits DMA mit rein.

    Ich möchte die Komplexität an einem kleinen Beispiel festmachen:
    Nehmen wir mal an, ich möchte einen virtuellen Synthesizer mit dem Rechner realisieren. (Etwas, was auf dem Atari kein Problem war, unter DOS gerade noch ging, und unter Windows schon unter die höheren Künste der Programmierung fällt).
    Da gibt es nämlich ein kleines Latenzproblem, dass je nach OS immer größer wird.
    Wir haben einmal ein MIDI IN (könnte ja auch was anderes sein), also einen seriellen Stream, der mir Daten über gewünschte Änderungen (im Sound) liefert.
    Die Software muss nun hingehen, und das Sample berechnen - und diese Daten so schnell wie möglich in den Speicher schreiben, und zwar - und nun kommt's - unmittelbar vor den derzeitigen Lesepunkt des Sound-DMAs!
    Wenn ich - wie ab dem XP - eine 'geschützte' Hardware habe, bin ich auf ein OS angewiesen, was mir entsprechende Funktionen zur Verfügung stellt, die mir solche Aktionen erlauben. Fehlt sowas, kann der Rechner vielleicht wunderbar zig Medien abspielen, aber für diese Anwendung ist er unbrauchbar.

    Oder nehmen wir den Fall Robotik:
    Da wäre es sinnvoller der Applikation die Masse der Rechenzeit zu geben, weil es einfach wichtig ist, dass nichts durch die Lichtschranke flutscht, anstatt nachzuschauen, was gerade im Internet los ist... Also - dynamische konfigurierbare Prioritäten? Sollten vielleicht auch schon im OS stecken.



  • Erhard Henkes schrieb:

    Könnte man die isr.asm komplett in die C-Module packen?

    musstu die doku deines compilers lesen. oft muss man isr's mit einem pseudo-keyword '__interrupt' beginnen. machmal geht's mit einer #pragma-anweisung. ist halt compiler-abhängig.
    🙂

    Bitsy schrieb:

    Da gibt es nämlich ein kleines Latenzproblem, dass je nach OS immer größer wird.
    Wir haben einmal ein MIDI IN (könnte ja auch was anderes sein), also einen seriellen Stream, der mir Daten über gewünschte Änderungen (im Sound) liefert.
    Die Software muss nun hingehen, und das Sample berechnen - und diese Daten so schnell wie möglich in den Speicher schreiben...

    MIDI ist doch ein sau-langsamer bus (32 kbits/s oder so), da kann der computer kaum die bremse sein. eher haste delays, weil der bus selber zu lahm ist. gibt's nicht schon was aktuelleres, als dieses steinzeit-protokoll?
    🙂



  • Erhard Henkes schrieb:

    "na und? dann polle ich eben in der timer-isr. ca. 18 anschläge/s als samplingrate sollte doch reichen".

    Da der Timer alle 18,2 ms mit IRQ0 Alarm schlägt

    wieso haste ihn so schnell eingestellt? normerweise tickert der mit 18.2Hz, nicht kHz.
    🙂


  • Mod

    @+fricky: Ja, Du hast völlig Recht, das habe ich durcheinander gebracht:

    By default, this channel of the timer is set to generate an IRQ0 18.222 times per second.

    Habe das oben korrigiert, um niemanden zu verwirren.

    Im Sourcecode timer.c läuft das zur Zeit so (muss in Bochs nicht exakt stimmen):

    #include "os.h"
    
    int timer_ticks = 0;
    
    /* timer fires 18.222 times per second.*/
    void timer_handler(struct regs* r)
    {
        ++timer_ticks;
        static int z=10;
        if ((timer_ticks % 1093) == 0) // 1093 = 60*18.222
        {
            k_printf("One minute has passed", ++z, 0x0B);
        }
    }
    
    void timer_wait(int ticks)
    {
        unsigned long eticks;
        eticks = timer_ticks + ticks;
        while(timer_ticks < eticks);
    }
    
    void timer_install()
    {
        /* Installs 'timer_handler' to IRQ0 */
        irq_install_handler(0, timer_handler);
    }
    

  • Mod

    dynamische konfigurierbare Prioritäten?

    Das ist ein interessantes Thema. Aber da wird noch viel Code den Compiler durchfließen, bevor ich da anlange.

    Momentan denke ich darüber nach, welche völlig neuen Impulse man setzen könnte, aber zuerst muss man das alte praktisch nachempfinden, sonst fehlt das Verständnis. Die Verschaltung der Hardware macht ja auch gewisse Vorgaben, die man leider akzeptieren muss.



  • Erhard Henkes schrieb:

    void timer_wait(int ticks)
    {
        unsigned long eticks;
        eticks = timer_ticks + ticks;
        while(timer_ticks < eticks);
    }
    

    ^^das sieht nicht überlauffest aus
    🙂


  • Mod

    Was ist schon "überlauffest" auf der Welt?

    #include "os.h"
    
    unsigned long timer_ticks = 0;
    
    /* timer fires 18.222 times per second.*/
    void timer_handler(struct regs* r)
    {
        ++timer_ticks;
        static unsigned long z=10;
        const unsigned long N = 109; // 109 = 60/10*18.222
        if (!(timer_ticks % N))
            k_printf("10 seconds have passed", ++z, 0x0B);
    }
    
    void timer_wait(unsigned long ticks)
    {
        unsigned long eticks;
        eticks = timer_ticks + ticks;
        while(timer_ticks < eticks);
    }
    
    void timer_install()
    {
        /* Installs 'timer_handler' to IRQ0 */
        irq_install_handler(0, timer_handler);
    }
    

    Besser?



  • Erhard Henkes schrieb:

    Besser?

    ist doch immer noch das selbe.
    so z.b:

    unsigned long eticks;
    
    void timer_handler(struct regs* r)
    {
      ...
      if (eticks)
        eticks--;
    }
    
    void timer_wait (unsigned long ticks)
    {
        disable_timer_interrupt();
        eticks = ticks;
        enable_timer_interrupt();
    
        // busy wait...
        while (eticks)
          ;
    }
    

    🙂


  • Mod

    Ja, gute Idee, habe es umgesetzt. Thanks @ +fricky.

    So sieht momentan timer.c aus:

    #include "os.h"
    
    unsigned long timer_ticks = 0;
    unsigned long eticks;
    
    void timer_handler(struct regs* r)
    {
        ++timer_ticks;
        if (eticks)
            --eticks;
    
        //TEST
        char bufferTimerticks[20];            k_itoa (timer_ticks, bufferTimerticks);
    	k_printf("             ",  6, 0x0B);  k_printf(bufferTimerticks, 6, 0x0B);
        char bufferWaitticks[20];         	  k_itoa (eticks, bufferWaitticks);
        k_printf("             ",  7, 0x0B);  k_printf(bufferWaitticks,  7, 0x0B);
        //TEST
    }
    
    void timer_wait (unsigned long ticks)
    {
        timer_uninstall();
        eticks = ticks;
        timer_install();
    
        // busy wait...
        while (eticks)
        {
            k_printf("waiting time runs",   8, 0x0B);
            /* do nothing */;
        };
        k_printf("waiting time has passed", 9, 0x0B);
    }
    
    void sleepSeconds (unsigned long seconds)
    {
        // based upon timer tick frequence of 18.222 Hz
        timer_wait((unsigned long)18.222*seconds);
    }
    
    void timer_install()
    {
        /* Installs 'timer_handler' to IRQ0 */
        irq_install_handler(0, timer_handler);
    }
    
    void timer_uninstall()
    {
        /* Uninstalls IRQ0 */
        irq_uninstall_handler(0);
    }
    

    ckernel.c:

    #include "os.h"
    
    int main()
    {
        k_clear_screen();
    
        // GDT, IDT, ISRS, IRQ, timer, keyboard
        gdt_install();
        idt_install();
        isrs_install();
        irq_install();
        timer_install();
        keyboard_install();
    
    	k_printf("   ************************************************", 0, 0xA);
    	k_printf("   *                                              *", 1, 0xA);
    	k_printf("   *          Welcome to PrettyOS 0.05            *", 2, 0xA);
    	k_printf("   *                                              *", 3, 0xA);
    	k_printf("   *        The C kernel has been loaded.         *", 4, 0xA);
    	k_printf("   *                                              *", 5, 0xA);
    	k_printf("   ************************************************", 6, 0xA);
    
    	update_cursor(8, 0);
            sti();
    	while(TRUE)
    	{
    	    static int zz=10;
    	    sleepSeconds(20);
    	    k_printf("20 sec have passed", ++zz, 0x0B);
    	};
    	return 0;
    };
    

    Es gibt ein offenbar bisher unerkanntes Problem:
    Solange man die Finger vom Keyboard lässt läuft der timer_handler. Sobald man aber die erste Taste nach dem Drücken los lässt, bleibt der Timer (die gezählten timer_ticks) stehen. Nur bei gedrückter Taste läuft er wieder weiter. Rattenscharfer Effekt. 😃

    Allerdings blicke ich momentan nicht durch, warum das passiert. Da fehlt noch einiges im Keyboard-Bereich. Ich habe den Code hoch geladen, damit ihr euch das mal anschauen könnt. 🙂
    http://www.henkessoft.de/OS_Dev/Downloads/PrettyOS_last_version.zip

    Bei Keyboard Port 0x60 u. 0x64 muss ich noch mal richtig lesen. Da klafft noch eine echte Wissenslücke bei mir.

    @Nobuo T: Würdest Du Dir bitte keyboard.c anschauen. Da muss ja der Wurm lauern. Deine konkreten Vorschläge von oben zum Thema Keyboard Controller wurden noch nicht umgesetzt. Mich würde interessieren, was genau den IRQ0 beim Taste-Loslassen "outknockt" und beim Taste-Drücken wieder aktiviert. 😉



  • Ok, mal wieder der Reihe nach:

    Bitsy schrieb:

    Ich glaube, der vorrangigste Punkt wäre nun eine Diskussion über die Architektur des OS an sich - und ob und wie solch ein 'Wunsch-OS' auf dem PC realisierbar ist.

    Ich gehe mal davon aus, dass Erhard sich da schon einen groben Plan gemacht hat, was fuer eine Art von OS er fabrizieren will. Das ob ist da wohl keine Frage, das wie wird hier aktuell diskutiert. 😉

    Was du da weiter anfuehrst, sind doch eher Spezialfaelle und Teilgebiete, des Themenbereichs Scheduling (Echtzeit-Prozesse). Solche Ansaetze wie Prioritaetensteuerung oder verschiedene Ansaetze fairer Ressourcenverteilung mit verschiedensten abgefahrenen queue-Konstrukten (da gibt es wirklich eine Menge weit komplizierteres als einfache Prioritaetensteuerung) kann man da vielleicht in einem Ueberblick kurz anschneiden, aber um den Rahmen nicht zu sprengen, waere mein Vorschlag, sich schliesslich einfach auf Round Robin zu beschraenken.

    Und DMA-Gefrickel ist ja nun voellig abgehoben. Immer im Hinterkopf behalten, dass das ein Internet-Tutorial und kein Kompendium zur OS-Entwicklung werden soll - das wird wie ich das sehe schon so eine ordentliche Portion Stoff. 😃

    [OT]BTW ist das Basteln eines Synths auch auf dem PC selbst unter Windows kein groesseres Problem als unter DOS - solange man gute Hardware (am besten mit HW Wavetable Synth) oder zumindest sehr gute Treiber (zumindest directX) hat.[/OT]

    Erhard Henkes schrieb:

    Würdest Du Dir bitte keyboard.c anschauen. Da muss ja der Wurm lauern. Deine konkreten Vorschläge von oben zum Thema Keyboard Controller wurden noch nicht umgesetzt. Mich würde interessieren, was genau den IRQ0 beim Taste-Loslassen "outknockt" und beim Taste-Drücken wieder aktiviert. 😉

    Scharfer Effekt -> reichlich daemlicher Fehler, wenn ich mich nicht verschielt habe:
    FetchAndAnalyzeScancode landet in einer Endlosschleife, wenn eine Taste losgelassen wird. Mal abgesehen von dem fehlenden EOI an den PIC duerfte das geloeschte IF wohl ausschlaggebend dafuer sein, dass sich in diesem Fall dann so lange nichts mehr tut, bis du wieder eine Taste drueckst.

    Kurz: Die Endlosschleife hat in FetchAndAnalyzeScancode nichts zu suchen.

    BTW: Ich hatte in meiner Auflistung noch vergessen, sich mal mit der Kernel-API (und einem HW-Abstraktions/Treiber-Prinzip) deines OS zu befasssen. Alle Kernel-Funktionen, Treiber etc. einfach nur ueber C-Funktionen und header zur Verfuegung zu stellen ist sicher nicht das Wahre. 🙂
    Ich wuerde die Einrichtung eines kleinen Sets der wichtigsten Funktionen zum I/O und spaeter dann Speicher- und Prozessverwaltung ueber Interrupts aehnlich DOS oder Linux vorschlagen.

    Je nachdem, was fuer einen Kern du basteln willst (Micro oder Monolith), waere es evtl. sinnvoll, das schon ganz am Anfang beim Aufbauen der ersten abstrakteren OS-Funktionen wie RAM-Verwaltung zu diskutieren, statt erst bei Adressraumtrennung, Privilegien und IPC. Evtl. mit Verweis auf diese spaeteren Themen zur Begruendung.


Anmelden zum Antworten