972
edits
[unchecked revision] | [unchecked revision] |
No edit summary |
m (Bot: Replace deprecated source tag with syntaxhighlight) |
||
(37 intermediate revisions by 17 users not shown) | |||
Line 1:
==Basics==
This is quite easy.
Text mode memory takes two bytes for every "character" on screen. One is the ''ASCII code'' byte, the other the ''attribute'' byte. so the text "HeLlo" would be stored as:
<pre>
0x000b8000: 'H',
0x000b8002: 'e',
0x000b8004: 'L',
0x000b8006: 'l',
</pre>
The ''attribute'' byte carries the ''foreground colour'' in its lowest 4 bits and the ''background color'' in its highest 3 bits. The interpretation of bit #7
For instance, using <tt>0x00</tt> as attribute byte means black-on-black (you'll see nothing). <tt>0x07</tt> is lightgrey-on-black (
For colour video cards, you have
When you print to any other page than 0, it will ''not'' appear on screen until that page is ''enabled'' or
====Color Table====
{| {{wikitable}}
|-
! Color number
! Color name
! RGB value
! Hex value
|-
| 0
| Black
| 0 0 0
| 00 00 00
|-
| 1
| Blue
| 0 0 170
| 00 00 AA
|-
| 2
| Green
| 0 170 0
| 00 AA 00
|-
| 3
| Cyan
| 0 170 170
| 00 AA AA
|-
| 4
| Red
| 170 0 0
| AA 00 00
|-
| 5
| Purple
| 170 0 170
| AA 00 AA
|-
| 6
| Brown
| 170 85 0
| AA 55 00
|-
| 7
| Gray
| 170 170 170
| AA AA AA
|-
| 8
| Dark Gray
| 85 85 85
| 55 55 55
|-
| 9
| Light Blue
| 85 85 255
| 55 55 FF
|-
| 10
| Light Green
| 85 255 85
| 55 FF 55
|-
| 11
| Light Cyan
| 85 255 255
| 55 FF FF
|-
| 12
| Light Red
| 255 85 85
| FF 55 55
|-
| 13
| Light Purple
| 255 85 255
| FF 55 FF
|-
| 14
| Yellow
| 255 255 85
| FF FF 55
|-
| 15
| White
| 255 255 255
| FF FF FF
|-
|}
==Printing Strings==
Line 26 ⟶ 118:
If you have a pointer to video memory and want to write a string, here is how you might do it;
<syntaxhighlight lang="c">
/
void write_string( int colour, const char *string )
{
{
*video++ = colour;
}
}
</syntaxhighlight>
This simply cycles through each character in the string, and copies it to the appropriate place in video memory.
For a more advanced print function, you need to store variables for x and y, as the display controller will not print a newline. This involves a switch statement or similar construct.
You also have to test for x>80 or y>25 and in the case of x>80 setting x to 0 and incrementing y, or in the case of y>25 scrolling.
==Printing Integers==
Just like in any environment
For example, since 1234 = 4 + 3* 10 + 2 * 100 + 1* 1000, if you repeatedly divide "1234" by ten and use the remainder of the division, you get the digits:
<pre>
Line 57 ⟶ 150:
</pre>
As this algorithm retrieves the digits in the "wrong" order (last-to-first),
Here is an example implementation of the itoa() function (which is not standard, but provided by many libraries):
<syntaxhighlight lang="c">
char * itoa( int value, char * str, int base )
{
char * rc;
char * ptr;
char * low;
// Check for supported base.
if ( base < 2 || base > 36 )
{
*str = '\0';
return str;
}
rc = ptr = str;
// Set '-' for negative decimals.
if ( value < 0 && base == 10 )
{
*ptr++ = '-';
}
// Remember where the numbers start.
low = ptr;
// The actual conversion.
do
{
// Modulo is negative for negative value. This trick makes abs() unnecessary.
*ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz"[35 + value % base];
value /= base;
} while ( value );
// Terminating the string.
*ptr-- = '\0';
// Invert the numbers.
while ( low < ptr )
{
char tmp = *low;
*low++ = *ptr;
*ptr-- = tmp;
}
return rc;
}
</syntaxhighlight>
[http://www.strudel.org.uk/itoa/ And here is a shorter one]
== Troubleshooting ==
Line 87 ⟶ 199:
=== Nothing is Displayed ===
Keep in mind that this way of writing to video memory will
([[GRUB]] does this setup for you.)
Another common mistake, e.g. in numerous tutorials spread across the net, is to link the .text section of your kernel/OS to the wrong memory address. If you don't have memory management in place yet, make sure you're using physical memory locations in the linker script.
===Printing a Character===
While in Protected Mode, try a simple command like:
<pre>
// C
*((int*)0xb8000)=0x07690748;
// NASM
mov [0xb8000], 0x07690748
// GAS
movl $0x07690748,0xb8000
</pre>
which should display 'Hi' in grey-on-black on top of your screen. If this does not work, check your paging / segmentation setup correctly maps your assumed video memory address to 0xB8000 (or 0xB0000).
=== Missing Strings ===
Previously, GCC had an option <tt>-fwritable-strings</tt> which could be used as a workaround for this, but it was deprecated in version 3.0 and removed in 4.0 and later, which was released in 2005. Even when the option was available, it was a kludge; the real solution was, and still is, to add <tt>.rodata</tt> to the script.
==See Also==
*[[Printing to the screen without a db]]
[[Category:Tutorials]]
[[Category:Video]]
[[Category:Text UI]]
|