I don’t understand how this is supposed to work.
GCC inline assembler is a pain to get right, but very specific about marking clobbering information, so that the compiler knows what you’re doing.
Microsoft Visual C++’s inline assember is really easy to use (it always seems to Just Work), but I have no ideas what kinds of guarantees or assumptions it makes about your code.
Does VC++ try to “auto-detect” what registers are clobbered? How does it know how the registers and the stack pointer will be changed? Does it make any assumptions? If so, how do you get around those assumptions?
As for why GCC doesn’t do it the way MSVC does, there are several reasons:
GCC is a retargettable compiler, but the assembly syntax is just raw text. In order for the clobber detection to be automatic, GCC would have to parse the assembly language to understand what registers are being clobbered (including implicitly clobbered ones by instructions whose opcodes do not name a register). This would have to work across all architectures. Currently, GCC does not parse the assembly language; it just pastes it into the assembly output, after performing the
%substitutions. The idea is to generate, and avoid parsing.In GCC inline assembly language, clobbering registers is the exception rather than the rule. The reason is that it is a more sophisticated language than that in MSVC. GCC’s inline assembly language allocates registers for you. So you usually don’t use something like
%eaxdirectly, but rather a code like%0for which GCC substitutes an available register. (And to do that, the compiler doesn’t have to understand the assembly language! you express the constraints which ensure that GCC substitutes an appropriate register for%0which fits the usage.) You only need clobber if your assembly code is overwriting hard-coded registers, not if it is overwriting the output operands allocated for you by GCC.Note that with GCC inline assembly, you don’t have to write the code which loads your assembly language operands from the C expressions that produce their initial values, or which stores your result operands into the C destinations. For instance you just express that there is to be an input operand of type
"r"(register) which is derived from the expressionfoo->bar + 1. GCC allocates the register and generates the code to load it fromfoo->bar + 1, and then replaces occurences of%0in your assembly template with the name of that register.