Reputation: 2462
I'm writing my own OS using BCC and I'd like to write a printf from scratch, without the variadic arg macros. Is there any reason I can't do that? I have a good start, but I can't get the first argument after the string.
void print_f(char *fmt, ...) {
char *str = fmt;
uint16_t *arg = (uint16_t *)&fmt + 1;
uint32_t *long_arg;
while (*fmt != '\0') {
if (*fmt == '%') {
switch(*++fmt) {
case 'c':
putchar((uint8_t)*arg);
arg++;
break;
default:
print_f("Malformed printf");
break;
}
} else {
putchar(*fmt);
}
fmt++;
}
return;
}
I think I am suppose to increment the pointer one address space and go from there, but it just returns garbage.
Upvotes: 1
Views: 1494
Reputation: 157414
Incrementing the address of the first argument to access subsequent variadic arguments may work on some older architectures, but it will not work in general, and certainly not on on x86-64, assuming that that is your target:
Some otherwise portable C programs depend on the argument passing scheme, implicitly assuming that all arguments are passed on the stack, and arguments appear in increasing order on the stack. Programs that make these assumptions never have been portable, but they have worked on many implementations. However, they do not work on the AMD64 architecture because some arguments are passed in registers. Portable C programs must use the header file
<stdarg.h>
in order to handle variable argument lists.AMD64 ABI, 3.5.7 Variable Argument Lists
If you are interested in reimplementing <stdarg.h>
yourself on x86-64, there are sufficient details including a va_arg
algorithm in the above reference.
Upvotes: 4