Functions with variable-length argument lists
Functions with variable-length argument lists
Hi there,
I am trying to implement a simple os with multi-segment memory model (real address mode).
Everything seems to be ok but once I set stack segment different from data segment, functions
with variable-length argument lists do not work properly. I am using gcc's __builtin_va_list for now
and I think that might be trouble. So my question is whether somebody can post a code that
handles this feature ( i.e. va_list, va_arg, va_start ...) .but everything built upon 'standard'
data types like int, char ...
thnx in advance & regards,
devel.
I am trying to implement a simple os with multi-segment memory model (real address mode).
Everything seems to be ok but once I set stack segment different from data segment, functions
with variable-length argument lists do not work properly. I am using gcc's __builtin_va_list for now
and I think that might be trouble. So my question is whether somebody can post a code that
handles this feature ( i.e. va_list, va_arg, va_start ...) .but everything built upon 'standard'
data types like int, char ...
thnx in advance & regards,
devel.
Yes, that's true but it is possible to apply address/codesize overrides (gas directive
'.code16' or '.code16gcc' ) so it is possible to emit code that runs in 16-bit
environment (with some additional setings). Regarding my problem, I hope that once I get
code for va_list handling and compile it for 16-bit environment my problem might be solved.
regards,
devel
'.code16' or '.code16gcc' ) so it is possible to emit code that runs in 16-bit
environment (with some additional setings). Regarding my problem, I hope that once I get
code for va_list handling and compile it for 16-bit environment my problem might be solved.
regards,
devel
Sample code for what? Ignoring the 16-bit multi segmented nature of your question is ignoring the entire point of your post. What do you want?Please forget about 16-bit environment and segmented memory model. If somebody could post some sample code then it would be really helpful.
And in case a third opinion is needed, get a 16 bit compiler. Or at least, use a flat memory model. 'Undefined territory' means that GCC can do just about anything, as you're violating its assumptions in a big way. The worst that can happen? You can munge your CMOS, munge your HDD...
Hi,
The reason that's difficult to answer is that it depends on the calling convention you are using. Generally, if you look in stdarg.h, you will see that va_arg et. al. are defined as pointing to a GCC builtin function. The compiler then substitutes the appropriate code.
If you are using 32 bit GCC, args are pushed on a stack. It's therefore fairly easy to make up the macros by looking at the stack frame and incrementing a pointer by sizeof(theargumentyouwant).
If you are using 64 bit GCC, the frist 6 args are passed via registers (rdi, rsi, rdx, rcx, r8, r9 in that order) and the rest are passed on the stack. This means that your macros suddenly become prohibitively complex and is why you should use the GCC builtin.
What are you trying to achieve at a higher level?
Cheers,
Adam
The reason that's difficult to answer is that it depends on the calling convention you are using. Generally, if you look in stdarg.h, you will see that va_arg et. al. are defined as pointing to a GCC builtin function. The compiler then substitutes the appropriate code.
If you are using 32 bit GCC, args are pushed on a stack. It's therefore fairly easy to make up the macros by looking at the stack frame and incrementing a pointer by sizeof(theargumentyouwant).
If you are using 64 bit GCC, the frist 6 args are passed via registers (rdi, rsi, rdx, rcx, r8, r9 in that order) and the rest are passed on the stack. This means that your macros suddenly become prohibitively complex and is why you should use the GCC builtin.
What are you trying to achieve at a higher level?
Cheers,
Adam
Hi,
As you have been warned, it is implementation-specific (future versions of GCC are absolutely welcome to change this without notice!), but here's theb start of an old, horrible printf()-like function I copied form somewhere before I saw the light.
..and so on - you get the idea.
Cheers,
Adam
As you have been warned, it is implementation-specific (future versions of GCC are absolutely welcome to change this without notice!), but here's theb start of an old, horrible printf()-like function I copied form somewhere before I saw the light.
Code: Select all
int Printf(const char *fmt, ...)
{
/* a higher level output function for the kernel */
if(DebugPrefix)
{
Puts(DebugPrefix);
PutChar(' ');
}
char **arg = (char **) &fmt;
char *p;
char buffer[STR_BUFFER_MAX_OCT];
u16 padlen;
int c;
arg++;
while((c=*fmt++)!=0)
{
if(c!='%')
PutChar(c);
else
{
c = *fmt++;
switch(c)
{
case 'd': /* decimal integer */
case 'i':
ltostr(*((long *)arg++), buffer);
Puts(buffer);
break;
case 'x': /* hexadecimal integer */
case 'X':
htostr(*((long *)arg++), buffer);
Puts(buffer);
break;
case 'o': /* octal */
case 'O':
otostr(*((long *)arg++), buffer);
Puts(buffer);
break;
....
Cheers,
Adam