Seitenleiste

Tutorial

Infodatenbank

Community

Ausgabe auf den Bildschirm

Damit wir auch mitverfolgen können, was unser Kernel denn gerade tut, ist es hilfreich, wenn wir Text auf den Bildschirm ausgeben können. Haben wir Funktionen dafür, so sind wir in der Lage, Debug- oder Statusinformationen auszugeben.

Wir haben schon einen Buchstaben auf den Monitor ausgegeben…
Dazu haben wir den Buchstaben zusammen mit einer anderen Zahl an eine Speicherstelle geschrieben.

Wichtig ist, dass es nicht irgendeine Speicherstelle war, sondern eine ganz bestimmte. Wir haben in den Speicherbereich 0xB8000 geschrieben. Dies ist der Speicherbereich, von dem aus der Bildschirminhalt für den sog. Color Text Mode gelesen wird. Im Color Text Mode wird, wie der Name schon sagt, farbiger Text ausgegeben.
Andere Modi sind z.B. der Monochrome Text Mode auf 0xB0000 (Einfarbiger Text) oder auch der Graphical Mode auf 0xA0000.

Diese Art, durch Manipulieren eines gewissen Speicherbereichs Hardware (der Monitor) zu kontrollieren, nennt man Memory Mapped I/O.

Wie funktioniert das?

Wir haben eine Adresse, an der unser Videospeicher sitzt. Schreiben wir dorthin Informationen, so werden sie auf dem Bildschirm angezeigt.

Wir müssen die Informationen natürlich auch in der richtigen Reihenfolge auf den Speicher schreiben. Dazu müssen wir wissen, wie dieser Speicherbereich aufgebaut ist.

Das Prinzip

Wir haben einen Bildschirm. Dieser hat 25 Zeilen. Jede Zeile ist 80 Zeichen breit. Heißt wir haben 25 * 80 = 2000 Zeichen.

Ein Zeichen… was ist das eigentlich?

Ein Zeichen ist im Endeffekt nur ein Byte mit einer darin gespeicherten Nummer. Die Nummer wird dann in einen Buchstaben o.ä. verwandelt.

Nun haben wir schon gelernt, dass wir uns im Color Text Mode befinden. Die Information über den Text haben wir, fehlt also noch die Farbe.

Die Farbe wird auch wieder über ein Byte gesteuert. In diesem Byte stehen Informationen über Vordergrund- und Hintergrundfarbe. Wir können das Zeichen auch Blinken lassen. Die Info dazu gehört hier auch hinein.

Zu jedem Zeichen benötigen wir also ein Byte, das aussagt, welches Zeichen (Buchstabe, Zahl) geschrieben werden soll und ein Byte, das Aussage über Farbe von Zeichen und Hintergrund gibt.
2000 Zeichen mit je 2 Byte ergibt damit 4000 Byte Speicher den wir benötigen.

Nun müssen wir nur noch wissen, wie die Informationen für Zeichen und Farbe angeordnet sind. Das verrate ich gleich:

Es ist immer ein Byte für das Zeichen, dann ein Byte für Informationen über Farbe etc, dann wieder ein Byte für das nächste Zeichen, usw…

In der Praxis

In der Praxis definieren wir einen Zeiger auf den Speicherbereich (0xB8000). Diesen Zeiger definieren wir als unsigned short, heißt wir schreiben immer 2 Byte auf den Speicher.

Wollen wir nun ein Zeichen schreiben, müssen wir wissen, wo wir zuletzt geschrieben haben (sonst überschreiben wir ja was). Dazu legen wir uns zwei Variabeln an, eine für die Position in X-Richtung (rechts) und eine für die Position in Y-Richtung (unten).

Zur Startadresse müssen wir nun nur ein entsprechendes Offset addieren, um an einer festgelegten Stelle schreiben zu können. Das Offset berechnet sich folgendermaßen:

unsigned short offset = Cursor_Y * 80 + Cursor_X;

Die Y-Position müssen wir mit 80 multiplizieren, da eine Zeile 80 Zeichen breit ist.

Nun können wir die genaue Speicherstelle adressieren, an die unser Zeichen kommen soll und das Zeichen mit den Attributen an diese Stelle schreiben:

unsigned short *pos = (unsigned short *)(0xB8000 + offset);
unsigned char wChar = 'A';
unsigned char Attribut = 0x0F;
*pos = (wChar) | (Attribut << 8);

FIXME (weiter)