Printing To Screen: Difference between revisions

Jump to navigation Jump to search
[unchecked revision][unchecked revision]
Content deleted Content added
Solar (talk | contribs)
→‎Printing Integers: '''If''' we provide example code, we could just as well go the full distance. ;-)
Solar (talk | contribs)
→‎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.
Line 105: Line 105:
== Printf ==
== Printf ==


If you're working with C, you may want to print any number of arguments and you may have looked at the <tt>stdarg.h</tt> file from other Operating Systems (e.g. linux 0.1 and Thix 0.3.x). These macro definitions may be a bit weird to understand as they're basically C voodoo using pointers and casts and sizeof. Beware before porting them to 16 bit systems, though.
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.


The good news are that <tt>stdarg.h</tt> is part of a freestanding implementation, so you can #include it even from your kernel source files. Under [[GCC]], the following simple implementation uses the gcc's built-in functionality to do all the work for you:
<tt>va_start()</tt> points to the first variable argument.
<tt>va_arg()</tt> advances the pointer, then evaluates to the previous argument (comma operator).
<tt>va_end()</tt> doesn't do anything.


The good news are that stdagr.h is part of the required features for freestanding implementations, so you can #include it even from your kernel source files.

'''Example:'''

To implement <tt>va_start()</tt>, you extract the address of the last 'known' argument and advance (yes, it's a <tt>+</tt> since you're rewinding the stack) to the next stack item. The voodoo comes to the fact that things are automatically aligned on 32bits boundary on the stack, even if just 1 byte. This approach however only works on x86 and also depends on the calling convention. Some calling conventions like fastcall, or on other architectures like x86-64 this approach doesn't work because the parameters are passed in registers and/or stack. Under [[GCC]], the following simple implementation uses the gcc's built-in functionality to do all the work for you:
<pre>
<pre>
#define va_start(v,l) __builtin_va_start(v,l)
#define va_start(v,l) __builtin_va_start(v,l)
Line 124: Line 117:
</pre>
</pre>


An implementation of <tt>stdarg.h</tt> and <tt>printf()</tt> is available from geezer/osd ([http://my.execpc.com/~geezer/osd/code/inc/stdarg.h stdarg.h], [http://my.execpc.com/~geezer/osd/code/inc/_printf.h _printf.h], [http://my.execpc.com/~geezer/osd/code/tinylib/stdio/doprintf.c doprintf.c]).
Not using those, <tt>va_arg()</tt> requires a bit more black magic since you have two things to do:
* advance to the next item
* return the value of the (previously current) item

You can get [http://my.execpc.com/~geezer/osd/code/inc/stdarg.h stdarg.h], [http://my.execpc.com/~geezer/osd/code/inc/_printf.h _printf.h] and [http://my.execpc.com/~geezer/osd/code/tinylib/stdio/doprintf.c doprintf.c] from geezer/osd.


Also, Solar's public domain c library has a starg.h implementation as well.
Solar's [http://pdclib.rootdirectory.de Public Domain C Library] has those implementations as well.


== Troubleshooting ==
== Troubleshooting ==