Buchempfehlung
Windows System Programming
Windows System Programming
Das Kompendium liefert viele interessante Informationen zur Windows-Programmierung auf Englisch. [Mehr Infos...]
FreeBASIC-Chat
Es sind Benutzer im FreeBASIC-Chat online.
(Stand:  )
FreeBASIC bei Twitter
Twitter FreeBASIC-Nachrichten jetzt auch über Twitter erhalten. Follow us!

fb:porticula NoPaste

Info
Info / Hilfe
Liste
Übersicht / Liste
Neu
Datei hochladen
Suche
Quellcode suchen
Download
Dateidownload

kernel.bas

Uploader:MitgliedThePuppetMaster
Datum/Zeit:16.08.2008 17:25:03

'####################################################################################################################
'### freeBASIC based x86-KERNEL
'####################################################################################################################
'### (c) 2008 DeltaLab's Germany
'### By.: Martin Wiemann
'####################################################################################################################



'####################################################################################################################
'== So wird der Source Compiliert ==
'fbc -c <FileName>.bas
'ld -Ttext=0x100000 <FileName>.o -o <BinarayFileName>
'####################################################################################################################





'####################################################################################################################
'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