3
votes

I was trying to check the compiled assembler of some code in VS 2012. I added two lines (before and after my code) as such:

__asm ; it begins here!
// My code
__asm ; it ends here!

However, VS didn't like that. I got

error C2400: inline assembler syntax error in 'opcode'; found 'bad token'

So I added a NOP, which I didn't want to:

__asm NOP ; Comment!

That worked fine. My question is twofold.

  1. Why didn't VS allow me to add an assembly comment?
  2. Is there a different way to add an assembly comment without adding an instruction, including NOP?
2
__asm { / // Comment / } also didn't work? Does this always happen when you place comments on a line of their own, or only if there are no instructions at all in the __asm block?Michael
Your suggestion doesn't work (I think the comment and } is parsed as a C++ comment). As I wrote in the question, __asm NOP ; Comment! works. The problem is just when there is no instruction.Avi Ginsburg
The slashes between the code-formatted blocks in my comment represents newlines, so it wasn't all meant to go on a single line. But perhaps you got that.Michael
Oh, you wanted those comments to be present in the assembly output from the compiler? Nevermind then.Michael
If you want the comments to appear in the assembly it doesn't matter what format of comment you use, assembly style or C/C++ style. Either way comments don't appear in the generated assembly unless you use the /FAs option and in that case the entire source line shows up as a comment in the assembly line.Ross Ridge

2 Answers

4
votes

The reason it doesn't work is that __asm is a keyword, just like int is a keyword, it cannot appear by itself and must follow the proper syntax. Take the following bit of code as an example:

int main()
{
    int      // here's a comment, but it's ignored by the compiler
    return 0;
}

The following code will fail with a compilation error, more specifically in VS2012 you get error C2143: syntax error : missing ';' before 'return'. This is an obvious error since we do not have the ending semi-colon to denote end of instruction; add the semi-colon and it compiles fine because we did not dis-obey the syntax of the C (or C++ in this case) language:

int main()
{
    int      // here's a comment, but it's ignored by the compiler
    ; // white space and comments are ignored by the compiler
    return 0;
}

The same is true of the following code:

int main()
{
    __asm ; here's a comment but it's ignored

    return 0;
}

Except here we get the error error C2400: inline assembler syntax error in 'opcode'; found 'constant', becuase it's treating everything after the __asm keyword as an assembler instruction and the comment is being rightfully ignored .. so the following code WOULD work:

int main()
{
    __asm ; here's a comment but it's ignored
    NOP ; white space and comments are ignored by the compiler

    __asm {; here's an __asm 'block'
    } // outside of __asm block so only C style comments work
    return 0;
}

So that answers your first question: Why didn't VS allow me to add an assembly comment?.. because it is a syntax error.

Now for your second question: Is there a different way to add an assembly comment without adding an instruction, including NOP?

Directly, no, there is not, but indirectly, yes there is. It's worth noting that the __asm keyword gets compiled into inline assembly in your program, so comments will be removed from the compiled assembly just as if it were a standard C/C++ comment, so trying to 'force' a comment in your assembly via that method is not necessary, instead, you can use the /FAs compiler flag and it will generate the assembly (machine code) mixed with the source, example:

Given the following (very simple) code:

int main()
{
    // here's a normal comment
    __asm { ; here's an asm comment and empty block
    } // here's another normal comment
    return 0;
}

When compiled with the /FAs compiler flag, the file.asm that was produced had the following output in it:

; Listing generated by Microsoft (R) Optimizing Compiler Version 18.00.31101.0 

    TITLE   C:\test\file.cpp
    .686P
    .XMM
    include listing.inc
    .model  flat

INCLUDELIB LIBCMT
INCLUDELIB OLDNAMES

PUBLIC  _main
; Function compile flags: /Odtp
; File c:\test\file.cpp
_TEXT   SEGMENT
_main   PROC

; 2    :     {

    push    ebp
    mov ebp, esp

; 3    :         // here's a normal comment
; 4    :         __asm { ; here's an asm comment and empty block
; 5    :         } // here's another normal comment
; 6    :         return 0;

    xor eax, eax

; 7    :     }

    pop ebp
    ret 0
_main   ENDP
_TEXT   ENDS
END

Notice how it includes the source and comments. If this code did more, you would see more assembly and the source associated with that as well.

If you're wanting to put comments in the inline assembly itself, then you can use normal C/C++ style comments as well as assembly comments within the __asm block itself:

int main()
{
    // here's a C comment
    __asm { ; here's an asm comment
        // some other comments
        NOP ; asm type comment
        NOP // C style comment
    } // here's another comment
    return 0;
}

Hope that can help.

EDIT:

It should be noted the following bit of code also compiles without error and I'm not 100% sure why:

int main()
{
    __asm
    __asm ; comment
    // also just doing it on a single line works too: __asm __asm
    return 0;
}

Compiling this code with the single __asm ; comment gives the compilation error, but with both it compiles fine; adding instructions to the above code and inspecting the .asm output shows that the second __asm is ignored for any other assembly commands preceding it. So I'm not 100% sure if this is a parsing bug or part of the __asm keyword syntax as there's no documentation on this behavior.

0
votes

On Linux, g++ accepts this:

__asm(";myComment");

and outputs, when you run g++ -S -O3 filename.cpp:

# 5 "filename.cpp" 1
    ;myComment

However, clang++ does not like it, and complains with this, when you run clang++ -S -O3 filename.cpp:

filename.cpp:5:9: error: invalid instruction mnemonic 'myComment'
  __asm(";myComment");
        ^
<inline asm>:1:3: note: instantiated into assembly here
        ;myComment
         ^~~~~~~~~

I was, however, able to get both g++ and clang++ to accept:

__asm("//myComment");

which outputs the same comment as in the assembly output above, for both compilers.


What clued me into this, as I was unable to find it anywhere else on the internet, was reading from here:

Microsoft Specific

Instructions in an __asm block can use assembly-language comments:

C++

__asm mov ax, offset buff ; Load address of buff

Because C macros expand into a single logical line, avoid using assembly-language comments in macros. (See Defining __asm Blocks as C Macros.) An __asm block can also contain C-style comments; for more information, see Using C or C++ in __asm Blocks.

END Microsoft Specific

This page then links to here and here. These provide more information on the matter.