To write asm that will assemble in either mode, use 32-bit operand size, and avoid push
/pop
: they're not available in 32-bit operand size for x86-64. Only the full-width register size for the mode, and 16-bit, are available for push/pop. (i.e. the 0x66
operand-size prefix works, but REX.W=0
doesn't in machine code, so push eax
is not encodeable in 64-bit mode.)
Also avoid inc
/dec
if you want the same machine code to work in both modes (short encoding in 32-bit mode becomes a REX prefix in 64-bit mode). inc/dec are fine if you only need asm source that assembles.
For inline asm in C++:
Avoid modifying any memory or making any function calls. It's hard to do this safely, so if you just want junk code you can just play with registers. You can't even safely push
in x86-64 code for the System V ABI, because the compiler might be using the red-zone below the stack, and there's no way to tell it you want to clobber it. I don't know if this applies to Clang with MSVC inline-asm syntax instead of GNU syntax where clobbers have to be explicitly declared.
Prefer GNU C inline asm syntax (with proper constraints to tell the compiler what registers you clobber).
MSVC itself doesn't support any inline asm syntax in 64-bit mode.
Xcode (clang) does support MSVC's syntax as well as GNU syntax, and it might support MSVC syntax even in 64-bit mode.
MSVC-style inline asm syntax basically sucks for wrapping short snippets (inputs have to bounce through memory because there is no syntax to ask for inputs in registers), and reportedly has been unreliable from version to version in MS's compiler. MS were probably looking for a reason or a way to drop it, and not supporting it for x86-64 makes sense. It would suck even more for accessing function args from inline asm if they left it unchanged, because they don't start in memory. Anyway, MSVC inline asm syntax is half dead, good riddance.
Anyway, if you really want to have some inline asm in 32-bit MSVC, then sure use that syntax. __asm __emit
might do something in 64-bit MSVC, I think IACA headers use that, so you could maybe encode some NOPs manually if you just want your code to look weird.