![](/img/trans.png)
[英]How long it takes to GCC compiler execute an asm volatile (“nop”/::) instruction?
[英]How does __asm __volatile execute?
gcc_inline void
lcr0(uint32_t val)
{
__asm __volatile("movl %0,%%cr0" : : "r" (val));
}
在上面的代碼中,我不確定將 val 插入到程序集字符串的何處。 val 是否替換字符串中的 %c?
如果可能的話,有人可以澄清: : "r"
作用嗎?
"r"
表示您將%0
指定為寄存器(作為輸入)。 (val)
表示您指定寄存器應包含val
的值。 因此編譯器將分配一個寄存器並確保它包含val
。 對於 x86_64,函數的第一個參數將在%edi
/ %rdi
,這就是%0
將擴展到的。
我站糾正...
...如果該函數沒有內聯,則val
將在edi
/ rdi
傳遞,但可能會在asm
之前混洗,但"r"
將導致編譯器將其安排在asm
某個寄存器中。 (請參閱下面的 -O0 的效果)。
此外,未聲明/定義為內聯的函數也可以在更高級別的優化中內聯。
我注意到只能從通用寄存器讀取/寫入CR0
,然后只能在特權級別 0。@PeterCordes 指出"memory"
破壞可能是一個好主意。 顯然,改變CR0
會產生非常令人興奮的副作用!
當我在-O0
嘗試此操作時,我發現忽略了一個簡單的inline
,並且為 x86_64 編譯的函數為:
lcr0:
pushq %rbp
movq %rsp, %rbp
movl %edi, -4(%rbp)
movl -4(%rbp), %eax
movl %eax,%cr0
nop
popq %rbp
ret
我猜gcc_inline
可能包括__attribute__((__always_inline__))
,在這種情況下,即使在-O0
lcr0
也是內聯的——但是有很多可愛的堆棧業務。 這次是 x86:
main:
pushl %ebp
movl %esp, %ebp
subl $16, %esp
movl 12(%ebp), %eax
movl (%eax), %eax
movl (%eax), %eax
movl %eax, -4(%ebp)
movl -4(%ebp), %eax
movl %eax, -8(%ebp)
movl -8(%ebp), %eax
movl %eax,%cr0
nop
movl $0, %eax
leave
ret
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.