pushing arguments

Programming, for all ages and all languages.
Post Reply
iammisc

pushing arguments

Post by iammisc »

can i call a function in c by just pushing the arguments or do i have to call it using the normal way.

Thanks.
durand
Member
Member
Posts: 193
Joined: Wed Dec 21, 2005 12:00 am
Location: South Africa
Contact:

Re:pushing arguments

Post by durand »

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
Maybe there are more but I'll just do these. I'm assuming you use GCC.

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." );

YeXo

Re:pushing arguments

Post by YeXo »

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?

Code: Select all

int dmesg( char *format, ... )
{
        va_list ap;
        va_start( ap, format )
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re:pushing arguments

Post by Solar »

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.
durand
Member
Member
Posts: 193
Joined: Wed Dec 21, 2005 12:00 am
Location: South Africa
Contact:

Re:pushing arguments

Post by durand »

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.

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
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.
YeXo

Re:pushing arguments

Post by YeXo »

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!
YeXo

Re:pushing arguments

Post by YeXo »

@durand: Now I was studying your code better, I asked myself why this line of code is there:

Code: Select all

void **start;
Your code initializes it in va_start but never reads or changes it.
durand
Member
Member
Posts: 193
Joined: Wed Dec 21, 2005 12:00 am
Location: South Africa
Contact:

Re:pushing arguments

Post by durand »

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.
Post Reply