i have a C++ static function with variable number of arguments as declared below

static int variablecall(int karl,int k2,...)

from looking at the calling code


ret1 = ct.variablecall(2,10,50,40,30,40);
00401C0D push 28h
00401C0F push 1Eh
00401C11 push 28h
00401C13 push 32h
00401C15 push 0Ah
00401C17 push 2
00401C19 call callingtest::variablecall (401D70h)
00401C1E add esp,18h
00401C21 mov dword ptr [ret1],eax
ret1 = ct.variablecall(2,10,50,40);
00401C24 push 28h
00401C26 push 32h
00401C28 push 0Ah
00401C2A push 2
00401C2C call callingtest::variablecall (401D70h)
00401C31 add esp,10h
00401C34 mov dword ptr [ret1],eax

it is CDECL style where the CALLER cleans up the stack
so my question, is there anyway inside the function to tell the size on the stack that the variable arguments take up? maybe based on the EBP,ESP values when the function is called.

and here is the dissasembly of the function
ESP obivously would be the current stack pointer



static int variablecall(int karl,int k2,...)
{
00401D70 push ebp
00401D71 mov ebp,esp
00401D73 push ecx
int test;
test = karl;
00401D74 mov eax,dword ptr [karl]
00401D77 mov dword ptr [test],eax
test = test*2;
00401D7A mov ecx,dword ptr [test]
00401D7D shl ecx,1
00401D7F mov dword ptr [test],ecx
return test;
00401D82 mov eax,dword ptr [test]
}

obviously when the function is first entered esp would be the current stack pointer
but before ebp is pushed and set to the local base pointer, what is it before?
the base pointer of whatever function /scope is calling right?

if i make a naked function is there anyway to compare the ebp when the function is ended and the stack pointer to find out the size difference that the total parameters make? or are other factors taken into account for the EBP when it enters? (such as local variables in the calling scope?)

or is there any other way to find out the size of variable arguments?
Posted on 2004-08-08 01:28:44 by klumsy
Pheraphst Stack question can help a little.

Have a nice day or night.
Posted on 2004-08-08 10:05:51 by rea
that link was informative and useful
though it was dealing with calling c/c++ varargs procedures

when what i want to do is BE such a procedure.. finding out the size of the varargs..
but i think it could be impossible, since the CALLEr manages the stack frame and its the caller who knows the size of the varargs..
even if it was possible i found another problem MSVC++ promotes datatypes .. i.e a float to a double before sending it through, and this wouldn't go down well in my example (where i want to basically just copy the varargs to a stackframe of another function call.)
so i've given up with doing it with varargs, but now just pass in a pointer to a structure containing the data i need..
but learnt a lot in the process.
Posted on 2004-08-09 17:52:28 by klumsy
And always is nice that ;), keep moving!

Have a nice day or night.
Posted on 2004-08-09 22:58:08 by rea
It's not impossible. Just make sure you write the procedure such that at least one perameter divulges the number of arguments. printf() for example moves along the stack in accordance with the format string passed to it. Some people choose to have the first argument be the number of successive arguments. Other people might like to terminate the argument list with some signaling value. It really all depends on how the procedure is designed.
Posted on 2004-08-09 23:09:14 by iblis
in my scenario i can Only send through the args, i can't actually send through the size,
however i have any idea that i think would work with at least MSVC++

the caller seems to clean up the stack consistantly in the instruction after CALL is called
with this command
add esp,10h

so wouldn't it be possible to get the RETURN address of CALL from the stack, to find where the next command
add esp,10h would be, and read the bytes to get the 10h to find out how many bytes, and adjust that according to the static parameters as well?
Posted on 2004-08-09 23:30:29 by klumsy
Sorry that I cant understand perfectly what you whant...

But I whant only show some things that I name diferent, clean can have diferent applications: feel the space with 0's, because there is some garbage (and reuse the space) or data to protect after use (only a break febore the fill will show it), or other 'no meaning' number. But add esp, 10h is aligning the stack, the data still there (Dont know much about pagining and how stack grows, but normally still accesible lower addres esp).


Have a nice day or night.
Posted on 2004-08-09 23:49:53 by rea

the caller seems to clean up the stack consistantly in the instruction after CALL is called

This is standard C call behaviour


so wouldn't it be possible to get the RETURN address of CALL from the stack, to find where the next command add esp,10h would be, and read the bytes to get the 10h to find out how many bytes, and adjust that according to the static parameters as well?

No - the ESP adding might be done at _any_ point later on, and could cover multiple function calls... this can happen when optimizations are turned on.
Posted on 2004-08-10 00:37:36 by f0dder
ok using my example code posted in the first example.

when the vararg procedure is called..


ret1 = ct.variablecall(2,10,50,40,30,40);
00401C0D push 28h
00401C0F push 1Eh
00401C11 push 28h
00401C13 push 32h
00401C15 push 0Ah
00401C17 push 2
00401C19 call callingtest::variablecall (401D70h)
00401C1E add esp,18h
00401C21 mov dword ptr [ret1],eax


the static would look something like this


... (whatever was on there before)
28h - cause by the function call, a vararg
1Eh - as above
28h - as aboive
32h - as above
0Ah - a non variable argument for the vararg function
2 - a non static argument for the vararg function
RETURNADDRESS - the return address from the call callingtest:variablecall
OLDEBP - when our vararg function is first entered it pushes the current EBP on the static
(local viarables if existing (which we the maker of this function can know how many, so for now we'll ignore this

so if we want to get the return address (so we can read from the code after it)

mov eax, (or i could be wrong adn its plus 8

and then eax would be pointing to this line on code

add esp,18h

in


00401C19 call callingtest::variablecall (401D70h)
00401C1E add esp,18h
00401C21 mov dword ptr [ret1],eax

so we can read from the actual code to get the 18h (i might get the offset wrong but lets start from where we were.
mov eax, (or i could be wrong adn its plus 8)
mov eax,byte ptr (to get the 18h (or whatever it is) from the add esp,18h since we know that msvc++ will always put this instruction after the vararg function returns
so now eax will contain 24 (18h) (in this example), and we know that we had 2 static parameter so 8 bytes, so 24 - 8 = 16, which should be the size of the varargs which it actually is..

so i think that this technique would be an accurate method to find the size of the varargs function calls with msvc++ (using a hack of reading the code that msvc++ makes, having an assumption of what it will write)
Posted on 2004-08-10 00:38:43 by klumsy

No - the ESP adding might be done at _any_ point later on, and could cover multiple function calls... this can happen when optimizations are turned on.

if it covered multiple function calls then the function calls would have incorrect stack pointers when they entered right? as for otpomisations on, i have looked at alot of examples WITH optmisations on and haven't seen an example yet.. but i know it _could_ happen..
Posted on 2004-08-10 00:42:18 by klumsy
I finally get it, I think... ;)

so my question, is there anyway inside the function to tell the size on the stack that the variable arguments take up? maybe based on the EBP,ESP values when the function is called.


Yes like in the refered post, you can use a direct comparation of ebp and esp, guess also a comparation of the old ebp and the new ebp (in the case of stack frame), but like you "arguee" (dont know if is the word, you will fail when in the anterior stack frame have used some local I see that you understand well that, but dont know how to go with that.

You should get the idea that you will need inline a little asm in your C code, in the refered post is used eax to pass the actual esp address, because is where the locals of this scope end, and start the scope of the arguments passed, that is the key, choose a register that will be trashed inside the proc with varargs, then, inside the proc, you can calculate the size of the arguments passed, before or after a stack frame is created, with the value passed in the register of choice...

some like:



asm{
mov eax esp
}
ret1 = ct.variablecall(2,10,50,40,30,40);


inside your variable call you will need the calculation ;).

Will be interesting see this type of pass variable arguments and instead the caller align the stack, use some like ret ... exist that mnemonic?... but pheraphs only help for know the count of variable args....


Have a nice day or night.
Posted on 2004-08-10 00:58:23 by rea
About the optimization...

In the board, searching.. but dont know the exact keywords..., but when I see was this

ct.variablecall(2,10,50,40,30,40);
ct.variablecall(2,10,50,40,30,40);
ct.variablecall(2,10,50,40,30,40);
ct.variablecall(2,10,50,40,30,40);

.. Imagine that you pass diferent values and diferent lenghts, then in this case, for each call will be a: add esp,18h, the optimizer only do a: add esp,18h*nCalls (for this constant lenght case), see that after that aligment all the scopes where mad, regarded to the original caller, his scope was at 18h*nCalls far at the very last call (we should see how is handled local scope??.. a local variable of the original scope should not be accesible), (my recomendation is imagine how the scopes look before the aligment, and for what that type of aligment is valid whitout affect reentrant code, or the funtions scope, and not programm crash) but because now I understand you only whant know inside the called function, then

asm{

mov eax esp
}
ret1 = ct.variablecall(2,10,50,40,30,40);
asm{
mov eax esp
}
ret1 = ct.variablecall(2,10,50,40,30,40);

asm{
mov eax esp
}
ret1 = ct.variablecall(2,10,50,40,30,40);

asm{
mov eax esp
}
ret1 = ct.variablecall(2,10,50,40,30,40);

asm{
mov eax esp
}
ret1 = ct.variablecall(2,10,50,40,30,40);
asm{
mov eax esp
}
ret1 = ct.variablecall(2,10,50,40,30,40);


Also if optimizer is turned on, because the function is designed for that.
Posted on 2004-08-10 01:07:47 by rea

asm{
mov eax esp
}
ret1 = ct.variablecall(2,10,50,40,30,40);


that would work and is a good idea (however if one the the values say 2,10,this->that,4)
would happen then its possible the this->that etc would ruin my register :(
anyhow i don't want to do asm from Outside the function call, only inside..
i'm going to experiment a little with the optomisations and see if they do indeed 'wreck' my idea.
i'm pretty sure that architectural (like function calls) are someting the optomiser keeps quite standard not to introduce horrid little weird bugs..
Posted on 2004-08-10 01:50:01 by klumsy
ok you are right, with full optomisations it consecture varargs calls it does just do one add esp, N*whatever
so another question, is there anythign you can write in code to tell the compiler NOT to optomise that section of code?
Posted on 2004-08-10 02:19:34 by klumsy

ok you are right, with full optomisations it consecture varargs calls it does just do one add esp, N*whatever

Darn, didn't see this before I had done a simple C+asmlisting that shows this happening. It's not just with varags, it's for all C calling convention routines.

Oh. and EBP,ESP comparisons can't be used either, as the optimizer can choose to not use standard frames, and instead treat EBP as yet a register.


so another question, is there anythign you can write in code to tell the compiler NOT to optomise that section of code?

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccelng/htm/pragm_21.asp

...how come you can't pass a "this is the end of parameters" thingy?
Posted on 2004-08-10 07:31:59 by f0dder
The thing is that at runtime, you can only know the diference from addressses, all the information of the languge in code is lost.

Then you will not know what type of argument was passed at runtime, the only way is pass information about the arguments passed is pass extra information, like iblis say about the control string of printf, not only the number but the type %s,%d, .... .

2,10,this->that,4

you will dont know the diference of the arguments passed, ..., Dont remember exactly how work a macro (or function?) that handle varargs in C, pheraphs only return the number of arguments passed, but without what type they are, you should get this information somewhere else. Look at the disassembly of that thing.


Have a nice day or night.
Posted on 2004-08-10 10:43:41 by rea
the reason in my sceaniro is i wanted to make a methoddispacher method similar to that in my artcile (in the article rather than vararguments) i just pass in a structure that contains the parameters..
so in this one i would pass in a static ptr to the address, a static pointer the the class instance "this", and variable arguments, which would relate exactly to the arguments of the function to call. so it would copy form the varargs to the stack for the called function..

so without finding the size of the varargs i'd need the user to know the size and put that in, or use a terminator as you say.

however what stopped me from using this idea is how c++ automatically promotes certian datatypes (i.e a float to a double, which would mean that if my tobecalled function excepts a float, c++ promoting the vararg float to a double would mess up the whole list of parameters/stack frame anyhow so i've given up this idea, but was still interested in the topic of this thread for curiousities sake.)
i'm curious why c/c++ automatically promotes a float to a double (since a float is already 32 bits), my assumption is so that people who pass in a double as a float for printf or something, don't make printf break, (because its already converted to a double).

the reason i don't trust a terminator is what if one of the parameters contains the same value.


Oh. and EBP,ESP comparisons can't be used either, as the optimizer can choose to not use standard frames, and instead treat EBP as yet a register.

since i'd be implementing the vararg function i'd be using naked and using my own stack frames..
however i don't think i'd be able to work it out frm comparing ebp and esp, and ebp would also be influences by the CALLER scopes local variables and such wouldn't it?

so i think i'll stay with my technique mentioned in the article, where i just pass in a pointer to a structure adn the size of the structure. but its been an interesting journey.

over and out.
thanks for all the knowledge
Posted on 2004-08-10 18:45:02 by klumsy

i'm curious why c/c++ automatically promotes a float to a double (since a float is already 32 bits), my assumption is so that people who pass in a double as a float for printf or something, don't make printf break, (because its already converted to a double).
Because the original Unix C compilers made that automatic promotion, and that info was published in the classic Kernighan and Ritchie (K&R) book on C. Of course, every compiler writer implemented this to stay compatible with Unix C, and be faithful to K&R. When C and C++ were finally getting standardized, there was too much code (and too many compilers) that relied on the auto-promo assumptions. So it's still part of the language wherever argument types are not specified.
Posted on 2004-08-10 21:56:34 by tenkey