Printing To Screen: Difference between revisions
Jump to navigation
Jump to search
[unchecked revision] | [unchecked revision] |
Content deleted Content added
→Printf: The explanations were not enough to base a stdarg.h implementation upon them, factually not quite correct, and as such probably more confusing than helpful. |
General rework. |
||
Line 1: | Line 1: | ||
==Basics== |
==Basics== |
||
Assuming that you are in [[protected mode]] and not using the [[BIOS]] to write text to screen, you will have write directly to "video" memory. |
|||
This is quite easy |
This is quite easy. The text screen video memory for colour monitors resides at <tt>0xB8000</tt>, and for monochrome monitors it is at address <tt>0xB0000</tt> (see [[Detecting Colour and Monochrome Monitors]] for more information). |
||
⚫ | |||
⚫ | |||
<pre> |
<pre> |
||
0x000b8000: 'H', |
0x000b8000: 'H', colour_for_H |
||
0x000b8002: 'e', |
0x000b8002: 'e', colour_for_e |
||
0x000b8004: 'L', |
0x000b8004: 'L', colour_for_L |
||
0x000b8006: 'l', |
0x000b8006: 'l', colour_for_l |
||
0x000b0008: 'o', |
0x000b0008: 'o', colour_for_o |
||
</pre> |
</pre> |
||
The ''attribute'' byte carries the ''foreground colour'' in its lowest 4 bits and the ''background color'' in its highest 3 bits. The bit #7 |
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 depends on how you (or the BIOS) configured the hardware (see [[VGA Resources]] for additional info). |
||
For instance, using <tt>0x00</tt> as attribute means black-on-black (you'll see nothing). <tt>0x07</tt> is lightgrey-on-black ( |
For instance, using <tt>0x00</tt> as attribute byte means black-on-black (you'll see nothing). <tt>0x07</tt> is lightgrey-on-black (DOS default), <tt>0x1F</tt> is white-on-blue (Win9x's blue-screen-of-death), <tt>0x2a</tt> is for green-monochrome nostalgics. |
||
For colour video cards, you have 16kb of text video memory to use |
For colour video cards, you have 16kb of text video memory to use. Since 80x25 mode does not use all 16kb (80 x 25 x 2, 4000 bytes per screen), you have 8 display pages to use. |
||
When you print to any other page than 0, it will ''not'' appear on screen until that page is ''enabled'' or |
When you print to any other page than 0, it will ''not'' appear on screen until that page is ''enabled'' or ''copied'' into the page 0 memory space. |
||
==Printing Strings== |
==Printing Strings== |
||
Line 27: | Line 28: | ||
<pre> |
<pre> |
||
/ |
// note this example will always write to the top |
||
// line of the screen |
|||
void write_string(int colour, const char *string) |
void write_string( int colour, const char *string ) |
||
{ |
{ |
||
volatile char *video = (volatile char*)0xB8000; |
|||
while( *string != 0 ) |
|||
{ |
|||
{ |
|||
*video++ = *string++; |
|||
⚫ | |||
string++; |
|||
} |
|||
video++; |
|||
⚫ | |||
video++; |
|||
} |
|||
} |
} |
||
</pre> |
</pre> |
||
Line 47: | Line 45: | ||
==Printing Integers== |
==Printing Integers== |
||
Just like in any environment |
Just like in any environment, you repeatedly divide the value by the base, the remainder of the division giving you the least significant digit of the value. |
||
For example, since 1234 = 4 + 3* 10 + 2 * 100 + 1* 1000, if you repeatedly divide "1234" by ten and use the result of the division, you get the digits: |
|||
<pre> |
<pre> |
||
Line 57: | Line 56: | ||
</pre> |
</pre> |
||
digits to |
As this algorithm retrieves the digits in the "wrong" order (last-to-first), you have to either work recursively, or invert the sequence of digits afterwards. If you know the numerical value of <tt>number % 10</tt>, you simply have to add this to the character '0' to have the correct character (e.g. '0'+4 == '4') |
||
Here is an example implementation of the itoa() function (which is not standard, but provided by many libraries): |
Here is an example implementation of the itoa() function (which is not standard, but provided by many libraries): |
||
Line 103: | Line 102: | ||
(see more on [http://www.osdev.org/phpBB2/viewtopic.php?t=10319 the forum].) |
(see more on [http://www.osdev.org/phpBB2/viewtopic.php?t=10319 the forum].) |
||
== printf and variable argument lists == |
|||
== Printf == |
|||
If you're working with C, you may want to print any number of arguments, like <tt>printf()</tt> does. For this, you need to handle variable argument lists. Looking at the <tt>stdarg.h</tt> file from other operating systems (e.g. Linux 0.1), you might be a bit confused by the macro definitions in that file, as they are basically black magic depending on the C calling conventions. As such, they are not exactly portable. |
If you're working with C, you may want to print any number of arguments, like <tt>printf()</tt> does. For this, you need to handle variable argument lists. Looking at the <tt>stdarg.h</tt> file from other operating systems (e.g. Linux 0.1), you might be a bit confused by the macro definitions in that file, as they are basically black magic depending on the C calling conventions. As such, they are not exactly portable. |
||
Line 125: | Line 124: | ||
=== Nothing is Displayed === |
=== Nothing is Displayed === |
||
Keep in mind that this way of writing to video memory will _only_ work if the screen has been correctly set up for 80x25 video mode (which is mode 03). You can do this either by initializing every VGA register manually or by calling the Set Video Mode service of the BIOS Int10h while you're still in real mode (in your bootsector, for instance). Most BIOS's |
Keep in mind that this way of writing to video memory will _only_ work if the screen has been correctly set up for 80x25 video mode (which is mode 03). You can do this either by initializing every VGA register manually, or by calling the ''Set Video Mode'' service of the BIOS Int10h while you're still in real mode (in your bootsector, for instance). Most BIOS's do that initialization for you, but some other (mainly on laptops) do not. Check out [[Ralf Brown's Interrupt List]] for details. Note also that some modes that are reported as "both text & graphic" by mode lists are actually graphic modes with BIOS functions that plot fonts when you call char/message output through Int10h (which means you'll end up with plain graphic mode once in [[Protected Mode]]). |
||
([GRUB] does this setup for you.) |
|||
⚫ | |||
⚫ | |||
===Printing in Real Mode=== |
|||
''It's '''real''' easy...'' |
|||
While still in [[Real Mode]], try to write directly to Video memory. If this doesn't work either you haven't set up the Video mode properly to 0x03 (check out [[RBIL]]) or you're assuming the wrong video memory address (<tt>0xb8000</tt> instead of <tt>0xb0000</tt>) |
|||
===Printing a Character=== |
===Printing a Character=== |
||
While in Protected Mode, try a simple command like |
While in Protected Mode, try a simple command like: |
||
<pre> |
<pre> |
||
// C |
|||
*((int*)0xb8000)=0x07690748; |
*((int*)0xb8000)=0x07690748; |
||
</pre> |
|||
// NASM |
|||
⚫ | |||
<pre> |
|||
mov [0xb8000], 0x07690748 |
mov [0xb8000], 0x07690748 |
||
</pre> |
|||
// GAS |
|||
and GAS-guys will have |
|||
<pre> |
|||
movl $0x07690748,0xb8000 |
movl $0x07690748,0xb8000 |
||
</pre> |
</pre> |
||
⚫ | |||
=== Missing Strings === |
=== Missing Strings === |
||
Sometimes printing individual characters works, but printing strings fails. This is usually due to the <tt>.rodata</tt> section missing in the linker script. The GCC option <tt>-fwritable-strings</tt> is a substitute workaround, but the real solution is to add <tt>.rodata</tt> to the script. |
|||
<pre> |
|||
kprint("Hello World"); |
|||
</pre> |
|||
and that no "Hello World" string appear in your kernel.bin (or whatever), don't search any further |
|||
[[Category:Video]] |
[[Category:Video]] |