use of .... (variable arguments to a function)
use of .... (variable arguments to a function)
ok I feel like a real newbie asking this question, but I have a reason...
I've already written complex programs that have had functions with varying amounts of input, but I've always had vectors to help me....
So for that reason I don't know how to use the ... operator in defining and passing args to a function....
So my questions are:
1) how do I use ... in the defining of a function?
2) How do I know how many args are passed to the function within the ....
3) How do I access the individual variables passed to the function through the ....
4) ASM wise how do I tell how many arguments are passed to the function (how and where are they pushed onto the stack?)
Yah in case you didn't guess I am re-writing the printf function for my OS so it can print variables too...
Thanks in avance,
Jules
P.S: Yes, The first few lines were an attempt to justify myself..., but all true I assure you..., please don't yell at me...
edit: Yah, I forgot to say this is in C by the way...
I've already written complex programs that have had functions with varying amounts of input, but I've always had vectors to help me....
So for that reason I don't know how to use the ... operator in defining and passing args to a function....
So my questions are:
1) how do I use ... in the defining of a function?
2) How do I know how many args are passed to the function within the ....
3) How do I access the individual variables passed to the function through the ....
4) ASM wise how do I tell how many arguments are passed to the function (how and where are they pushed onto the stack?)
Yah in case you didn't guess I am re-writing the printf function for my OS so it can print variables too...
Thanks in avance,
Jules
P.S: Yes, The first few lines were an attempt to justify myself..., but all true I assure you..., please don't yell at me...
edit: Yah, I forgot to say this is in C by the way...
Re: use of ....
Simple, you just put ... as the last argument of the arg list like for a simple printf:suthers wrote: 1) how do I use ... in the defining of a function?
Code: Select all
int printf(const char* fmt, ...);
You don't that's why you either have a terminating argument such as a NULL or you have the caller tell you how many arguments are being passed. For example, printf knows how many arguments it is going to be receiving by parsing its format string.suthers wrote: 2) How do I know how many args are passed to the function within the ....
Use the va_* macros. For example(This code might not work or even be syntactically correct. Its only purpose is for you to get the basic gist of things):suthers wrote: 3) How do I access the individual variables passed to the function through the ....
Code: Select all
void using_var_args(int num_args, ...)
{
va_list args;
int i = 0;
va_start(args, num); /* the first argument is a va_list. The second is the last non ... argument to a function */
printf("the numbers passed are : ");
for(;i < num_args;i++) {
int cur = va_arg(args, int); /* the first argument is a va_list. The second is the type to return */
printf("%d,", cur);
}
/* finally remember to call va_end */
va_end(args);
}
I'm assuming this is for the i386 processor. Other processors are different, even x86_64 which you might assume to be like the i386 is different. Basically, you first need to know the stack offset at which your last argument is located. Then you'd have to use that info as the base for other arguments. For example, if all your arguments are integers and your last argument was the first argument, it would be at ebp offset 12. So, the next argument would be at ebp offset 16 and the one after that would be at 20 and the one after that at 24 and so on.suthers wrote: 4) ASM wise how do I tell how many arguments are passed to the function (how and where are they pushed onto the stack?)
Hope that helps.
Look Here for more info:
http://wiki.osdev.org/Stack
and
http://www.cplusplus.com/reference/clib ... start.html
http://www.cplusplus.com/reference/clib ... a_arg.html
http://www.cplusplus.com/reference/clib ... a_end.html
- Combuster
- Member
- Posts: 9301
- Joined: Wed Oct 18, 2006 3:45 am
- Libera.chat IRC: [com]buster
- Location: On the balcony, where I can actually keep 1½m distance
- Contact:
Re: use of ....
and varargs + assembly + x86_64 = Bad Idea (tm)I'm assuming this is for the i386 processor. Other processors are different, even x86_64 which you might assume to be like the i386 is different.
Re: use of ....
What would be the best way to 'emulate' a va_list though...
would I use a void pointer and increment it by 4 to get the next arg and take (&the_last_arg_passed_to_printf_that's_non_...) + 4 as the address of the beginning o the list?
Thanks in advance,
Jules
P.S. I'll try to implement this way, but It might not work, so if anybody has any better suggestions please tell me... (or reassure me that this is a good idea/it will work would be nice too...)
would I use a void pointer and increment it by 4 to get the next arg and take (&the_last_arg_passed_to_printf_that's_non_...) + 4 as the address of the beginning o the list?
Thanks in advance,
Jules
P.S. I'll try to implement this way, but It might not work, so if anybody has any better suggestions please tell me... (or reassure me that this is a good idea/it will work would be nice too...)
Re: use of ....
You don't need to 'emulate' a va_list, just use it! It's a GCC builtin, not in the standard library. An example from my code:suthers wrote:What would be the best way to 'emulate' a va_list though...
would I use a void pointer and increment it by 4 to get the next arg and take (&the_last_arg_passed_to_printf_that's_non_...) + 4 as the address of the beginning o the list?
Thanks in advance,
Jules
P.S. I'll try to implement this way, but It might not work, so if anybody has any better suggestions please tell me... (or reassure me that this is a good idea/it will work would be nice too...)
Code: Select all
#include <stdarg.h>
...
void X86StackFrame::construct(ProcessorState &state,
uintptr_t returnAddress,
unsigned int nParams,
...)
{
// Obtain the stack pointer.
uintptr_t *pStack = reinterpret_cast<uintptr_t*> (state.getStackPointer());
// How many parameters do we need to push?
// We push in reverse order but must iterate through the va_list in forward order,
// so we decrement the stack pointer here.
pStack -= nParams+1; // +1 for return address.
uintptr_t *pStackLowWaterMark = pStack;
*pStack++ = returnAddress;
va_list list;
va_start(list, nParams);
for(int i = nParams-1; i >= 0; i--)
{
*pStack++ = va_arg(list, uintptr_t);
}
va_end(list);
// Write the new stack pointer back.
state.setStackPointer(reinterpret_cast<uintptr_t> (pStackLowWaterMark));
}
Re: use of ....
Doesn't work for me....
But then again I;m using an antiquated version of gcc (3.4.2 and the mingw port at that...).
Could that have something to do with it?
Thanks in advance,
Jules
But then again I;m using an antiquated version of gcc (3.4.2 and the mingw port at that...).
Could that have something to do with it?
Thanks in advance,
Jules
Re: use of ....
What doesn't work? Are you sure you included <stdarg.h>?
Re: use of ....
including a stdlib include in an OS?
I didn't think that would work, so I didn't try...
Now to figure out how to tell gcc what include path to use in the command line
Jules
I didn't think that would work, so I didn't try...
Now to figure out how to tell gcc what include path to use in the command line
Jules
Re: use of ....
Did you even read what I wrote?JamesM wrote:It's a GCC builtin, not in the standard library.
Re: use of ....
Sorry I didn't read tha part...
Jules
Jules
Re: use of ....
I also believe in gcc that you could simply use __builtin_va_list, __builtin_va_arg, etc. However, I read about this a long time ago and I might be wrong.
- Combuster
- Member
- Posts: 9301
- Joined: Wed Oct 18, 2006 3:45 am
- Libera.chat IRC: [com]buster
- Location: On the balcony, where I can actually keep 1½m distance
- Contact:
Re: use of ....
True. From stdarg.h coming with gcc:
Code: Select all
#define va_start(v,l) __builtin_va_start(v,l)
#define va_end(v) __builtin_va_end(v)
#define va_arg(v,l) __builtin_va_arg(v,l)
Re: use of ....
Weird all my standard args contains is:Combuster wrote:True. From stdarg.h coming with gcc:Code: Select all
#define va_start(v,l) __builtin_va_start(v,l) #define va_end(v) __builtin_va_end(v) #define va_arg(v,l) __builtin_va_arg(v,l)
Code: Select all
#ifndef RC_INVOKED
#include_next<stdarg.h>
#endif
Jules
Re: use of ....
Thanks, fixed, all I did was remove '-nostdinc' from the command line, I though: "Ok, so I'm was trying to pass an include path to gcc, which is its default path... , how about I just allow it to use its standard command path...", Yah I know I'm pretty stupid sometimes....
Thanks a mill for the help.
Thanks,
Jules
Thanks a mill for the help.
Thanks,
Jules
- Combuster
- Member
- Posts: 9301
- Joined: Wed Oct 18, 2006 3:45 am
- Libera.chat IRC: [com]buster
- Location: On the balcony, where I can actually keep 1½m distance
- Contact:
Re: use of ....
its not in /usr/include, its in the GCC directory (one of the other places it will look for its headers):and also there is no other stdargs file in my include directory, so I don't understand how the #include_next could work...
Code: Select all
/usr>find -iname 'stdarg.h'
./lib/gcc/i686-pc-mingw32/3.4.4/include/stdarg.h