Chars (PI5): Unterschied zwischen den Versionen

Aus C und Assembler mit Raspberry
KKeine Bearbeitungszusammenfassung
KKeine Bearbeitungszusammenfassung
Zeile 121: Zeile 121:


Mein Beispiel für den Font habe ich als "ms8x8font.fon" im Includeverzeichnis abgelegt.
Mein Beispiel für den Font habe ich als "ms8x8font.fon" im Includeverzeichnis abgelegt.
=== Font-Erstellen ===
Nun kümmern wir uns darum, dem Computer beizubringen, wie die einzelnen Zeichen aussehen. Dazu erstellen wir eine Art Datenbank, in der jedes Zeichen beschrieben wird, wie es aussieht.Wie bereits zuvor erwähnt, müssen wir selbst einen Zeichentabelle erstellen, in der wir festlegen, wie jedes einzelne Zeichen aussieht. Zur Einfachheit werden wir nur eine 8x8 Matrix verwenden.
Dazu erstellen wir nun eine Datei, die dem folgendem Aussehen entspricht:
<syntaxhighlight>
Dimension
  INT X
  INT Y
Data
  Binärcode
</syntaxhighlight>
Zunächst geben wir die Größe der Zeichen in X und Y an. Daraus können wir zur Berechnung der einzelnen Zeichen der entsprechenden Binärcode ausgelöst werden. Hier steht jedes Bit, das gesetzt ist, für ein Pixel, welches gezeichnet werden soll.
Umgesetzt in Code, sieht es dann so aus:
<syntaxhighlight lang="asm">
/* 8x8 FONT by Satyria */
@ Dimension
.int 8 @ x
.int 8 @ y
@ Data
@ 0: NULL
.byte 0b00000000
.byte 0b00000000
.byte 0b00000000
.byte 0b00000000
.byte 0b00000000
.byte 0b00000000
.byte 0b00000000
.byte 0b00000000
...
...
@ 65: "A"
.byte 0b00011000
.byte 0b00111100
.byte 0b00111100
.byte 0b01100110
.byte 0b01111110
.byte 0b11000011
.byte 0b11000011
.byte 0b00000000
@ 66: "B"
...
...
</syntaxhighlight>


=== Font-Anzeigen lassen ===
=== Font-Anzeigen lassen ===
Zeile 245: Zeile 194:
Nun müssen wir jedes Bit dieser Font-Matrix auswerten. Dazu verwenden wir folgende Formel: (Zeile >> (7 - BitPos)) & 1;
Nun müssen wir jedes Bit dieser Font-Matrix auswerten. Dazu verwenden wir folgende Formel: (Zeile >> (7 - BitPos)) & 1;


Wir lesen zunächst das Byte heraus, was wir mit w11 (Zeile) definiert haben. Dies machen wir mit dem Befehl ldrb w13,[x10,x11]. Dies bedeutet das wir aus dem Speicher das Byte lesen, welches im Speicher an x10 steht und addieren dort den Offset von x11 dazu. Den Wert schreiben wir nach w13. Da wir das Ergebnis falsch herum bekomme, ziehen wir von der 7 (1. Bit = 0) die BitPos ab, die wir in der Schleife mit w12 definiert haben. Verschieben damit dann das Byte
Wir lesen zunächst das Byte heraus, was wir mit w11 (Zeile) definiert haben. Dies machen wir mit dem Befehl ldrb w13,[x10,x11]. Dies bedeutet das wir aus dem Speicher das Byte lesen, welches im Speicher an x10 steht und addieren dort den Offset von x11 dazu. Den Wert schreiben wir nach w13. Da wir das Ergebnis falsch herum bekommen, ziehen wir von der 7 (1. Bit = 0) die BitPos ab, die wir in der Schleife mit w12 definiert haben. Verschieben damit dann die Bits im Byte um die Positionen mit lsr nach rechts und mit "and" löschen wir alle höherwertigen Bits, bis auf das erste.
 
Nun können wir das Ergebnis auswerten. Wenn der Wert gleich Null ist, dann zeichne ein Pixel in der Hintergrundfarbe, ansonsten in der Vordergrundfarbe.


 
Hier der gesamte Code für die DrawChar-Funktion:
Wir müssen, um den Font zu zeichnen, eine Schleife bilden, in der wir die Daten auswerten. Um eine Ende der Schleife zu definieren, verwenden wir die Y-Position. Da der Font 8 Pixel hoch ist, addieren wir einfach acht hinzu. Wenn wir später diesen Wert erreicht haben, haben wir auch das gesamte Zeichen gemalt.
 
Unser Font haben wir in Binärform erstellt. Das Bedeutet, wenn wir nun die Daten Auswerten, müssen wir hier auch in Binär denken.


<syntaxhighlight lang="asm">
<syntaxhighlight lang="asm">
  mov r10,#8
//void DrawChar(char c, u32 x0, u32 y0)
</syntaxhighlight>
//Zeichnet einen Char an die Position x0, y0 auf den Screen
.globl DrawChar
DrawChar:
stp x29, x30, [sp, -16]!
stp x20, x21, [sp, -16]!
stp x10, x11, [sp, -16]!
stp x12, x13, [sp, -16]!
stp x14, x15, [sp, -16]!
mov x29, sp
    Sichere zunächst die Position
mov w20,w1 // x0
mov w21,w2 // y0


In r10 legen wir die Position des Pixels ab, den wir überprüfen und eventuell dann zeichnen werden. Damit wir einen einzelnen Bit prüfen können, verwenden wir r10 und eine Shift-Operation.
    //Berechne den Zeiger auf das richtige Zeichen
ldr x10,=font
lsl w0,w0,#3
add x10,x10,x0


Zunächst laden wir das gesammte Byte aus dem Speicher nach r0.
    //for (w11 = 0; w11 < FONT_HEIGHT; w11++)
mov w11,#0
1:
cmp w11,#FONT_HEIGHT
bge 2f


<syntaxhighlight lang="asm">
    //for (w12 = 0; w12 < FONT_WIDTH; w12++)
DrawCharLoop1:
mov w12,#0
  ldrb r0,[r7] 
3:
  lsr r0,r10   
cmp w12,#FONT_WIDTH
  and r0,#1     
bge 4f
  cmp r0,#1     
</syntaxhighlight>


Da wir in r10 die Position gespeichert haben, um die Position des entsprechenden Pixel auszuwerten, schieben wir einfach die Bits mit der Anzahl aus r10 nach rechts. Damit steht das eigentliche Bit, welches wir auswerten wollen, an der Position "0" im Byte. Damit der Wert dann noch auswertbar wird, verwenden wir ein "and" und löschen damit alle Bits oberhalb des unteren Bits. Nun können wir den Wert einfach mit #1 vergleichen.
    //Überprüfe das Bit nach folgender Formel:
    //(Zeile >> (7 - BitPos)) & 1;
ldrb w13,[x10,x11]
mov w14,#7
sub w14,w14,w12
lsr w13,w13,w14
and w13,w13,#1
    //Wenn Ergebniss 0 ist, dann Hintergrund zeichnen
cbz w13,5f


<syntaxhighlight lang="asm">
    //Ansonsten in der Vordergrundfarbe
  bne DrawCharSkip1
ldr x13,=FrontColor
      mov r0,r5 
ldr w13,[x13]
      mov r1,r6
ldr x14,=DrawColor
      bl DrawPixel
str w13,[x14]
  DrawCharSkip1:
b 6f
</syntaxhighlight>
5:
ldr x13,=BackColor
ldr w13,[x13]
ldr x14,=DrawColor
str w13,[x14]


Wenn hier nun keine #1 steht, überspringen wir einfach die "DrawPixel"-Funktion. Ansonsten übergeben wir die Positionen von x und y und zeichnen einen Punkt.
6:
    //Zeichne den Pixel an die Position
mov w0,w12
add w0,w0,w20
mov w1,w11
add w1,w1,w21
bl DrawPixel


Wenn wir dies soweit haben, müssen wir unsere Werte, die wir für die Auswertung benutzen, entsprechend anpassen.
    //end_for w12
 
add w12,w12,#1
<syntaxhighlight lang="asm">
b 3b
  add r5,#1    
4:
  sub r10,#1   
    //end_for w11
  cmp r10,#-1   
add w11,w11,#1
  bne DrawCharSkip2
b 1b
      add r7,#1 
2:
      mov r10,#8 
ldp x14, x15, [sp], 16
      sub r5,#9 
ldp x12, x13, [sp], 16
      add r6,#1 
ldp x10, x11, [sp], 16
DrawCharSkip2:
ldp x20, x21, [sp], 16
ldp x29, x30, [sp], 16
ret
</syntaxhighlight>
</syntaxhighlight>


Zunächst erhöhen wir die Position X um eins, für das nächste Pixel. Subtrahieren die Shiftposition um eins und vergleichen dann diesen Wert. Wenn dieser nicht negativ wurde, überspringen wir den nächsten Teil. Sollte er negativ sein, so haben wir eine Zeile komplett ausgewertet.
Um das nun zu testen, ob es geht, müssen wir unser main-Programm ändern:
In diesem Fall, müssen wir einige Werte anpassen, damit wir dann die nächste Zeile anzeigen können. Dazu erhöhen wir zunächst den Zeiger auf den Font um eins, unseren Shiftwert setzen wir wieder auf acht und setzen X wieder zurück zum Ausgangswert. Y erhöhen wir um eins, für die nächste Zeile.
 
Das nächste, was wir prüfen müssen, ist, wenn wir nun das Ende des Fonts erreicht haben. Dies Bedeutet, dass das komplette Zeichen angezeigt wurde.


<syntaxhighlight lang="asm">
<syntaxhighlight lang="asm">
  cmp r6,r9   
//
  popcs {r4,r5,r6,r7,r8,r9,r10,pc}
// kernel.S
  b DrawCharLoop1 
//
</syntaxhighlight>


In r9 hatten wir das Ende des Fonts abgelegt und wir vergleichen nun einfach diese Position mit der aktuellen Y Position. Wenn dieser Unterschied Größer oder gleich ist, wird die Funktion beendet. Wenn nicht, wird einfach die Schleife wiederholt.
.section .text
.globl main
main:


Juhu, wir haben es geschafft. Nun wollen wir aber diese Funktion testen. Also schreiben wir unser Hauptprogramm um.
    bl LED_off
bl Init_Screen


<syntaxhighlight lang="asm">
mov w10,#33
main:            
mov w11,#100
  mov sp,#0x8000
2:
cmp w10,#90
bge 1f
mov w0,w10
mov w1,#100
mov w2,w11
bl DrawChar
add w11,w11,#10
add w10,w10,#1


  bl FB_Init 
b 2b
 
1:
  mov r0,#0xff 
mov w0,#2
  mov r1,#0x00
bl LED_Error
  mov r2,#0xff
999:
   bl SetColor
   b 999b
</syntaxhighlight>
</syntaxhighlight>


Zunächst erstellen wir unseren Screen und setzen die Farbe auf Pink.
Wie zuvor schon, schalten wir wieder unsere LED aus, um einen Ausgangszustand zu haben. Initialiesieren unseren Screen und erzeugen dann eine Schleife, die von 33 bis 90 zählt. Diesen Wert übergeben wir der DrawChar-Funktion in w0. Zusätzlich geben wir ihr die Koordinaten für den "Char" in w1 (immer 100) und w2 (jeweils um 10 erhöht) mit. Am ende unseres Programms gehen wir wieder in den Fehlercode 2, damit wir sehen, dass er alles abgearbeitet hat.
 
Unser Ziel wird sein, dass wir alle Zeichen anzeigen lassen, die wir in der Font-Liberay erstellt haben.
 
<syntaxhighlight lang="asm">
  mov r4,#0   
  mov r5,#16
  mov r6,#16
  mov r7,#350
  mov r8,#500
</syntaxhighlight>
 
In r4 legen wir einen Zähler an, der jedes Zeichen repräsentiert. Zunächst wird der Wert auf null gesetzt, was dem ersten Zeichen entspricht.
Um nicht aus dem Bereich der Anzeige zu kommen, werden wir die Zeichen in einem 16 x 16 Gitter setzen. Die Positionen sind in r5 und r6 abgelegt.
In r7 und r8 sind die Startkoordinaten für unser Feld abgelegt.
 
<syntaxhighlight lang="asm">
loop:           
  mov r0,r4
  mov r1,r7
  mov r2,r8
  bl DrawChar
</syntaxhighlight>
 
Mit einem einfache Übertrag vom Zeichen und der Position übergeben wir unserer neuen "DrawChar"-Funktion das Zeichen und lassen es uns anzeigen.
 
<syntaxhighlight lang="asm">
  add r4,#1
  add r7,#10
  sub r5,#1
  cmp r5,#0
  bne loop
</syntaxhighlight>
 
Im Anschluss erhöhen wir den Zeichenzähler (r4) um eins, Setzen die X Position um 10 hoch. Und reduzieren die X-Position unseres Gitters um eins. Solange dieser Wert nicht die Null erreicht hat, wird nun die Schleife ausgeführt.
 
Wenn nicht:
 
<syntaxhighlight lang="asm">
  add r8,#10
  mov r7,#350
  mov r5,#16
  sub r6,#1
  cmp r6,#0
  beq skip
  b loop
skip:
</syntaxhighlight>
Die Position von Y wir um 10 erhöht und die Position X auf den Ausgangswert (350) gesetzt. In unserem Gitter fangen wir für die X-Position wieder von vorne an und die Y-Position wird um eins reduziert. Wenn nun die Y-Position null erreicht haben wir 256 Zeichen dargestellt und sind fertig. Wenn noch nicht, wird die Schleife einfach wiederholt.

Version vom 13. August 2024, 09:40 Uhr

DrawChar auf dem Raspberry Pi

Wir haben nun eine Pixel-Funktion geschrieben, aber möchten wir nicht auch, dass der Raspberry Pi Informationen direkt auf dem Bildschirm anzeigen kann? Das wollen wir jetzt versuchen. In der Regel kommuniziert der Computer mittels Schriftzeichen. Dies geschieht nicht einfach so; ähnlich wie ein Mensch muss der Computer zuerst lernen, wie jeder einzelne Buchstabe aussieht. Außerdem muss er wissen, wann er das entsprechende Zeichen verwenden soll. Bestimmte Bytewerte stehen für bestimmte Zeichen oder Steuercodes. Es gibt einen Standard, der diese Kommunikation festlegt. Dieser Code nennt sich "ANSI-Zeichencode".

Der ANSI-Zeichencode

Der ANSI-Zeichencode, den wir hier verwenden, ist eine Erweiterung des ASCII-Codes, bei dem von 7-Bit pro Zeichen auf 8-Bit pro Zeichen umgestellt wurde, was einem Byte entspricht. Der ANSI-Zeichencode wurde eingeführt, als Computeranwender über Netzwerke kommunizieren wollten. Dafür war es notwendig, dass beide Computer mit dem gleichen Code "sprechen".

Innerhalb des ASCII-Codes sind die Zahlenwerte für die Zeichen in der Regel identisch, aber in der Erweiterung zu 8-Bit nicht unbedingt gleich. Jede Computerfirma hat eigene Codepages entwickelt und veröffentlicht. Gerade in der Anfangszeit dominierten IBM-Rechner mit dem Betriebssystem MS-DOS. Wir werden hier genau diesen Zeichencode verwenden, der dort eingesetzt wurde und auch unter Windows in der Konsole verwendet wird. Dieser Code wird als "Codepage 437" bezeichnet.

00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
0x0 NULL
0x1 §
0x2 Space ! " # $ % & ' ( ) * + , - . /
0x3 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
0x4 @ A B C D E F G H I J K L M N O
0x5 P Q R S T U V W X Y Z [ \ ] ^ _
0x6 ` a b c d e f g h i j k l m n o
0x7 p q r s t u v w x y z { } ~ DEL
0x8 Ç ü é â ä à å ç ê ë è ï î ì Ä Å
0x9 É æ Æ ô ö ò û ù ÿ Ö Ü ¢ £ ¥ ƒ
0xA á í ó ú ñ Ñ ª º ¿ ¬ ½ ¼ ¡ « »
0xB
0xC
0xD
0xE α ß Γ π Σ σ µ τ Φ Θ Ω δ φ ε
0xF ± ÷ ° · ²    

Font-Erstellen

Nun kümmern wir uns darum, dem Computer beizubringen, wie die einzelnen Zeichen aussehen. Dazu erstellen wir eine Art Datenbank, in der jedes Zeichen beschrieben wird. Zur Einfachheit verwenden wir eine 8x8 Matrix, um die Zeichen darzustellen.

Dazu erstellen wir eine Datei, die folgendermaßen aussieht:

  • Dimension
    • INT X
    • INT Y
  • Data
    • Binärcode

Zunächst geben wir die Größe der Zeichen in X und Y an. Daraus können wir zur Berechnung der einzelnen Zeichen den entsprechenden Binärcode ableiten. Hier steht jedes Bit, das gesetzt ist, für ein Pixel, welches gezeichnet werden soll. Umgesetzt in Code sieht es dann so aus:

/* 8x8 FONT by Satyria */

@ Dimension
.int 8 @ x
.int 8 @ y

@ Data
@ 0: NULL 
.byte 0b00000000
.byte 0b00000000
.byte 0b00000000
.byte 0b00000000
.byte 0b00000000
.byte 0b00000000
.byte 0b00000000
.byte 0b00000000

...

@ 65: "A" 
.byte 0b00011000
.byte 0b00111100
.byte 0b00111100
.byte 0b01100110
.byte 0b01111110
.byte 0b11000011
.byte 0b11000011
.byte 0b00000000

@ 66: "B" 
.byte 0b11111100
.byte 0b01100110
.byte 0b01100110
.byte 0b01111100
.byte 0b01100110
.byte 0b01100110
.byte 0b11111100
.byte 0b00000000

...

Dieses Beispiel zeigt, wie wir die Datenbank für die Zeichendarstellung aufbauen können. Jeder Buchstabe wird als 8x8 Pixel großes Muster beschrieben, wobei jedes Byte eine Zeile des Musters darstellt. Das Bitmuster gibt an, welche Pixel gesetzt werden und somit sichtbar sind.

Mein Beispiel für den Font habe ich als "ms8x8font.fon" im Includeverzeichnis abgelegt.

Font-Anzeigen lassen

Nachdem wir nun einen Font beschrieben haben, also definiert haben, wie ein Zeichen aussieht, müssen wir diesen noch auf den Bildschirm zeichnen.

Bisher können wir nicht auf externe Medien, während unser Programm läuft, zugreifen. Da dies bisher nicht geht, müssen wir den Font in unseren Sourcecode integrieren. Dazu verwenden wir die Include-Funktion des Compilers.

.section .data

font:
.include "ms8x8font.fon"

Unserer Funktion werden wir den Namen "DrawChar" geben. Ihr wird das Zeichen selbst, welches angezeigt werden soll und die Position (x,y) übergeben.

Zunächst sichern wir diese Angaben, damit diese nicht gelöscht werden, wenn wir eine andere Funktion verwenden.

//void DrawChar(char c, u32 x0, u32 y0)
//Zeichnet einen Char an die Position x0, y0 auf den Screen
.globl DrawChar
DrawChar:
	stp x29, x30, [sp, -16]!
	stp x20, x21, [sp, -16]!
	stp x10, x11, [sp, -16]!
	stp x12, x13, [sp, -16]!
	stp x14, x15, [sp, -16]!
	mov x29, sp
	
    Sichere zunächst die Position
	mov w20,w1	// x0
	mov w21,w2	// y0

Unseren Font haben wir im Datenbereich abgelegt und ihm das Label "font" gegeben. Diesen Zeiger legen wir in x10 ab.

    //Berechne den Zeiger auf das richtige Zeichen 
	ldr x10,=font
	lsl w0,w0,#3
	add x10,x10,x0

Da wir die Dimension des Fonts kennen, überspringen wir diese Angabe. Danach multiplizieren wir die Übergabe des Zeichen, welche wir in w0 übergeben bekommen haben, mit acht. Ein Shift um 3 Positionen nach links, entspricht einer Multiplikation von acht. Und addieren das Ergebnis auf den Zeiger. Damit haben wir die Position des entsprechenden Fonts, den wir anzeigen lassen wollen.

Da wir wissen, wie der Font aufgebaut ist, also 8x8 Pixel, verwenden wir zwei ineinander verschachtelte Schleifen:

    //for (w11 = 0; w11 < FONT_HEIGHT; w11++)
	mov w11,#0
1:
	cmp w11,#FONT_HEIGHT
	bge 2f

    //for (w12 = 0; w12 < FONT_WIDTH; w12++)
	mov w12,#0
3:
	cmp w12,#FONT_WIDTH
	bge 4f

...

    //end_for w12
	add w12,w12,#1
	b 3b
4:
    //end_for w11
	add w11,w11,#1
	b 1b

Nun müssen wir jedes Bit dieser Font-Matrix auswerten. Dazu verwenden wir folgende Formel: (Zeile >> (7 - BitPos)) & 1;

Wir lesen zunächst das Byte heraus, was wir mit w11 (Zeile) definiert haben. Dies machen wir mit dem Befehl ldrb w13,[x10,x11]. Dies bedeutet das wir aus dem Speicher das Byte lesen, welches im Speicher an x10 steht und addieren dort den Offset von x11 dazu. Den Wert schreiben wir nach w13. Da wir das Ergebnis falsch herum bekommen, ziehen wir von der 7 (1. Bit = 0) die BitPos ab, die wir in der Schleife mit w12 definiert haben. Verschieben damit dann die Bits im Byte um die Positionen mit lsr nach rechts und mit "and" löschen wir alle höherwertigen Bits, bis auf das erste. Nun können wir das Ergebnis auswerten. Wenn der Wert gleich Null ist, dann zeichne ein Pixel in der Hintergrundfarbe, ansonsten in der Vordergrundfarbe.

Hier der gesamte Code für die DrawChar-Funktion:

//void DrawChar(char c, u32 x0, u32 y0)
//Zeichnet einen Char an die Position x0, y0 auf den Screen
.globl DrawChar
DrawChar:
	stp x29, x30, [sp, -16]!
	stp x20, x21, [sp, -16]!
	stp x10, x11, [sp, -16]!
	stp x12, x13, [sp, -16]!
	stp x14, x15, [sp, -16]!
	mov x29, sp
	
    Sichere zunächst die Position
	mov w20,w1	// x0
	mov w21,w2	// y0

    //Berechne den Zeiger auf das richtige Zeichen 
	ldr x10,=font
	lsl w0,w0,#3
	add x10,x10,x0

    //for (w11 = 0; w11 < FONT_HEIGHT; w11++)
	mov w11,#0
1:
	cmp w11,#FONT_HEIGHT
	bge 2f

    //for (w12 = 0; w12 < FONT_WIDTH; w12++)
	mov w12,#0
3:
	cmp w12,#FONT_WIDTH
	bge 4f
	

    //Überprüfe das Bit nach folgender Formel:
    //(Zeile >> (7 - BitPos)) & 1;
	ldrb w13,[x10,x11]
	mov w14,#7
	sub w14,w14,w12
	lsr w13,w13,w14
	and w13,w13,#1
    //Wenn Ergebniss 0 ist, dann Hintergrund zeichnen
	cbz w13,5f

    //Ansonsten in der Vordergrundfarbe
	ldr x13,=FrontColor
	ldr w13,[x13]
	ldr x14,=DrawColor
	str w13,[x14]
	b 6f
	
5:
	ldr x13,=BackColor
	ldr w13,[x13]
	ldr x14,=DrawColor
	str w13,[x14]

6:
    //Zeichne den Pixel an die Position
	mov w0,w12
	add w0,w0,w20
	mov w1,w11
	add w1,w1,w21
	bl DrawPixel

    //end_for w12
	add w12,w12,#1
	b 3b
4:
    //end_for w11
	add w11,w11,#1
	b 1b
2:
	ldp x14, x15, [sp], 16
	ldp x12, x13, [sp], 16
	ldp x10, x11, [sp], 16
	ldp x20, x21, [sp], 16
	ldp x29, x30, [sp], 16
	ret

Um das nun zu testen, ob es geht, müssen wir unser main-Programm ändern:

//
// kernel.S
//

.section .text
.globl main
main:

    bl LED_off
	bl Init_Screen

	mov w10,#33
	mov w11,#100
2:
	cmp w10,#90
	bge 1f
	
	mov w0,w10
	mov w1,#100
	mov w2,w11
	bl DrawChar
	add w11,w11,#10
	add w10,w10,#1

	b 2b
1:	 
	mov w0,#2
	bl LED_Error
999:
   b 999b

Wie zuvor schon, schalten wir wieder unsere LED aus, um einen Ausgangszustand zu haben. Initialiesieren unseren Screen und erzeugen dann eine Schleife, die von 33 bis 90 zählt. Diesen Wert übergeben wir der DrawChar-Funktion in w0. Zusätzlich geben wir ihr die Koordinaten für den "Char" in w1 (immer 100) und w2 (jeweils um 10 erhöht) mit. Am ende unseres Programms gehen wir wieder in den Fehlercode 2, damit wir sehen, dass er alles abgearbeitet hat.