我试图掌握C(ATT装配)中内联装配的基础知识,所以我通过添加2个变量来练习。
好的,这样可以按预期工作; 将src变量复制到dst变量,然后将dst变量添加为5.src和dst的值分别为1和6。
int src = 1; int dst = 0; asm ("mov %[SRC], %[DEST]\n\t" "add $5, %0" : [DEST] "=r" (dst)); : [SRC] "r" (src));但是当我尝试这个时, src和dst的值仍然是1和6.我希望src的值为1, dst的值为5,因为将dst加5(自MOV以来值为0)操作已被删除)应该有输出5。
int src = 1; int dst = 0;
asm ("add $5, %[DEST]" : [DEST] "=r" (dst) : [SRC] "r" (src));因此,我尝试使用以下代码将src作为输入操作数删除,但现在dst获取值11。
int dst = 0; asm ( "add $5, %[DEST]" : [DEST] "=r" (dst));现在我有点困惑它是如何工作的。 我有什么误会?
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?
最满意答案
代码的第一部分按预期工作。 那里
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第二部分不起作用,因为你从不使用%[SRC] ,并且因为%[DEST]不是输入操作数,所以它的值不会进入计算。 你只是得到了gcc决定使用的寄存器。 第三部分出于同样的原因失败了。
要使其工作,您需要将dst指定为输入和输出操作数,因为您既使用其值又更改它。 但是,这不起作用:
asm("add $5, %0" // This does not work! : "=r" (dst) : "r" (dst));因为现在你有一个带有值dst的输入操作数%1和一个不同的输出操作数%0其值将被写入dst ,你永远不会使用%1 。 这种表示法可以让你写
asm("mov %1, %0; add $5, %0" // needlessly inefficient! : "=r" (dst) : "r" (dst));但那当然是不必要的低效率。 要使用单个寄存器执行此操作,您需要使用匹配的约束,如下所示:
asm("add $5, %0" : "=r" (dst) : "0" (dst));这告诉gcc允许%0作为输入操作数,并且它具有dst的值。 这是gcc手册的相关部分。
最后,使用命名操作数,它看起来像这样:
asm ("add $5, %[DEST]" : [DEST] "=r" (dst) : "[DEST]" (dst));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 6The 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));更多推荐
发布评论