Consider the following code:
#include <stdio.h>
void main() {
uint32_t num = 2;
__asm__ __volatile__ ("CPUID");
__asm__ __volatile__ ("movl $1, %%ecx":);
__asm__ __volatile__ ("andl $0, %%ecx": "=r"(num));
printf("%i\n", num);
}
My initial expectation was that this code would print 0, and it does if I comment out the CPUID line, but as-is it was giving me garbage. After some trial, error, and research I realized that I was getting the value of a random register. Apparently GCC doesn’t assume that I want the result of the statement being executed.
The problem is that I’ve seen (other people’s) code that relies on that statement properly getting the result of the AND, regardless of what is going on with the other registers. Obviously such code is broken, given my observations, and the "=r" should be replaced with "=c".
My question is, can we ever rely on the "=r" constraint behaving consistently or according to the obvious expectation? Or is GCC’s implementation too opaque/weird/other and it’s best just to avoid it in every situation?
In order to use the
=routput specifier you need to give gcc the freedom to pick the register that it wants to use. You do that by specifying the inputs and outputs generically with%0for the output and the inputs starting with%1for the first input.In your case you are saying that
numcan be in a register. But there is nothing in the asm instruction that uses the output register. So gcc will essentially ignore this.The reason that you are getting a different value if you comment or don’t comment the
CPUIDinstruction is thatCPUIDcan write toeax,ebx,ecx, andedx. I tried your example on my system and got0as the result in both cases. But I noticed that the assembly that is generated is printing the value ofeax. So I guess when I ran this programCPUIDwas writing0toeax.If you did want to use the
=rconstraint you would need to do something like this:Otherwise if your asm code specifically mentions a register then you will need to specify it in the constraint list. In your example that means using
=c.