The MASM Forum Archive 2004 to 2012

General Forums => The Campus => Topic started by: starsiege on December 10, 2008, 07:47:13 PM

Title: a question on inline assembly code
Post by: starsiege on December 10, 2008, 07:47:13 PM
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 :)
Title: Re: a question on inline assembly code
Post by: Vortex on December 10, 2008, 08:35:45 PM
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.
Title: Re: a question on inline assembly code
Post by: Tedd on December 10, 2008, 09:41:21 PM
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.)
Title: Re: a question on inline assembly code
Post by: Rockoon on December 11, 2008, 01:39:45 AM
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.

Title: Re: a question on inline assembly code
Post by: zooba on December 11, 2008, 02:09:57 AM
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
Title: Re: a question on inline assembly code
Post by: KeepingRealBusy on December 11, 2008, 02:17:42 AM
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.
Title: Re: a question on inline assembly code
Post by: Rockoon on December 11, 2008, 02:42:26 AM
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)
Title: Re: a question on inline assembly code
Post by: zooba on December 11, 2008, 12:40:11 PM
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 (http://msdn.microsoft.com/en-us/library/5hd5ywk0.aspx), 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
Title: Re: a question on inline assembly code
Post by: starsiege on December 11, 2008, 06:55:26 PM
thanks guys (and girls too!). and also thanks for the detailed explanations!
Title: Re: a question on inline assembly code
Post by: Vortex on December 11, 2008, 07:10:10 PM
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.