Chars (PI5)e: Unterschied zwischen den Versionen

Aus C und Assembler mit Raspberry
KKeine Bearbeitungszusammenfassung
 
(8 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt)
Zeile 3: Zeile 3:
After implementing a function to set individual pixels, we now want to teach the Raspberry Pi to display text on the screen. Texts consist of characters that the computer does not inherently recognize. Like a human, the computer must first "learn" how each character looks before it can display it. These characters are defined in a specific code that the computer understands. One of the most widely used codes is the ANSI character code.
After implementing a function to set individual pixels, we now want to teach the Raspberry Pi to display text on the screen. Texts consist of characters that the computer does not inherently recognize. Like a human, the computer must first "learn" how each character looks before it can display it. These characters are defined in a specific code that the computer understands. One of the most widely used codes is the ANSI character code.


**The ANSI Character Code**
== The ANSI Character Code ==


The ANSI character code we are using here is an extension of the original ASCII code. While ASCII originally used only 7 bits per character, ANSI extends this to 8 bits, which equals one byte. The ANSI code was developed when computers needed to communicate over networks and ensure that both sides used the same characters. The first 128 characters in the ANSI code match the ASCII code, but characters 128 to 255 can vary depending on the code page used.
The ANSI character code we are using here is an extension of the original ASCII code. While ASCII originally used only 7 bits per character, ANSI extends this to 8 bits, which equals one byte. The ANSI code was developed when computers needed to communicate over networks and ensure that both sides used the same characters. The first 128 characters in the ANSI code match the ASCII code, but characters 128 to 255 can vary depending on the code page used.
Zeile 9: Zeile 9:
Here, we use "Codepage 437," which was originally developed by IBM for MS-DOS computers and is still used today in the Windows command line.
Here, we use "Codepage 437," which was originally developed by IBM for MS-DOS computers and is still used today in the Windows command line.


|     | 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 0A | 0B | 0C | 0D | 0E | 0F |
{| class="wikitable" style="text-align: center;"
| --- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- |
|+
| 0x0 | NUL| ☺ | ☻ | ♥ | ♦ | ♣ | ♠ | • | ◘ | ○ | ◙ | ♂ | ♀ | ♪ | ♫ | ☼ |
! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !! !!
| 0x1 | ► | ◄ | ↕ | ‼ | ¶ | § | ▬ | ↨ | ↑ | ↓ | → | ← | ∟ | ↔ | ▲ | ▼ |
|-
| 0x2 | Space | ! | " | # | $ | % | & | ' | ( | ) | * | + | , | - | . | / |
! !! 0x0 !! 0x1 !! 0x2 !! 0x3 !! 0x4 !! 0x5 !! 0x6 !! 0x7 !! 0x8 !! 0x9 !! 0xA !! 0xB !! 0xC !! 0xD !! 0xE !! 0xF
| 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 |
! 0x0
| 0x5 | P | Q | R | S | T | U | V | W | X | Y | Z | [ | \ | ] | ^ | _ |
| NULL || ☺ || ☻ || ♥ || ♦ || ♣ || ♠ || • || ◘ || ○ || ◙ || ♂ || ♀ || ♪ || ♫ || ☼
| 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 |
! 0x1
| 0x8 | Ç | ü | é | â | ä | à | å | ç | ê | ë | è | ï | î | ì | Ä | Å |
| ► || ◄ || ↕ || ‼ || ¶ || § || ▬ || ↨ || ↑ || ↓ || → || ← || ∟ || ↔ || ▲ || ▼
| 0x9 | É | æ | Æ | ô | ö | ò | û | ù | ÿ | Ö | Ü | ¢ | £ | ¥ | ₧ | ƒ |
|-
| 0xA | á | í | ó | ú | ñ | Ñ | ª | º | ¿ | ⌐ | ¬ | ½ | ¼ | ¡ | « | » |
! 0x2
| 0xB | ░ | ▒ | ▓ | │ | ┤ | ╡ | ╢ | ╖ | ╕ | ╣ | ║ | ╗ | ╝ | ╜ | ╛ | ┐ |
| Space || ! || " || # || $ || % || & || ' || ( || ) || * || + || , || - || . || /
| 0xC | └ | ┴ | ┬ | ├ | ─ | ┼ | ╞ | ╟ | ╚ | ╔ | ╩ | ╦ | ╠ | ═ | ╬ | ╧ |
|-
| 0xD | ╨ | ╤ | ╥ | ╙ | ╘ | ╒ | ╓ | | ╪ | ┘ | ┌ | █ | ▄ | ▌ | ▐ | ▀ |
! 0x3
| 0xE | α | ß | Γ | π | Σ | σ | µ | τ | Φ | Θ | Ω | δ | ∞ | φ | ε | ∩ |
| 0 || 1 || 2 || 3 || 4 || 5 || 6 || 7 || 8 || 9 || : || ; || < || = || > || ?
| 0xF | ≡ | ± | ≥ | ≤ | ⌠ | ⌡ | ÷ | ≈ | ° | • | · | √ | ⁿ | ² | ■ |
|-
! 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
| ≡ || ± || ≥ || ≤ || ⌠ || ⌡ || ÷ || ≈ || ° || • || · || √ || ⁿ || ² || ■ ||     
|}


**Creating a Font**
== Creating a Font ==


To enable the computer to display characters, we need to show it what each character looks like. To do this, we create a kind of database where each character is described as an 8x8 pixel pattern.
To enable the computer to display characters, we need to show it what each character looks like. To do this, we create a kind of database where each character is described as an 8x8 pixel pattern.
Zeile 34: Zeile 70:
For example, the file describing these characters might look like this:
For example, the file describing these characters might look like this:


```c
<syntaxhighlight lang="asm">
/* 8x8 FONT by Satyria */
/* 8x8 FONT by Satyria */


@ Dimension, noch verzichten wir auf die Dimensionen
@ Dimension, nor do we renounce the dimensions
@.int 8 @ x  
@.int 8 @ x  
@.int 8 @ y
@.int 8 @ y
Zeile 73: Zeile 109:
.byte 0b11111100
.byte 0b11111100
.byte 0b00000000
.byte 0b00000000
```
</syntaxhighlight>


In this example, the character "A" is described as an 8x8 pixel pattern, where each byte represents a row of the pattern. Each bit in this byte stands for a pixel: A set bit (1) means that the pixel is drawn, while an unset bit (0) means that the pixel remains transparent.
In this example, the character "A" is described as an 8x8 pixel pattern, where each byte represents a row of the pattern. Each bit in this byte stands for a pixel: A set bit (1) means that the pixel is drawn, while an unset bit (0) means that the pixel remains transparent.
Zeile 79: Zeile 115:
My example for the font is saved as "ms8x8font.fon" in the include directory.
My example for the font is saved as "ms8x8font.fon" in the include directory.


**Drawing Characters on the Screen**
== Drawing Characters on the Screen ==


After defining what each character looks like, we need to write a function to display these characters on the screen. We call this function "DrawChar." It will be given the character to draw as well as the position (x, y) on the screen.
After defining what each character looks like, we need to write a function to display these characters on the screen. We call this function "DrawChar." It will be given the character to draw as well as the position (x, y) on the screen.
Zeile 85: Zeile 121:
First, we save the passed values so that they are not overwritten by other functions:
First, we save the passed values so that they are not overwritten by other functions:


```asm
<syntaxhighlight lang="asm">
//void DrawChar(char c, u32 x0, u32 y0)
//void DrawChar(char c, u32 x0, u32 y0)
//Draws a character at position x0, y0 on the screen
//Draws a character at position x0, y0 on the screen
Zeile 100: Zeile 136:
mov w20, w1 // x0
mov w20, w1 // x0
mov w21, w2 // y0
mov w21, w2 // y0
```
</syntaxhighlight>


Next, we calculate the pointer to the character we want to draw. The font is stored in the data section and has the label "font." To determine the exact position of the desired character, we shift the value of the character 3 bits to the left (equivalent to multiplying by 8 since each character has 8 rows) and add it to the base pointer:
Next, we calculate the pointer to the character we want to draw. The font is stored in the data section and has the label "font." To determine the exact position of the desired character, we shift the value of the character 3 bits to the left (equivalent to multiplying by 8 since each character has 8 rows) and add it to the base pointer:


```asm
<syntaxhighlight lang="asm">
     // Calculate the pointer to the correct character  
     // Calculate the pointer to the correct character  
ldr x10, =font
ldr x10, =font
lsl w0, w0, #3
lsl w0, w0, #3
add x10, x10, x0
add x10, x10, x0
```
</syntaxhighlight>


Now that we have the pointer to the character, we use two nested loops to iterate through the 8x8 pixel pattern:
Now that we have the pointer to the character, we use two nested loops to iterate through the 8x8 pixel pattern:


```asm
<syntaxhighlight lang="asm">
     //for (w11 = 0; w11 < FONT_HEIGHT; w11++)
     //for (w11 = 0; w11 < FONT_HEIGHT; w11++)
mov w11, #0
mov w11, #0
Zeile 125: Zeile 161:
cmp w12, #FONT_WIDTH
cmp w12, #FONT_WIDTH
bge 4f
bge 4f
```
</syntaxhighlight>


Within the inner loop, the current byte of the row we are drawing is loaded into `w13`. To check the relevant bit, the byte is shifted to the right (`lsr`), so that the bit to be checked is at position 0. Then it is checked with an `and` instruction to see if this bit is set:
Within the inner loop, the current byte of the row we are drawing is loaded into `w13`. To check the relevant bit, the byte is shifted to the right (`lsr`), so that the bit to be checked is at position 0. Then it is checked with an `and` instruction to see if this bit is set:


```asm
<syntaxhighlight lang="asm">
     // Check the bit using the following formula:
     // Check the bit using the following formula:
     // (Row >> (7 - BitPos)) & 1;
     // (Row >> (7 - BitPos)) & 1;
ldrb w13, [x10,
ldrb w13, [x10, w11]
 
w11]
ldr w14, =7
ldr w14, =7
sub w14, w14, w12
sub w14, w14, w12
Zeile 140: Zeile 174:
tst w13, #1
tst w13, #1
beq 5f
beq 5f
```
</syntaxhighlight>


If the bit is set, we calculate the corresponding coordinates on the screen and call the `SetPixel` function to set the pixel at that position:
If the result is 0, we draw a pixel in the background color; otherwise, in the foreground color.:


```asm
<syntaxhighlight lang="asm">
     // Draw the pixel
     // If the result is 0, draw in the background color
add w13, w20, w12
cbz w13, 5f
add w14, w21, w11
 
bl SetPixel
    // Otherwise, draw in the foreground color
ldr x13, =FrontColor
ldr w13, [x13]
ldr x14, =DrawColor
str w13, [x14]
b 6f
5:
5:
```
ldr x13, =BackColor
ldr w13, [x13]
ldr x14, =DrawColor
str w13, [x14]
</syntaxhighlight>


This process is repeated for every row of the character. After each row is completed, the function loops back and moves to the next row. Once all rows are drawn, the function exits:
Finally, we draw the pixel at the calculated position on the screen:


```asm
<syntaxhighlight lang="asm">
     // Jump back to the inner loop
6:
     // Draw the pixel at the position
mov w0, w12
add w0, w0, w20
mov w1, w11
add w1, w1, w21
bl DrawPixel
 
    // end_for w12
add w12, w12, #1
add w12, w12, #1
b 3b
b 3b
4:
4:
     // Jump back to the outer loop
     // end_for w11
add w11, w11, #1
add w11, w11, #1
b 1b
b 1b
2:
2:
```
Finally, we restore the saved values and return:
```asm
ldp x14, x15, [sp], 16
ldp x14, x15, [sp], 16
ldp x12, x13, [sp], 16
ldp x12, x13, [sp], 16
Zeile 174: Zeile 221:
ldp x29, x30, [sp], 16
ldp x29, x30, [sp], 16
ret
ret
```
</syntaxhighlight>
 
Here is the entire code for the `DrawChar` function:
 
<syntaxhighlight lang="asm">
// void DrawChar(char c, u32 x0, u32 y0)
// Draws a character at position x0, y0 on the 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
 
    // First, save the position
    mov w20, w1  // x0
    mov w21, w2  // y0
 
    // Calculate the pointer to the correct character
    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
 
    // Check the bit using the following formula:
    // (Row >> (7 - BitPos)) & 1;
    ldrb w13, [x10, x11]
    mov w14, #7
    sub w14, w14, w12
    lsr w13, w13, w14
    and w13, w13, #1
    // If the result is 0, then draw the background
    cbz w13, 5f
 
    // Otherwise, draw in the foreground color
    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:
    // Draw the pixel at the 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
</syntaxhighlight>
 
== Testing the Function ==
 
To test the function, we modify our main program to include a loop that writes a series of characters to the screen:
 
<syntaxhighlight lang="asm">
//
// 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
</syntaxhighlight>
 
In this example, we turn off the LED, initialize the screen, and then draw a series of characters on the screen starting at position (100, 100). With each iteration of the loop, the character is moved 10 pixels down. If the program runs successfully, error code 2 is output.


This is how the `DrawChar` function draws a character on the screen.
You can download the source code as a ZIP file from the following link: https://www.satyria.de/arm/sources/assem/chars.zip


---
-----


This translation maintains the technical integrity and context of the original text while ensuring the content is accurate.
{| style="width: 100%;
| style="width: 33%;" | [[Graphics (PI5)|< Back (Graphics (PI5))]]
| style="width: 33%; text-align:center;" | [[English|< Home >]]
| style="width: 33%; text-align:right;" | [[The Terminal|Next (The Terminal) >]]
|}

Aktuelle Version vom 22. Februar 2025, 11:32 Uhr

Drawing Characters on the Raspberry Pi

After implementing a function to set individual pixels, we now want to teach the Raspberry Pi to display text on the screen. Texts consist of characters that the computer does not inherently recognize. Like a human, the computer must first "learn" how each character looks before it can display it. These characters are defined in a specific code that the computer understands. One of the most widely used codes is the ANSI character code.

The ANSI Character Code

The ANSI character code we are using here is an extension of the original ASCII code. While ASCII originally used only 7 bits per character, ANSI extends this to 8 bits, which equals one byte. The ANSI code was developed when computers needed to communicate over networks and ensure that both sides used the same characters. The first 128 characters in the ANSI code match the ASCII code, but characters 128 to 255 can vary depending on the code page used.

Here, we use "Codepage 437," which was originally developed by IBM for MS-DOS computers and is still used today in the Windows command line.

0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xA 0xB 0xC 0xD 0xE 0xF
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 ± ÷ ° · ²    

Creating a Font

To enable the computer to display characters, we need to show it what each character looks like. To do this, we create a kind of database where each character is described as an 8x8 pixel pattern.

For example, the file describing these characters might look like this:

/* 8x8 FONT by Satyria */

@ Dimension, nor do we renounce the dimensions
@.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

In this example, the character "A" is described as an 8x8 pixel pattern, where each byte represents a row of the pattern. Each bit in this byte stands for a pixel: A set bit (1) means that the pixel is drawn, while an unset bit (0) means that the pixel remains transparent.

My example for the font is saved as "ms8x8font.fon" in the include directory.

Drawing Characters on the Screen

After defining what each character looks like, we need to write a function to display these characters on the screen. We call this function "DrawChar." It will be given the character to draw as well as the position (x, y) on the screen.

First, we save the passed values so that they are not overwritten by other functions:

//void DrawChar(char c, u32 x0, u32 y0)
//Draws a character at position x0, y0 on the 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
	
    // Save the position first
	mov w20, w1	// x0
	mov w21, w2	// y0

Next, we calculate the pointer to the character we want to draw. The font is stored in the data section and has the label "font." To determine the exact position of the desired character, we shift the value of the character 3 bits to the left (equivalent to multiplying by 8 since each character has 8 rows) and add it to the base pointer:

    // Calculate the pointer to the correct character 
	ldr x10, =font
	lsl w0, w0, #3
	add x10, x10, x0

Now that we have the pointer to the character, we use two nested loops to iterate through the 8x8 pixel pattern:

    //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

Within the inner loop, the current byte of the row we are drawing is loaded into `w13`. To check the relevant bit, the byte is shifted to the right (`lsr`), so that the bit to be checked is at position 0. Then it is checked with an `and` instruction to see if this bit is set:

    // Check the bit using the following formula:
    // (Row >> (7 - BitPos)) & 1;
	ldrb w13, [x10, w11]
	ldr w14, =7
	sub w14, w14, w12
	lsr w13, w13, w14
	tst w13, #1
	beq 5f

If the result is 0, we draw a pixel in the background color; otherwise, in the foreground color.:

    // If the result is 0, draw in the background color
	cbz w13, 5f

    // Otherwise, draw in the foreground color
	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]

Finally, we draw the pixel at the calculated position on the screen:

6:
    // Draw the pixel at the 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

Here is the entire code for the `DrawChar` function:

// void DrawChar(char c, u32 x0, u32 y0)
// Draws a character at position x0, y0 on the 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

    // First, save the position
    mov w20, w1  // x0
    mov w21, w2  // y0

    // Calculate the pointer to the correct character
    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

    // Check the bit using the following formula:
    // (Row >> (7 - BitPos)) & 1;
    ldrb w13, [x10, x11]
    mov w14, #7
    sub w14, w14, w12
    lsr w13, w13, w14
    and w13, w13, #1
    // If the result is 0, then draw the background
    cbz w13, 5f

    // Otherwise, draw in the foreground color
    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:
    // Draw the pixel at the 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

Testing the Function

To test the function, we modify our main program to include a loop that writes a series of characters to the screen:

//
// 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

In this example, we turn off the LED, initialize the screen, and then draw a series of characters on the screen starting at position (100, 100). With each iteration of the loop, the character is moved 10 pixels down. If the program runs successfully, error code 2 is output.

You can download the source code as a ZIP file from the following link: https://www.satyria.de/arm/sources/assem/chars.zip


< Back (Graphics (PI5)) < Home > Next (The Terminal) >