News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

a question on inline assembly code

Started by starsiege, December 10, 2008, 07:47:13 PM

Previous topic - Next topic

starsiege

Hi guys
              i have a question about inline assembly code


at the beginning of an asm block, may general purpose registers such as EAX and EBX have unknown values?

thanks in advance :)

Vortex

Compiling the code below with Pelles C :

#include <stdio.h>

int main(int argc,char *argv[])
{
char *format="eax = %X , ebx = %X , ecx = %X , edx = %X\n";
int t=(int)format;

__asm{
push edx
push ecx
push ebx
push eax
push t
call printf
add esp,5*4
}

return 0;
}


The result is :

eax = 407000 , ebx = 7FFDA000 , ecx = 7C90003D , edx = 140608

I guess there is no easy way to guess the initial values of those registers.

Compiling and running the same code with VC++ 2005 Express Edition :

eax = 383168 , ebx = 7C80AC51 , ecx = 1 , edx = 40D4B8

The compiler's C run-time startup code uses some registers internally.

Tedd

Quote from: starsiege on December 10, 2008, 07:47:13 PM
at the beginning of an asm block, may general purpose registers such as EAX and EBX have unknown values?
They will be unknown to you, yes (since you have no idea what the compiler was doing with them before.)
No snowflake in an avalanche feels responsible.

Rockoon

Quote from: Tedd on December 10, 2008, 09:41:21 PM
They will be unknown to you, yes (since you have no idea what the compiler was doing with them before.)

And further, even if you take the time to figure out what they are in a specific case, even a seemingly insignificant change to the source somewhere could change how the compiler manages the registers prior to the asm block.

It should, however, be noted that most C compilers have a 'fastcall' calling convention which can be enabled for a specific function. In such a case, the function will be called with its parameters given in registers.. each compiler has its own 'fastcall' convention so your asm block would be compiler-specific.

..and finally, all bets are off if you use any sort of global 'whole program' type optimization feature of a compiler. In general compilers will follow no standard calling convention for non-external calls using these features. Each internal function will be treated on a case-by-case basis to a calling convention specifically tailored to the needs of both the caller and the callee.

When C++ compilers can be coerced to emit rcl and rcr, I *might* consider using one.

zooba

Quote from: Rockoon on December 11, 2008, 01:39:45 AM
all bets are off if you use any sort of global 'whole program' type optimization feature of a compiler.

You may get away with this - some compilers won't even attempt optimisation of a function if it contains inline assembly code (I know all the Microsoft ones do this), simply because now the compiler can't be sure what the values of the registers are. My personal preference is to compile assembly routines into their own functions and call them from C/C++.

Cheers,

Zooba :U

KeepingRealBusy

Tedd,

You can always start with a PUSH of any regs you use (or a PUSHAD - not allowable for 64 bit), followed by a pop of the regs (in inverse order of pushes) or a POPAD after your functional ASM coding.

Dave.

Rockoon

Quote from: zooba on December 11, 2008, 02:09:57 AM
You may get away with this - some compilers won't even attempt optimisation of a function if it contains inline assembly code

I know of no compiler that behaves like this. It is certainly true that some compilers do no optimizing *through* inline asm, but they still do what they can on the code before, as well as the code after.

I think GCC is understood to be the best at optimizing around inline asm because it actualy examines it, enabling it to optimize *through* the inline block. May require that the inline be in at&t syntax even though gcc now supports intel syntax.

I also think that many compilers refuse to inline any functions with inline asm, even with __forceinline. That is certainly a significant optimization technique that you dont necessarily want to give up just to try to save a few cycles on something trivial (like a vector addition function)
When C++ compilers can be coerced to emit rcl and rcr, I *might* consider using one.

zooba

Quote from: Rockoon on December 11, 2008, 02:42:26 AM
I know of no compiler that behaves like this. It is certainly true that some compilers do no optimizing *through* inline asm, but they still do what they can on the code before, as well as the code after.

You're right, I based that statement on (poor) memory of this MSDN page, which effectively says exactly what you said. (Apparently it even determines which registers don't change through the __asm block and will use those.)

Even so, losing inlining is bad enough. :bg I still prefer to keep ASM separate from C++ code and generally find that it's no harder to do.

Cheers,

Zooba :U

starsiege

thanks guys (and girls too!). and also thanks for the detailed explanations!

Vortex

starsiege,

It's preferable to follow zooba's advice, moving assembly routines to individual asm files as this will not break the compiler's optimization mechanism.