'#################################################################################################################### '### freeBASIC based x86-KERNEL '#################################################################################################################### '### (c) 2008 DeltaLab's Germany '### By.: Martin Wiemann '#################################################################################################################### '#################################################################################################################### '== So wird der Source Compiliert == 'fbc -c .bas 'ld -Ttext=0x100000 .o -o '#################################################################################################################### '#################################################################################################################### 'Für Spätere Zwecke gibt es hier eine Variable zum aktivieren des Grafischen Modus (Pixel zeichen) Dim Shared G_Video_GFX_Mode as UByte: G_Video_GFX_Mode = 0 'Konstanter Wert von 25 Zeilen im Textmodus Const G_Video_Text_Row as UByte = 25 'Konstanter Wert von 80 Spalten im Textmodus Const G_Video_Text_Col as UByte = 80 'Der Text-Speicherbereich beginnt bei &Hb8000 ... Sollte sich das (warum auch immer) mal ändern Const G_Video_Text_PTR_Base as UByte Ptr = &Hb8000 'Die aktuelle Zeile wird durch diese Variable gehalten Dim Shared G_Video_Text_Pos_Row as UShort 'Das gleiche mit der Spalte Dim Shared G_Video_Text_Pos_Col as UShort 'Dieses Array definiert den Speicherbereich des Text-Modes. Auf diesen Kann man anschliessend direkt zugreifen Dim Shared G_Video_Text as UShort Ptr: G_Video_Text = Cast(UShort Ptr, G_Video_Text_PTR_Base) 'Diese Variable merkt sich, ob der Cursor sichtbar ist oder nicht Dim Shared G_Video_Cursor_Show as UByte: G_Video_Cursor_Show = 1 '#################################################################################################################### 'Schreibt einen Wert (V_Value) an die Adresse (V_Port) Sub outb(ByVal V_Port as UShort, ByVal V_Value as UByte) Asm mov edx, DWord Ptr [V_Port] mov eax, DWord Ptr [V_Value] out dx, al End Asm End Sub '-------------------------------------------------------------------------------------------------------------------- 'Liest einen Wert (Return) von der Adresse (V_Port) Function inb(ByVal V_Port as UShort) as UByte Dim T as UByte ASM mov edx, DWord Ptr [V_Port] in al, dx mov [T], al END ASM Return T End Function '#################################################################################################################### '[Intern] Setzt den Cursor an eine angegebene Stelle in dem Text Sub Int_Text_Cursor_Move(V_Row as UShort, V_Col as UShort) 'Zuerst wird geprüft ob der Grafische Modus aktiv ist, Wenn ja: Dann Sub Verlassen If G_Video_GFX_Mode <> 0 Then Exit Sub 'Prüfen ob sich die neue Position auserhalb des gültigen Bereichs befindet If V_Row > G_Video_Text_Row Then Exit Sub If V_Col > G_Video_Text_Col Then Exit Sub 'Durch das Verschieben des Cursors wird dieser automatish sichtbar gemacht 'Darum müssen wir diesen Status wieder aktivieren G_Video_Cursor_Show = 1 'Aktuelle Cursorposition zum Schreiben von Text speichern G_Video_Text_Pos_Row = V_Row G_Video_Text_Pos_Col = V_Col 'Die 'Längsposition' im Speicher errechnen Dim TLP as UShort = V_Row * G_Video_Text_Col + V_Col 'Das HighByte der Position setzen outb(&H3D4, 14) outb(&H3D5, (TLP shr 8)) 'Das LowByte der Position setzen outb(&H3D4, 15) outb(&H3D5, TLP) End Sub '-------------------------------------------------------------------------------------------------------------------- '[Intern] Macht den Cursor 'unsichtbar' Sub Int_Text_Cursor_Hide() 'Da der Cursor nicht 'abschaltbar' ist verschieben wir diesen einfach an eine Stelle 'die nicht sichbar ist. G_Video_Cursor_Show = 0 'Die 'Längsposition' im Speicher errechnen ( + 1 um ihn auserhalb zu platzieren) Dim TLP as UShort = G_Video_Text_Row * G_Video_Text_Col + 1 'Das HighByte der Position setzen outb(&H3D4, 14) outb(&H3D5, (TLP shr 8)) 'Das LowByte der Position setzen outb(&H3D4, 15) outb(&H3D5, TLP) End Sub '-------------------------------------------------------------------------------------------------------------------- '[Intern] Macht den Cursor wieder 'sichtbar' Sub Int_Text_Cursor_Show() 'Cursorstatus setzen G_Video_Cursor_Show = 1 'Die Alte Position haben wir und noch 'gemerkt'. Darum brauchen wir diese nur zu setzen Int_Text_Cursor_Move(G_Video_Text_Pos_Row, G_Video_Text_Pos_Col) End Sub '#################################################################################################################### '[Intern] Löschen des gesammten Bildschirms Sub Int_Text_CLS() 'Zuerst wird geprüft ob der Grafische Modus aktiv ist, Wenn ja: Dann Sub Verlassen If G_Video_GFX_Mode <> 0 Then Exit Sub 'Idealerweise würde man hier in FB das 'Clear' verwenden. Da es jedoch ein OS Spezifischer Befehl ist 'müssen wir das Leeren von 'Hand' durchführen. For Y as UShort = 0 to G_Video_Text_Row - 1 For X as UShort = 0 to G_Video_Text_Col - 1 'Wir schreiben eine 0 an die aktuelle Speicheradresse. Da das Array aus UShort's 'besteht überschreiben wir dadurch nicht nur das Zeichen sondern auch den Farbcode 'Wir 'Leeren' den Speicher allerdings nicht mit einer Leeren Farbe, sondern mit dem 'Standardgrau. Wenn wir dies nicht tuen würdn, könnten wir den Cursor nicht mehr sehen. G_Video_Text[Y * G_Video_Text_Col + X] = &H07 * 256 'Dies wiederhohlen wir solange, bis alle Adressen mit '0' gefüllt sind. Next Next 'Zum schluss setzen wir noch die Aktuelle Schreibposition zurück G_Video_Text_Pos_Row = 0 G_Video_Text_Pos_Col = 0 'Und ie neue Position mit der Cursorpositin abgleichen If G_Video_Cursor_Show = 1 Then Int_Text_Cursor_Move(G_Video_Text_Pos_Row, G_Video_Text_Pos_Col) End Sub '-------------------------------------------------------------------------------------------------------------------- '[Intern] Um Text auf den Bildschirm zu schreiben Sub Int_Text_Print(ByVal V_Text as String = "", ByVal V_ByteCode as UByte = 0) 'Zuerst wird geprüft ob der Grafische Modus aktiv ist, Wenn ja: Dann Sub Verlassen If G_Video_GFX_Mode <> 0 Then Exit Sub 'Eine Variable, welche uns den Pointer auf den Text / den ByteCode bereitstellt Dim XTextPtr as UByte Ptr 'Anschliessend Prüfen wir, ob der Nutzer Text oder den Code verwendet 'Auch hier können wir nicht mit V_Text = "" arbeiten, da dies wieder eine OS Spezifische 'überprüfugn wäre. Darum müssen wir prüfen, ob der Variable ein Speicherbereich zugeordnet wurde If V_ByteCode > 0 Then 'Offensichtlich will er den ByteCode nutzen. (Ein ByteCOde von 0 ist als Ausgabe nicht in verwendung) XTextPtr = @V_ByteCode Else 'Andernfalls benötigen wir den Pointer auf unseren Text XTextPtr = StrPtr(V_Text) End If 'Da wir nicht wissen, was sich in der Text Variable für zeichen befinden, 'müssen wir diese Schritt für Schritt abarbeiten Do 'Jetzt selectieren wir das Zeichen nach seiner funktion Select Case *XTextPtr Case 10 'Linefeed (Es wird in die nächste Zeile gesprungen) 'Um einen Linefeed zu erzeugen müssen wir zuerst herausfinden, ob wir uns am Ende bzw. 'Kurz davor, im Speicher, befinden oder nicht. If G_Video_Text_Pos_Row + 1 = G_Video_Text_Row Then 'Wenn ja, dann müssen wir die Daten im Speicher verschieben 'Wir beginnen bei der 2ten Zeile um alles nach oben zu rücken For Y as UShort = 1 to G_Video_Text_Row - 1 For X as UShort = 0 to G_Video_Text_Col - 1 'Jetzt Kopieren wir Die Daten aus Zeile Y in die Zeile Y - 1 G_Video_Text[(Y - 1) * G_Video_Text_Col + X] = G_Video_Text[Y * G_Video_Text_Col + X] 'Dies wiederhohlen wir solange, bis alle Adressen mit '0' gefüllt sind. Next Next 'Selbstverständlich müssen wir auch die 'neue' Zeile leeren For X as UShort = 0 to G_Video_Text_Col - 1 G_Video_Text[(G_Video_Text_Row - 1) * G_Video_Text_Col + X] = 0 Next Else 'Wenn nicht, dann können wir einfach zur nächsten Zeile springen G_Video_Text_Pos_Row += 1 End If 'Ein LineFeed beinhaltet NICHT das Zurücksetzen des Cursors auf den Zeilenanfang Case 13 'Carrier Return (Der Cursor soll an den Anfang der zeile zurück) 'Der Carrier Return ist ausschliesslich!!! ein Zurückfahren des Cursors! Kein Linefeed! G_Video_Text_Pos_Col = 0 Case Else 'Andere Zeichen (welche dargestellt werden sollen) 'Hier prüfen wir, ob wir uns noch in einem zulässigem Bereich des Speichers befinden 'Wir müssen jedoch nicht überprüfen, ob wir einen Carrier Return durchführen müssen 'da unser Speicher Linear (Sprich: durchgängig) ist, und das nächste Zeichen der 'nächsten Zeile das darauffolgende im Speicher ist. If G_Video_Text_Pos_Col = G_Video_Text_Col Then 'Die Zeile scheint auserhalb zu sein. Darum müssen wir hier einen LineFeed durchführen 'Um einen Linefeed zu erzeugen müssen wir zuerst herausfinden, ob wir uns am Ende bzw. 'Kurz davor, im Speicher, befinden oder nicht. If G_Video_Text_Pos_Row + 1 = G_Video_Text_Row Then 'Wir beginnen bei der 2ten Zeile um alles nach oben zu rücken For Y as UShort = 1 to G_Video_Text_Row - 1 For X as UShort = 0 to G_Video_Text_Col - 1 'Jetzt Kopieren wir Die Daten aus Zeile Y in die Zeile Y - 1 G_Video_Text[(Y - 1) * G_Video_Text_Col + X] = G_Video_Text[Y * G_Video_Text_Col + X] 'Dies wiederhohlen wir solange, bis alle Adressen mit '0' gefüllt sind. Next Next 'Selbstverständlich müssen wir auch die 'neue' Zeile leeren For X as UShort = 0 to G_Video_Text_Col - 1 G_Video_Text[(G_Video_Text_Row - 1) * G_Video_Text_Col + X] = 0 Next Else 'Wenn nicht, dann können wir einfach zur nächsten Zeile springen G_Video_Text_Pos_Row += 1 End If 'Da es sich hier um einen 'Zeilenumbruch' handelt, müssen wir auch die Spalte zurücksetzen G_Video_Text_Pos_Col = 0 End If 'Da wir in einem Gültigem Bereich sind können wir das Zeichen jetzt dort Platzieren 'Gleichzeitig schreiben wir noch die neue Farbe mit hinein G_Video_Text[G_Video_Text_Pos_Row * G_Video_Text_Col + G_Video_Text_Pos_Col] = &H07 * 256 + *XTextPtr 'Nachdem auch dies geschaft ist, Platzieren wir uns auf dem nächsten Zeichenspeicher G_Video_Text_Pos_Col += 1 End Select 'Wenn der Cursor sichtbar ist, dann müssen wir diesen Verschieben If G_Video_Cursor_Show = 1 Then Int_Text_Cursor_Move(G_Video_Text_Pos_Row, G_Video_Text_Pos_Col) 'Ist die String Variable leer, dann will der Benutzer offensichtlich ein ByteCode einfügen darum 'können wir nach dem ersten durchlauf die Schleife verlassen If @V_Text = 0 Then Exit Do 'Wir springen zum nächsten Textzeichen XTextPtr += 1 'Und prüfen, ob er noch gültige Zeichen enthält. Andernfalls verlassen wir auch hier die Schleife If *XTextPtr = 0 Then Exit Do Loop End Sub '#################################################################################################################### 'Erstmal den Bildschirm leeren. Das ist nötig da unser Bootloader (GRUB) da noch einiges drauf schreibt Int_Text_Cls() 'Dann geben wir unseren Text aus Int_Text_Print("Hallo Meister!") 'Und noch ein CR Int_Text_Print(, 13) 'und ein LF .. was zusammen einen 'Zeilenumbruch auslöst' Int_Text_Print(, 10) 'Wir verstecken den Cursor für einen augenblick Int_Text_Cursor_Hide() 'Um Ihn gleich wieder sichtbar zu machen Int_Text_Cursor_Show() 'Das is zwar sinnfrei, da man das wohl kaum sehen wird, aber es zeigt, was einem zur verfügung steht :) 'Noch eine Endlosschleife, damit das Prog nicht gleich wieder beendet wird. Do Loop 'Ein 'End' ist hier übrigens nicht möglich, da dieser Befehl OS spezifisch ist. '#################################################################################################################### '!!!!!!! Es ist SEHR wichtig, das diese Zeilen AM ENDE!!! des Quellcodes stehen, '!!!!!!! da der Source sonst nicht funktioniert!!!!!!! '#################################################################################################################### CONST mb_magic = &H1BADB002 CONST mb_flags = 3 '-------------------------------------------------------------------------------------------------------------------- ASM .global _start _start: call fb_ctor__kernel jmp $ fb_RtInit: ret mb_header: .align 4 .int mb_magic .int mb_flags .int -mb_magic-mb_flags END ASM