Lau*_*nis 9 x86 assembly gcc inline-assembly
我正在尝试为ia32编写GCC内联asm for CMPXCHG8B.不,我不能用__sync_bool_compare_and_swap.它必须使用和不使用-fPIC.
到目前为止,我所做的最好(编辑:毕竟不起作用,详见下面我自己的答案)
register int32 ebx_val asm("ebx")= set & 0xFFFFFFFF;
asm ("lock; cmpxchg8b %0;"
"setz %1;"
: "+m" (*a), "=q" (ret), "+A" (*cmp)
: "r" (ebx_val), "c" ((int32)(set >> 32))
: "flags")
Run Code Online (Sandbox Code Playgroud)
但是我不确定这实际上是否正确.
"b" ((int32)(set & 0xFFFFFFFF))由于PIC,我不能为ebx_val 做,但register asm("ebx")编译器接受了显然变量.
BONUS:ret变量用于分支,因此代码最终看起来像这样:
cmpxchg8b [edi];
setz cl;
cmp cl, 0;
je foo;
Run Code Online (Sandbox Code Playgroud)
任何想法如何描述输出操作数,使它成为:
cmpxchg8b [edi]
jz foo
Run Code Online (Sandbox Code Playgroud)
?
谢谢.
下面的怎么样,这在一个小测试中似乎对我有用:
int sbcas(uint64_t* ptr, uint64_t oldval, uint64_t newval)
{
int changed = 0;
__asm__ (
"push %%ebx\n\t" // -fPIC uses ebx, so save it
"mov %5, %%ebx\n\t" // load ebx with needed value
"lock\n\t"
"cmpxchg8b %0\n\t" // perform CAS operation
"setz %%al\n\t" // eax potentially modified anyway
"movzx %%al, %1\n\t" // store result of comparison in 'changed'
"pop %%ebx\n\t" // restore ebx
: "+m" (*ptr), "=r" (changed)
: "d" ((uint32_t)(oldval >> 32)), "a" ((uint32_t)(oldval & 0xffffffff)), "c" ((uint32_t)(newval >> 32)), "r" ((uint32_t)(newval & 0xffffffff))
: "flags", "memory"
);
return changed;
}
Run Code Online (Sandbox Code Playgroud)
如果这也被错误编译,您能否添加一个触发此行为的小片段?
关于奖励问题,我认为不可能使用指令中的条件代码在汇编器块之后进行分支cmpxchg8b(除非您使用asm goto或类似的功能)。来自GNU C 语言扩展:
寻找一种方法来访问汇编指令留下的条件代码是一个自然的想法。然而,当我们尝试实现这一点时,我们发现没有办法让它可靠地工作。问题是输出操作数可能需要重新加载,这将导致额外的后续“存储”指令。在大多数机器上,这些指令会在有时间测试条件代码之前更改它。对于普通的“测试”和“比较”指令,不会出现此问题,因为它们没有任何输出操作数。
编辑:我找不到任何指定一种方式或另一种方式的来源,是否可以在使用输入%N值的同时修改堆栈(这个古老的链接说“您甚至可以将寄存器推入堆栈,使用它们,并且把它们放回去。”但该示例没有输入)。
但应该可以通过将值固定到其他寄存器来做到这一点:
int sbcas(uint64_t* ptr, uint64_t oldval, uint64_t newval)
{
int changed = 0;
__asm__ (
"push %%ebx\n\t" // -fPIC uses ebx
"mov %%edi, %%ebx\n\t" // load ebx with needed value
"lock\n\t"
"cmpxchg8b (%%esi)\n\t"
"setz %%al\n\t" // eax potentially modified anyway
"movzx %%al, %1\n\t"
"pop %%ebx\n\t"
: "+S" (ptr), "=a" (changed)
: "0" (ptr), "d" ((uint32_t)(oldval >> 32)), "a" ((uint32_t)(oldval & 0xffffffff)), "c" ((uint32_t)(newval >> 32)), "D" ((uint32_t)(newval & 0xffffffff))
: "flags", "memory"
);
return changed;
}
Run Code Online (Sandbox Code Playgroud)