A common error occurring when compiling a 64-bit application: error C4235, Assembler

30.10.2010

Visual C++ does not support 64-bit inline assembler. That is why you get an error when trying to compile a code like this:

void waitvrt(void)
{
  __asm {
      mov  dx,3dah
  VRT:
      in    al,dx
      test  al,8
      jnz    VRT
  NoVRT:
      in    al,dx
      test  al,8
      jz    NoVRT
  }
}
1>.\Third_party\Src\CreditsThread.cpp(111) :
error C4235: nonstandard extension used :
'__asm' keyword not supported on this architecture

If you still need to use assembler code, you may use a third-party 64-bit assembler, for example, MASM.

But you will most likely need to rewrite the existing code in C/C++. The assembler code is likely to be obsolete and it is more reasonable to use modern functions provided by operating systems or C/C++ constructs. Using assembler for the purpose of optimization can rarely be justified because Visual C++ compiler creates rather efficient code in most cases. Also, remember that you may use intrinsic-functions.

Intrinsic-functions are special system-dependent functions performing such actions that cannot be performed at the level of C/C++ code or that do it much more efficiently than other means. On the whole, they allow you to get rid of inline-assembler because it is often undesirable or impossible to use it.

Programs can use intrinsic-functions to create faster code because there are no expenses on calling common functions. Of course, the size of the code will be a bit larger. MSDN gives the list of the functions that can be replaced with their intrinsic-versions. For example, these are memcpy, strcmp, etc.

Microsoft Visual C++ compiler has a special option "/Oi" that allows you to replace the calls of some functions with their intrinsic-versions automatically.

Besides automatic replacement of common functions with intrinsic-versions, you may use intrinsic-functions in the code explicitly. This is why it may be useful:

  • As I have already said, inline assembler is not supported by Visual C++ in the 64-bit mode. But intrinsic-code is.
  • Intrinsic-functions are simpler to use because you do not need to know registers or other similar low-level constructs when dealing with them.
  • Intrinsic-functions are updated in compilers. But assembler code must be updated manually.
  • The embedded optimizer does not work with assembler code, so you need external linking of the module. But this all does not concern intrinsic-code.
  • Intrinsic-code is easier to port than assembler code.

Using intrinsic-functions in automated mode (with the help of the compiler switch) allows you to get some per cent of performance gain at no cost, and "manual" introduction of intrinsic-functions allows you to get even more. That is why using them is absolutely justified.

To learn more about intrinsic-functions see the Visual C++ team blog.