can i call a function in c by just pushing the arguments or do i have to call it using the normal way.
Thanks.
pushing arguments
Re:pushing arguments
You need to provide the calling context. Can you call a function in C from where? Since I'm not 100%, I'll give you a few different options:
Calling a C function from asm
Calling a variable function
Calling a variable argument function
- Calling a C function from asm.
- Calling a variable function
- Calling a variable argument function
Calling a C function from asm
Code: Select all
--- C function ---
void function( unsigned int eax, unsigned int ebx, unsigned int ecx )
{
....
}
--- ASM code ---
pushl %ecx
pushl %ebx
pushl %eax
call function
popl %eax
popl %ebx
popl %ecx
Calling a variable function
Code: Select all
typedef int (*cool_func)(int,void*);
int func1( int val, void *data )
{
return val * 100;
}
int func2( int val, void *data )
{
return val * 500;
}
int calling_function( cool_func func )
{
return func( 5, NULL );
}
...
calling_function( func1 );
calling_function( func2 );
...
Calling a variable argument function
Code: Select all
int dmesg( char *format, ... )
{
va_list ap;
va_start( ap, format );
char * string;
int number;
while ( *format != 0 )
switch (*format++)
{
case 's':
string = va_arg( ap, char* );
print string string;
break;
case 'i':
number = va_arg( ap, char* );
print integer number;
break;
default:
break;
}
va_end( ap );
return 0;
}
dmesg( "%s%i%s", "I feel ", 100, " years old." );
Re:pushing arguments
Is it possible to use the last type (the one with variable arguments) without the standard c library. I'm asking this because I want to implement it into a kernel.
I'm talking about these lines of code. Do they rely on the c library or not?
I'm talking about these lines of code. Do they rely on the c library or not?
Code: Select all
int dmesg( char *format, ... )
{
va_list ap;
va_start( ap, format )
Re:pushing arguments
They do. It's <stdarg.h> we're talking about here. The downside is, this can not be implemented in 100% portable C. The upside is, every compiler must provide some way to implement it. AFAIK, GCC provides its own version of this header somewhere in its directory structure. If you look for a more generic way, check out the PDCLib (see my signature) which provides a generic implementation that has been tested to work OK (with x86 GCC, at least).
Every good solution is obvious once you've found it.
Re:pushing arguments
And the last time I posted code on this site, it caused a little bit of a stir.. but here is code I wrote myself which you may use freely.
This should be your "stdarg.h" file and it will work on an 32 bit x86 system compiled with GCC without any problems. It basically just manipulates the stack.
You'll need to fix some line wrapping issues
Then you could include it and dmesg should compile - give or take.
Does anyone have any suggestions otherwise? My pointer arithmetic could use some cleaning and I could do with some variable size explicitness. However, it will work fine.
This should be your "stdarg.h" file and it will work on an 32 bit x86 system compiled with GCC without any problems. It basically just manipulates the stack.
Code: Select all
#ifndef _STDARG_H
#define _STDARG_H
#ifndef _HAVE_VA_LIST
#define _HAVE_VA_LIST
typedef struct
{
void **ptr;
} va_list;
#endif
#define va_start( ap, lastarg ) \
ap.ptr = (void**)( (unsigned int)&lastarg + sizeof(const char*) );
#define va_arg( ap, type) \
((type)*(ap.ptr)); \
ap.ptr = (void**)( ((unsigned int)ap.ptr) + sizeof( type ) );
#define va_end( ap ) \
ap.ptr = NULL;
#endif
Then you could include it and dmesg should compile - give or take.
Does anyone have any suggestions otherwise? My pointer arithmetic could use some cleaning and I could do with some variable size explicitness. However, it will work fine.
Re:pushing arguments
Thanks for your help Solar and for the code durand. I'll test it as soon as I'm at home. I hope it works!
Re:pushing arguments
@durand: Now I was studying your code better, I asked myself why this line of code is there:
Your code initializes it in va_start but never reads or changes it.
Code: Select all
void **start;
Re:pushing arguments
Just delete it. I just did. If it's not used, it's not important. I had a rewind macro at one point and it's left overs of that.