3
votes

We know, if I set %eax as the input, then I cannot include it into list of clobbered registers. So my question is that, is that legal to modify the value of %eax in the assembly code without any declaration in clobbered list?

__asm__ __volatile__("inc %0" :: "a"(num) : "%eax"); // illegal
__asm__ __volatile__("inc %0" :: "a"(num));       // Can I modify %eax?
1
Your code will compile + assemble, but then potentially break in weird ways at runtime, or sometimes not break, depending on the surrounding code and optimization options. This means that unit-testing is not sufficient to prove inline-asm correct or safe.Peter Cordes

1 Answers

4
votes

No, if the assembly code changes an input register, it must also be listed as an output register, or as an in-out register, by using "+" instead of "=" in the constraint.

Examples:

__asm__ __volatile__("..." : "+r"(num));
__asm__ __volatile__("..." : "=a"(dummy) : "a"(num));
__asm__ __volatile__("..." : "=r"(dummy) : "0"(num));

The first example specifies num as both an input and an output. This will overwrite the prior value of num, which may be undesirable if the operand is clobbered rather being set to a useful value.

The second example explicitly uses eax for both input and output. It directs the output to a dummy variable so as to not corrupt the actual input variable num.

The third example uses a dummy output, to avoid modifying num, and also avoids specifying eax explicitly, allowing the compiler to choose which register to use. The "0" constraint tells the compiler to use the same register as operand 0 for this input operand.