Im trying to get a grasp on the basics of inline assembly in C (ATT assembly), so Im practicing by adding 2 variables.
Ok so this works as intended; the src variable gets copied to the dst variable and then the dst variable gets added by 5. The values of src and dst are 1 and 6 respectively.
int src = 1;
int dst = 0;
asm ("mov %[SRC], %[DEST]\n\t"
"add $5, %0"
: [DEST] "=r" (dst));
: [SRC] "r" (src));
But when I try this out, the values of src and dst are still 1 and 6. I was expecting src to have the value 1 and dst to have the value 5 since adding 5 to dst (which has the value of 0 since the MOV operation has been removed) should have the output 5.
int src = 1;
int dst = 0;
asm ("add $5, %[DEST]"
: [DEST] "=r" (dst)
: [SRC] "r" (src));
So I then try removing the src as an input operand using the following code, but now dst gets the value 11.
int dst = 0;
asm (
"add $5, %[DEST]"
: [DEST] "=r" (dst));
Now I'm a bit confused how it works. What am I misunderstanding?
The first part of your code works as expected. There
mov %[SRC], %[DEST] ; copies %[SRC] into %[DEST], which is now 1
add $5, %0 ; adds 5 to %0 (which is %[DEST]), so that's 6
The second part does not work because you never use %[SRC]
, and because %[DEST]
is not an input operand, so its value doesn't come into the calculation. You just get what happens to be in the register gcc decides to use. The third part fails for the same reason.
For it to work, you need to specify dst
as both an input and output operand, since you're both using its value and changing it. However, this does not work:
asm("add $5, %0" // This does not work!
: "=r" (dst)
: "r" (dst));
because now you have an input operand %1
with value dst
and a distinct output operand %0
whose value will be written to dst
, and you never use %1
. This notation would allow you to write
asm("mov %1, %0; add $5, %0" // needlessly inefficient!
: "=r" (dst)
: "r" (dst));
but that is, of course, needlessly inefficient. In order to do this with a single register, you need to use a matching constraint like this:
asm("add $5, %0"
: "=r" (dst)
: "0" (dst));
This tells gcc that %0
as an input operand is allowed, and that it has the value of dst
. Here is the relevant part of the gcc manual.
With named operands, finally, it looks like this:
asm ("add $5, %[DEST]"
: [DEST] "=r" (dst)
: "[DEST]" (dst));