Adding values in C using inline assembly

拟墨画扇 提交于 2020-03-14 18:29:22

问题


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?


回答1:


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));


来源:https://stackoverflow.com/questions/28136075/adding-values-in-c-using-inline-assembly

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!