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