im trying to link a obj file in my vc++ program but for some reason it crashes, look

void _declspec(naked) SumMultiply(void){

ret // this will return to my programs code

if i do this all is fine and the program works when i call SumMultiply(); but if i do

void _declspec(naked) SumMultiply(void){

push offset first
push offset second
call MyProcedure
ret // this will lead me to somewhere and will crash my program

anyone have an idea of what could i do to fix this ? i think the problem is the call MyProcedure but dunno how to fix, if anyone could help

thanks in advance.
Posted on 2002-05-19 14:14:13 by The Keeper
void _declspec(naked) SumMultiply(void){

push offset first
push offset second

call MyProcedure

pop offset first
pop offset second
ret // this will lead me to somewhere and will crash my program

You need to pop the pushed values...
Posted on 2002-05-20 06:44:07 by PredeX
hello, it still crashing, when i compile with vc++ it gives a warning in the 2 pops
warning C4409: illegal instruction size
warning C4409: illegal instruction size

push offset first
push offset second
call MyProcedure

after the ret that sends me to somewhere that i would crash i used the ''a" command in sice which means assemble and typed ret, it leaded to another place that i would crash then i did the same thing and it brought me back to my program code :/ no idea why, theres something i dont undernet ://

hope anyone can help me out
thanks a lot.
:confused: :confused: :confused: :confused: :confused:
Posted on 2002-05-20 10:56:58 by The Keeper
Whats the calling convention of the procedure "MyProcedure"?
If it is a C call then the caller is responsible for stack cleanup.

This is I believe what PredeX is trying to get at, but forgot you cannot pop to an immediate value (pop 6 what does that do?).

Change them both to "pop edx".

It may be easier to use a debugger on this, simply write down esp and ebp before the first push, and compare them to esp & ebp after the call. They should be the same, if they are not, then your problem comes from stack corruption.

Posted on 2002-05-20 11:08:32 by Mirno
push offset first
push offset second

call MyProcedure

pop offset first
pop offset second

Don't mind me, I'm still a noob, but offsets aren't immediates, are they?

Also, shouldn't it be

pop offset second then
pop offset first

Still a newbie
Posted on 2002-05-20 12:02:51 by Bighillwill
since you can add to esp, why would you pop with C calling convention?
Another thing to take note of is that "naked" is very dangerous...
you must manually preserve all registers. As far as I can tell, even
eax,ecx,edx ... and yeah, eax even if the func has a return value.
Some of my problems were due to an incremental linker though,
so I'm not 100% sure about the register preservation - I just know
that naked is dangerous ;). And anyway, why would you use a
naked func that does nothing but calling an asm func? Just set up
a proper asm func prototype...
Posted on 2002-05-20 12:12:34 by f0dder
f0dder, take a look here:

Subject: Re: Watcom 11.0 inline asm
From: "Stephen Howe " <SPAMGUARDstephen.howe@teamsybase.com>
Newsgroups: powersoft.public.watcom_c_c++.general

<rockman@albanet.it> wrote in message
> Hello!
> All I need to know is what registers (if any) should
> I preserve when using _asm inside my Watcom C program.
> Can I change any register (besides esp, of course), or
> the compiler expects some or all registers to be the
> same as before the _asm?

The compiler makes worst case assumptions on registers. It will presume EAX,
EBX, ECX, EDX, ESI, EDI are changed and will assume that these registers are
not preserved. Given this you should save EBP if you modify it and also any
segment registers.

#pragma aux is more efficient.

> In this case I will have to
> push the relevant registers before my asm code, and pop
> them after it. Which registers?

Just EBP. All the others you need not worry about as the compiler assumes
the worst that these have changed.

You can see this from

>>> TEST.C
extern int some_variable;

void test(void)
{ _asm "mov some_variable, 0";
>>> TEST.C

Compile with WCC386 /oaxt TEST.C

You will see in TEST.LST:

push ebx
push ecx
push edx
push esi
push edi
mov dword ptr FLAT:_some_variable,00000000H
pop edi
pop esi
pop edx
pop ecx
pop ebx

EAX is not pushed and popped as the compiler assumes that that is changed
anyway, so it makes no effort to preserve. This shows why i prefer #pragma
aux and not _asm

> Also, how do I pass parameters and get return values
> from a _asm piece of code? I know that with #pragma
> you can do it like:

You can MOV values into local or global variables.

Personally I prefer #pragma aux as it is much more efficient.

Stephen Howe (In search of excellence)
London, UK

General reminder (READ THIS, IT IS NOT FOR SHOW):
1. Make sure you specify the version number of the product
2. Make sure you specify the host operating system
3. Make sure you specify the type of target executable

Thank you
Posted on 2002-05-20 16:05:41 by Maverick
Does anybody know if VisualC++ (not that I use it, anyway) is different in this regard?

And, by the way, f0dder: in a old post of yours you said that you ran comparations about compilers, and you attached a file.. it's very interesting, but the file ain't there anymore. Can you repost it please?

Is there a truly "best" C compiler around for x86 (speed-optimization wise)? Which is it?
Posted on 2002-05-20 16:07:56 by Maverick
visual C docs:

Naked functions are provided as an advanced feature. They enable you to declare a function that is being called from a context other than C/C++, and thus make different assumptions about where parameters are, or which registers are preserved.

So I guess you have to preserve everything...

Posted on 2002-05-20 16:39:25 by Thomas
Yes, my post was a bit off-topic, and was about the inline asm stuff. For the specific case of (naked) functions, I agree that any compiler is the same in this regard, i.e. you've to preserve the registers you modify.
Posted on 2002-05-20 18:04:43 by Maverick

thanks everyone, it worked with 2 pop edx, i just wonder where Mirno got them from..why not pop eax...oh well asm gods..
Posted on 2002-05-20 21:56:42 by The Keeper
maverick, I know about calling conventions. I believe VC++ handles
inline asm blocks the way it handles calls, eax+ecx+edx=trashable,
rest must be preserved (I'd like some watcom/gcc-like "let's tell the
compiler what this asm block trashes" functionality, but oh well...)

It sorta makes sense that "naked" doesn't make any assumptions
and that you must preserve all registers... *however*, if you have
to preserve EAX even in routines that return a value... wtf are you
going to do? ;) I *could* be wrong about this of course, as I had
some trouble with incremental linking and some updated files not
being included in the build, and I don't really feel like doing testing
right now.

Keeper, "add esp, 8" instead of 2xPOP edx. The edx popping is
Posted on 2002-05-21 02:13:36 by f0dder
Yes, "to preserve EAX even in routines that return a value" would be black magic.. nothing else.

Thus no need for it, at all.. as for 2 POP's instead of a simple ADD to ESP.

But I am saying nothing interesting. :)
Posted on 2002-05-21 03:57:33 by Maverick

Yes, "to preserve EAX even in routines that return a value" would be black magic.. nothing else.

If the compiler brain****3dley assumes EAX is untrashed across
naked functions...

As for the pop stuff, two pops is one byte shorter, but really...
Posted on 2002-05-21 09:01:52 by f0dder
The reason to I carried on with pop was that it was the advice posted earlier, and is "easy" to understand, while the add esp, N option is a little more mystical (plus I can never remember whether I'm supposed to add or subtract :grin: ).

The reason I chose edx was that it is a register I thought I could trash, it could well have been ecx, but not eax as that could have a result in it from MyProcedure... Looking back with the function returning a void, it could well have been eax, but what the hey.

Posted on 2002-05-21 09:22:50 by Mirno