gpt4 book ai didi

gcc - 在GCC内联汇编中包装CMPXCHG8B的正确方法(32位)

转载 作者:行者123 更新时间:2023-12-04 13:34:09 32 4
gpt4 key购买 nike

我正在尝试为ia32的CMPXCHG8B编写GCC内联asm。不,我不能使用__sync_bool_compare_and_swap。它必须与-fPIC和不与-fPIC一起使用。

到目前为止,我所能做到的最好( EDIT :毕竟行不通,有关详细信息,请参见下面的我自己的答案)

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

但是我不确定这是否正确。

由于PIC,我无法为ebx_val做 "b" ((int32)(set & 0xFFFFFFFF)),但显然 register asm("ebx")变量已被编译器接受。

奖励:ret变量用于分支,因此代码最终看起来像这样:
cmpxchg8b [edi];
setz cl;
cmp cl, 0;
je foo;

关于如何描述输出操作数的任何想法,使其变为:
cmpxchg8b [edi]
jz foo



谢谢你。

最佳答案

以下内容怎么样?在一个小测试中,以下内容似乎对我有用:

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

如果这也被错误编译,您能否提供一个触发此行为的小片段?

关于红利问题,我认为不可能使用 cmpxchg8b指令中的条件代码在汇编程序块之后分支(除非您使用 asm goto或类似功能)。从 GNU C Language Extensions:

It is a natural idea to look for a way to give access to the condition code left by the assembler instruction. However, when we attempted to implement this, we found no way to make it work reliably. The problem is that output operands might need reloading, which would result in additional following "store" instructions. On most machines, these instructions would alter the condition code before there was time to test it. This problem doesn't arise for ordinary "test" and "compare" instructions because they don't have any output operands.



编辑:我找不到任何指定一种方式或其他方式的源,既可以修改堆栈,又可以使用 %N输入值( This古老的链接说:“您甚至可以将寄存器插入堆栈,使用它们,并放回原处。”,但该示例没有输入)。

但是应该可以不通过将值固定到其他寄存器来做到这一点:
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;
}

关于gcc - 在GCC内联汇编中包装CMPXCHG8B的正确方法(32位),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6756985/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com