![]() |
|
Passing parameters to C++ functions manually by pushing them onto the stack |
Mr. Xboxor
Member #3,763
August 2003
![]() |
Ok, so let's say that in my program I store the certain parameter types that a particular function takes. Using this information, and a pointer to data that I want to pass to a function, I want to push the data onto stacks/put it into registers manually through inline assembly code, and read the return value of the function. An example:
I'm afraid this is a very difficult question, so I thankyou ahead of time for any time you spend on it. Basically I want to know what the parameter passing conventions are for the various basic data types, and how they apply to classes, pointers, and the like. Oh, and how to read the return value the function returns. I'm guessing it may be compiler specific, but that is ok. I'm using the mingw port of gcc. Any information really would be useful. Thanks for any help. Chris Mueller "Java is high performance. By high performance we mean adequate. By adequate we mean slow." -Mr. Bunny |
Jonatan Hedborg
Member #4,886
July 2004
![]() |
I have no idea, but im sure your disassembler of choice will answer that question
|
Evert
Member #794
November 2000
![]() |
Quote: Basically I want to know what the parameter passing conventions are for the various basic data types, and how they apply to classes, pointers, and the like. As I recall, parameters are pushed onto the stack right to left, but you can check that easily enough by looking at the assembler output. Quote: Oh, and how to read the return value the function returns. I'm not sure if this is still true, but it used to be true that integers were returned in AL/AX/EAX for char/short/int. Pointers are returned in DS:EDI (I think - might be DS:ESI). Quote: I'm using the mingw port of gcc. Any information really would be useful. Take note of the -s compiler switch: it will make the compiler spit out the generated assembler source code. |
Korval
Member #1,538
September 2001
![]() |
Quote: Basically I want to know what the parameter passing conventions are for the various basic data types, and how they apply to classes, pointers, and the like. No, you do not. I feel like we've had this conversation before, but here goes. This changes from processor to processor. Your code will, almost certainly not work running natively in 64-bit mode on x86-64 chips (since they have an additional 8 registers), and any code that does will almost certainly not do it on 32-bit chips. And, without question, you can forget about running it on Mac's or anything that isn't an x86 chip. There is no singular hard-and-fast rule for this. And, as you have pointed out, it can even vary from compiler to compiler. One of C's primary (initial) functions was to abstract away this kind of thing so that we wouldn't need it. I'm pretty sure that the answer to the obvious question of "Why are you needing to do this?" is going to involve some attempt to call a function of runtime-defined arguments in a fashion that C was not designed to handle. Think of it this way. Microsoft, knowing full well that COM was only going to be used on x86 machines, could have had macros pushing and popping arguments on and off the stack. However, they do not. They make you call IDispatch interfaces via passing an array of arguments and a "pointer" for a return value. This solution, while bothersome, works, and works guarenteeably and without question. What you're trying to do does not. Quote: Take note of the -s compiler switch: it will make the compiler spit out the generated assembler source code. Will the assembly actually have the argument pushing/popping in it? I seem to recall that, on some GCC's I've used, the assembler that they output is somewhat... incomplete regarding these kinds of details. It expects the linker to fill in the blanks (which makes sense, as it allows libraries built by other compilers to be used by GCC, and vice-versa). |
Kitty Cat
Member #2,815
October 2002
![]() |
Quote: One of C's primary (initial) functions was to abstract away this kind of thing so that we wouldn't need it. C also allows you to have an indeterminate arguments, whereas C++ doesn't. He could just define the function as int somefunc(myargs), declare it as int somefunc(), and just pass the arguments as if it's expecting it. It works with function pointers, too.
-- |
CascoOscuro
Member #4,966
August 2004
![]() |
Quote: C also allows you to have an indeterminate arguments, whereas C++ doesn't.
It is not true. In C++ as C you can put an indeterminated number of arguments (for example, printf(const char* str, ...)) and use them with the cstdarg macros. |
Kitty Cat
Member #2,815
October 2002
![]() |
Quote: It is not true. In C++ as C you can put an indeterminated number of arguments (for example, printf(const char* str, ...)) and use them with the cstdarg macros. If you look at my example though, that's not quite what it does (ie. no va_args.. just some prototype and casting trickery). Although it might still work with (...) in place of (), but the compiler may not be bound to put those extra arguments on the stack like normal arguments.. I don't know. -- |
Oscar Giner
Member #2,207
April 2002
![]() |
func(int a, ...) is variable number of arguments (but at least 1 argument is mandatory), which is different from func(), indeterminate number of variables (but the number of arguments taken by the real function is fixed, just unspecified in the declaration) Quote: Take note of the -s compiler switch: it will make the compiler spit out the generated assembler source code. It's -S (uppercase) -- |
CascoOscuro
Member #4,966
August 2004
![]() |
Quote: is different from func(), indeterminate number of variables In pure C. In C++ is like func(void), so you must use in C++ func(...). About your idea of use manually the stack, use the asm{} instruction. //I'm using gcc assembler notation asm{ mov %esp,%ebp subl %esp, BYTES_FOR_YOUR_LOCAL_VARIABLE #Operations which you want... addl %esp, BYTES_FOR_YOUR_LOCAL_VARIABLE mov %ebp,%esp } Altough you can simulate the stack with a STL stack modifier. |
Oscar Giner
Member #2,207
April 2002
![]() |
func(...) is not equivalent to C's func(). Actually, func(...) is quite useless since there's no standard way to access the parameters (va* functions require at least one parameter). See this:
This is valid C code. There's no way to do this using C++. Declaring f as int f(...) (and keeping its definition as int f(int a, int b)) will give you a link error. C++ had to remove this feature to allow function overloading. -- |
Kitty Cat
Member #2,815
October 2002
![]() |
Would you be able to do this? struct someStruct { // or class extern "C" int (*funcptr)(); } You should be able to attach a normal C++ function to a C function pointer.. the only difference between the two is name mangling which should be fine as long as you play by the compiler's rules. You might need to make the whole struct a C-style struct (as in my previous example), or maybe just that one member (as here) if the compiler allows that. But as long as the function pointer has () and uses the C mangling scheme, you should be able to attach any C or C++ function to it (class member functions can be tricky and may not be worth it.. just stic to normal C++ or C functions), and be able to pass any number of arbitrary arguments to the function pointer. -- |
Mr. Xboxor
Member #3,763
August 2003
![]() |
Yes, I have brought this up before, so sorry for the repitition. First off, I'm not worried about compiler or hardware specific issues. I wasn't planning on making the program multi-platform or anything like that. Secondly, inside the program, when I wish to call a function, all I will have is a pointer to the data inside of the program. I won't know at compile time how the parameters should be passed, but I will at runtime. Basically, at runtime, inside of the program, I will have a pointer to the data I want to pass to the function, I will know how many bytes each parameter consists of, and I will even know the type of the parameter. But I will not know this at compile time, so it rules out the use of C function pointers or whatever. I will take a look at the assembly code output though, thanks for that suggestion. Chris Mueller [edit] "Java is high performance. By high performance we mean adequate. By adequate we mean slow." -Mr. Bunny |
gillius
Member #119
April 2000
|
Use functors to do what you are wanting to do, and store the parameters in the functor object. Gillius |
Kitty Cat
Member #2,815
October 2002
![]() |
Quote: Secondly, inside the program, when I wish to call a function, all I will have is a pointer to the data inside of the program. Why not make the functions take a void* argument to that data, and have the beginning of the function extract it however it needs? -- |
Mr. Xboxor
Member #3,763
August 2003
![]() |
Ah, when I posted this question last time I got the same responses. What I'm trying to do is extremely difficult, and platform dependent, so I'm giving up. I didn't want to have to program a function any differently. Meaning, I wanted to take a function I had already written, and just call it by passing parameters to it manually, but that's too hard. Sorry for any inconvenience. "Java is high performance. By high performance we mean adequate. By adequate we mean slow." -Mr. Bunny |
Billybob
Member #3,136
January 2003
|
This is FAR from compiler dependant. If it was, how would programs call DLL functions? On Windows, at least, the convention is to push arguments right to left, and then pop them left to right in the function. I really don't see any reason pushing arguments yourself is seen as bad. The compiler does it anyway! You may not end up cross-platform, but then again maybe you will! I see no reason for Linux to push and pop arguments differently, though it's certainly possible. Correct me if I'm horribly wrong! EDIT: And yes, the ASM produced by GCC contains pushing and poping.
|
Kitty Cat
Member #2,815
October 2002
![]() |
Quote: If it was, how would programs call DLL functions? Function pointers with known paramters/return types. You can get around unknown paramters by using a C function pointer with indeterminate paramters (ie. (*funcptr)()), but he only has the stack data in memory and doesn't know what it is (only the function that's being called does). He should probably rethink his idea since this is completely looking like hack-ville. -- |
Bob
Free Market Evangelist
September 2000
![]() |
Quote: If it was, how would programs call DLL functions? DLL interface to C functions is well defined. It's independent of language or compiler. Try using C++ classes across DLLs and compilers. Quote: The compiler does it anyway! The compiler is not required to. One can implement a fully-compliant C compiler without a stack. -- |
|