[英]How can I be sure a general purpose register is not being used by others before entering a inline assembly?
以下是一段GCC内联汇编代码。 它以原子方式将输入*Value
增加一。 并返回增加的值。
在汇编代码中,它使用EAX
寄存器。 在调用此函数之前,我怎么能知道别人没有使用EAX
? 如果正在使用它,则汇编代码将破坏某些内容。
UINT32
__cdecl
AtomicIncrement (
IN volatile UINT32 *Value
)
{
UINT32 Result;
__asm__ __volatile__ (
"movl $1, %%eax \n\t" ; <============== HERE, EAX is being modified.
"lock \n\t"
"xadd %%eax, %2 \n\t"
"inc %%eax "
: "=a" (Result), // %0
"=m" (*Value) // %1
: "m" (*Value) // %2
: "memory",
"cc"
);
return Result;
}
我从这里读到:
...整数值和内存地址在EAX寄存器中返回...(cdecl调用约定)
这是否意味着如果我遵循cdecl
调用约定,则编译器将确保在进入汇编函数时可以安全地使用 EAX
? 如果我使用其他通用寄存器(例如EBX
,则必须将其放入“ Clobber”部分中 ? 即在最后一个冒号之后?
您使用的是"=a"
输出操作数,因此编译器知道您的asm会写入该寄存器。
它将进行相应的计划,在您的asm运行后,使用其他寄存器来存储所需的内容。 由您决定是否要在有约束的情况下向编译器准确描述自己的asm,因为否则它是一个黑匣子。
函数调用约定与内联汇编的相关性基本上为零。 内联此函数后,它将位于某个较大函数的中间。
使用内联asm代替GNU C内置的__atomic_add_fetch
这样做没有任何好处,后者会根据是否使用结果进行编译以lock xadd
或lock add
。 https://gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins.html 。
如果您确实坚持使用内联asm,请对两个输入/输出操作数使用"+r"
和"+m"
约束,并且只需在asm模板中使用lock xadd
。 让编译器完成剩下的工作,然后用C编写(将寄存器输入设置为asm之前的1
,之后再递增)。 这样,编译器可以根据需要将++
优化为以后的操作。 GCC知道如何将1
放入寄存器,以及如何递增。
当然,gcc也知道如何使用lock
指令,这就是为什么您应该使用内置指令或C ++ 11 std :: atomic使其lock
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.