Inserting a comment in __asm results in C2400 erro

2019-08-06 14:47发布

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?

1条回答
戒情不戒烟
2楼-- · 2019-08-06 14:57

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.

查看更多
登录 后发表回答