繁体   English   中英

在进入嵌入式程序集之前,如何确定其他人没有使用通用寄存器?

[英]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 xaddlock 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM