gcc 内联汇编的奇怪行为?
Strange behavior with gcc inline assembly?
我是 gcc 内联汇编的新手。
为什么此代码输出“1”而不是“5”?
代码:
#include <stdio.h>
static inline int atomic_add(volatile int *mem, int add)
{
asm volatile(
"lock xadd %0, (%1);"
: "=a"(add)
: "r"(mem), "a"(add)
: "memory"
);
return add;
}
int main(void)
{
int a=1;
int b=5;
printf ( "%d\n", atomic_add(&a, b) );
return 0;
}
运行:
$ ./a.out
1 # why not 5?
非常感谢。 :)
变量 add
以值 5 开始,*mem
以 1
开始。
lock xadd %0, (%1)
程序集模板被 gcc 编译为:
lock xadd %eax, (%edx)
GCC 必须使用 eax
,因为您的约束表明 %0
应该使用 %eax
。您的约束还将 %eax
与变量 add
联系起来。我相信 GCC 可以免费为我们提供任何它想要的其他操作数的寄存器(在我的测试中它碰巧使用 %edx
)。
所以:
%eax
以 5
开头,并且 %edx
指向具有值 1
的内存位置
xadd
指令交换两个操作数并将和放在目标中,因此执行 %eax
后有 1
和 the memory pointed to by
% edxcontains
6`
您的约束还表明 %eax
应该存储回变量 add
,因此 add
得到 1
。这就是函数返回的内容。
在x86中,XADD是Exchange and Add指令。所以保存add
参数的寄存器在lock xadd
指令后变成了1
。 add
然后由 atomic_add()
返回,因此您看到打印的是 1
而不是 5
.
对于 atomic_add()
你可能只想使用 lock add
而不是 lock xadd
:
#include <stdio.h>
static inline int atomic_add(volatile int *mem, int add)
{
asm volatile(
"lock add %0, (%1);"
: "=a"(add)
: "r"(mem), "a"(add)
: "memory"
);
return add;
}
int main(void)
{
int a=1;
int b=5;
printf ( "%d\n", atomic_add(&a, b) );
return 0;
}
这会像您期望的那样打印 5
:
$ ./a.out
5
我是 gcc 内联汇编的新手。 为什么此代码输出“1”而不是“5”?
代码:
#include <stdio.h>
static inline int atomic_add(volatile int *mem, int add)
{
asm volatile(
"lock xadd %0, (%1);"
: "=a"(add)
: "r"(mem), "a"(add)
: "memory"
);
return add;
}
int main(void)
{
int a=1;
int b=5;
printf ( "%d\n", atomic_add(&a, b) );
return 0;
}
运行:
$ ./a.out
1 # why not 5?
非常感谢。 :)
变量 add
以值 5 开始,*mem
以 1
开始。
lock xadd %0, (%1)
程序集模板被 gcc 编译为:
lock xadd %eax, (%edx)
GCC 必须使用 eax
,因为您的约束表明 %0
应该使用 %eax
。您的约束还将 %eax
与变量 add
联系起来。我相信 GCC 可以免费为我们提供任何它想要的其他操作数的寄存器(在我的测试中它碰巧使用 %edx
)。
所以:
%eax
以5
开头,并且%edx
指向具有值1
的内存位置
xadd
指令交换两个操作数并将和放在目标中,因此执行%eax
后有1
和the memory pointed to by
% edxcontains
6`您的约束还表明
%eax
应该存储回变量add
,因此add
得到1
。这就是函数返回的内容。
在x86中,XADD是Exchange and Add指令。所以保存add
参数的寄存器在lock xadd
指令后变成了1
。 add
然后由 atomic_add()
返回,因此您看到打印的是 1
而不是 5
.
对于 atomic_add()
你可能只想使用 lock add
而不是 lock xadd
:
#include <stdio.h>
static inline int atomic_add(volatile int *mem, int add)
{
asm volatile(
"lock add %0, (%1);"
: "=a"(add)
: "r"(mem), "a"(add)
: "memory"
);
return add;
}
int main(void)
{
int a=1;
int b=5;
printf ( "%d\n", atomic_add(&a, b) );
return 0;
}
这会像您期望的那样打印 5
:
$ ./a.out
5