簡體   English   中英

__asm __volatile 如何執行?

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

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM