Link to home
Start Free TrialLog in
Avatar of Aidman
Aidman

asked on

Inline Assembler Macros?

Hi, all :)

I am trying to write a high performance library by using inline assembler, but I have encountered a irritating problem. It seems that VC++ refuses to accept multi-instructions within the inline asm section for the macro. For example, I can write a inline assembler macro with the single instruction “mov eax, 0” but that’s it, VC++ refuses to accept anymore instructions. The following code might give a better understanding:

#define TestMacro1(x) _asm{ mov eax, 0 } // This works
#define TestMacro2(x) _asm{ mov eax, 0; mov ebx, 0 } // This doesn’t


So what I am trying to do here is to add more then one instruction into the macro, but I don’t know how. Any ideas on how to solve this are highly appreciated.

Thanks in advance.
Aidman » over and out
Avatar of Exceter
Exceter
Flag of United States of America image

Try this,

#define TestMacro2(x) _asm mov eax, 0; _asm mov ebx, 0;

Cheers!
Exceter
Avatar of ShawnCurry
ShawnCurry

Yeah the macro expands to a single line.
Avatar of Aidman

ASKER

I added a breakpoint in "TestMacro2(0);" line and run the following code in debug mode (shortcut: F5) using VC++:

#define TestMacro2(x) _asm mov eax, 0; _asm mov ebx, 0;

int main() {
      TestMacro2(0);
      return 0;
}

When the program reached the breakpoint at "TestMacro2(0);" I switched to disassembly mode (shortcut: Alt+8) and got the following data:
4:        TestMacro2(0);
00401028   mov         eax,0
5:        return 0;
0040102D   xor         eax,eax
6:    }

According to this only the first instruction of the macro was added. :(
ASKER CERTIFIED SOLUTION
Avatar of Salte
Salte

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Aidman

ASKER

I get the following error and warning:

warning C4405: 'mov' : identifier is reserved word
error C2400: inline assembler syntax error in 'second operand'; found 'register'
odd error messages you got there, could you be a little specific and give us the exact code that produced those error messages?

If it is my code and #define then I am not sure exactly why it should give error when you compile the define. It might cause errors when you expand it depending on the context etc but a #define is supposed to just read text as such and you can write whatever you want in it without any errors.

Also, the compiiler is absolutely right that 'mov' is a reserved word, that's the whole idea....

Similarly with the assembler syntax, the second operand is probably a register, that is also usually not an error unless the instruction in question do not permit a register as the second operand for that instruction.

Again, it would be nice if you could show us the CODE that is related to those errors and warnings.

Specifically also with a comment or other way to identify which line refer to which error. You probably get some line numbers associated with the error messages, but when you dump the code here such a relationship is lost so for example dumping the code like this:

  __asm {
     mov    blah blah blah    // line 27
     .....
    .....
   }

line 27: C4405: 'mov' .....blah blah blah.

is a good way to show us error messages and warnings.

Alf
Avatar of Aidman

ASKER

The code I used:

#define TestMacro2(x) \
  do { \
     __asm { \
          mov eax,0 \
          mov ebx,x \
     } \
  } while (0)

int main() {
      int x = 1;
      TestMacro2(x);
      return 0;
}

The following error and warning are at the line "TestMacro2(x);":

warning C4405: 'mov' : identifier is reserved word
error C2400: inline assembler syntax error in 'second operand'; found 'register'
Avatar of Aidman

ASKER

but I seem to have solved the problem, by simple defining like this:

#define TestMacro2(x) \
      _asm mov eax,0 \
      _asm mov ebx,x

But I will give the points to Salte, becouse he explained his code.
Anyway, Thanks for your replys :)
It's odd that it didn't accept the block assembly.... Is it because I wrote __asm instead of _asm?

Try to replace the __asm with _asm. It is possible it doesn't accept double underscore there. On the other hand, the fact that the error writes "inline assembler syntax error" indicates to me that it is indeed the inline assembler which is active so I tend to rather think it is a bug in the compiler.

If you found the work around you can also use:

#define TestMacro2(x) \
    do {
        _asm mov eax,0 \
        _asm mov ebx,x \
   } while(0)

Be careful though, if the compiler do do emit any code for the while(0) you might not want that to happen. Either way, it is worth a try.

Also, if in doubt it is a good idea to give the option so that you get the compiler to generate assembly listing of a small function call like the above where you call the macro in a small function so you can see if the generate code makes sense or not.

Alf
Microsoft reccommends the double underscore.  They say the results with the standard _asm are "unpredictable".  But that's not the reason it didn't work.  The compiler for whatever reason can't accept more than one assembly statement per line without another __asm.  Im pretty sure I read that in the VC help files.   Also, an __asm line doesn't require a semicolon.  That's what I was trying to say about the macro expanding to a single line.  If it doesn't complile on one line, you cant write it as a macro.  For instance, this doesn't work:

int main()
{
      int x = 1;
      do {  __asm{ mov eax,0  mov ebx,x }  }while(0);
      return 0;
}

But this does:
int main()
{
      int x = 1;
      do {  __asm mov eax,0  __asm mov ebx,x   }while(0);
      return 0;
}

So:

#define TestMacro \
      do { \
            __asm mov eax,0 \
            __asm mov ebx,x \
      }while(0);

int main() {

    int x = 1;        
    TestMacro(x);
    return 0;
}
Only one asm statement per __asm UNLESS it is an asm block:

__asm {
   ......many assembly statements here...
}

so if they don't accept the __asm { \   etc (note the open brace) it means that the preprocessor remove the brace or some such (it shouldn't do), otherwise I can't find any good explanation why, you can write:

#define foo(x) \
   do { \
      __asm mov eax,0 \
      __asm mov ebx,x \
   } while (0)

but not

#define bar(x) \
    do { \
       __asm { \
             mov eax,0 \
             mov ebx,x \
      } \
   } while(0)

Note that the second simply uses the __asm block as opposed to the asm statement. I really can't see any good reason why that shouldn't be OK syntax.

Also, note that it is part of the clue to NOT terminate the while(0) with a semicolon in the definition.

The reason is that you place the semicolon when you "call" the macro:

int main()
{
    int x = 1;
    foo(x);
    return 0;
}

You can't use a semicolon in the assembler statement because it's threated the beginning of a comment, like a // for the preprocessor

My problem is that I want to use labels inside the macro. This is not possible because I can't have labels in one line

This is ok:
__asm jz mylabel
__asm mov eax,10  
mylabel:
__asm mov ebx,20

This is not ok:
__asm jz mylabel   __asm mov eax,10   mylabel:   __asm mov ebx,20

This is  ok:
__asm jz mylabel   __asm mov eax,10    __asm mov ebx,20

But I need my label...
On VS 2005 the solution is a double asm block

#define TEST(anyuniquetextl)   __asm \
{ \
  __asm { mov eax,10 } \
  __asm { mov ebx,20 } \
  __asm { jmp mylabel ## anyuniquetext } \
  ...
mylabel ## anyuniquetext: \
  __asm { mov ecx,30 } \
}

The anyuniquetest is necessary for using the TEST block multiple times inside the same C++ function.

http://msdn.microsoft.com/en-us/library/352sth8z(VS.80).aspx
You do realize that this is a 5 year old question, right?
Sure, I was seeking a solution now (use of labels)... and in the future someone else may have the same problem. So I posted it for everyone. :)