在进入内联汇编之前,如何确定通用寄存器没有被其他人使用?
How can I be sure a general purpose register is not being used by others before entering a inline assembly?
下面是一段GCC内联汇编代码。它以原子方式将输入 *Value
增加 1。并且 return 增加的值。
在汇编代码中,它使用了EAX
寄存器。在调用此函数之前,我怎么知道 EAX
没有被其他人使用?如果正在使用,汇编代码会损坏一些东西。
UINT32
__cdecl
AtomicIncrement (
IN volatile UINT32 *Value
)
{
UINT32 Result;
__asm__ __volatile__ (
"movl , %%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;
}
我从 here 中读到:
...Integer values and memory addresses are returned in the EAX
register... (the cdecl call convention)
那么这是否意味着如果我遵循 cdecl
调用约定,编译器将确保 EAX
在输入时可以 安全使用 组装功能?如果我使用其他一些通用寄存器,比如说 EBX
,我 必须 把它放在 clobber section? IE。在最后一个冒号之后?
您正在使用 "=a"
输出操作数,因此编译器知道您的 asm 写入该寄存器。
它会做出相应的计划,在你的 asm 运行后使用不同的寄存器来存放它想要的任何东西。是否向编译器准确描述你的 asm 取决于你,否则它就是一个黑盒子。
函数调用约定与内联汇编的相关性基本上为零。
此函数内联后,它将位于某个较大函数的中间。
使用内联 asm 而不是 GNU C 内置 __atomic_add_fetch
执行此操作没有任何好处,它将编译为 lock xadd
或 lock add
,具体取决于是否使用结果. https://gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins.html.
如果您坚持使用内联汇编,请对两个 input/output 操作数和 仅 使用 "+r"
和 "+m"
约束在 asm 模板中有 lock xadd
。让编译器完成剩下的工作,所以用 C 语言编写(在 asm 之前将寄存器输入设置为 1
,然后递增)。这让编译器可以根据需要将 ++
优化为稍后的操作。 GCC 知道如何将 1
放入寄存器,以及如何递增。
当然,gcc 也知道如何使用 lock
ed 指令,这就是为什么你应该让它通过使用内置函数或 C++11 std::atomic.
下面是一段GCC内联汇编代码。它以原子方式将输入 *Value
增加 1。并且 return 增加的值。
在汇编代码中,它使用了EAX
寄存器。在调用此函数之前,我怎么知道 EAX
没有被其他人使用?如果正在使用,汇编代码会损坏一些东西。
UINT32
__cdecl
AtomicIncrement (
IN volatile UINT32 *Value
)
{
UINT32 Result;
__asm__ __volatile__ (
"movl , %%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;
}
我从 here 中读到:
...Integer values and memory addresses are returned in the EAX register... (the cdecl call convention)
那么这是否意味着如果我遵循 cdecl
调用约定,编译器将确保 EAX
在输入时可以 安全使用 组装功能?如果我使用其他一些通用寄存器,比如说 EBX
,我 必须 把它放在 clobber section? IE。在最后一个冒号之后?
您正在使用 "=a"
输出操作数,因此编译器知道您的 asm 写入该寄存器。
它会做出相应的计划,在你的 asm 运行后使用不同的寄存器来存放它想要的任何东西。是否向编译器准确描述你的 asm 取决于你,否则它就是一个黑盒子。
函数调用约定与内联汇编的相关性基本上为零。 此函数内联后,它将位于某个较大函数的中间。
使用内联 asm 而不是 GNU C 内置 __atomic_add_fetch
执行此操作没有任何好处,它将编译为 lock xadd
或 lock add
,具体取决于是否使用结果. https://gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins.html.
如果您坚持使用内联汇编,请对两个 input/output 操作数和 仅 使用 "+r"
和 "+m"
约束在 asm 模板中有 lock xadd
。让编译器完成剩下的工作,所以用 C 语言编写(在 asm 之前将寄存器输入设置为 1
,然后递增)。这让编译器可以根据需要将 ++
优化为稍后的操作。 GCC 知道如何将 1
放入寄存器,以及如何递增。
当然,gcc 也知道如何使用 lock
ed 指令,这就是为什么你应该让它通过使用内置函数或 C++11 std::atomic.