簡體   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