簡體   English   中英

將生成的程序集重寫為GCC內聯程序集

[英]Rewriting generated assembly into GCC inline assembly

在CI中有:

struct segv_ctrl {
    _Bool volatile*volatile rfaulted_eh_ptr;
    _Bool volatile*volatile wfaulted_eh_ptr;
};
_Thread_local struct segv_ctrl segv_ctrl;
_Bool rfaulted_eh(char volatile*Ptr)
{
    _Bool volatile faulted=0;
    char c; _Bool r;
    segv_ctrl.rfaulted_eh_ptr = &faulted;
    #if 1
    c=*Ptr;
    r = faulted;
    #else
    //I'd like this to produce the same code as the #if block above
    //but I obviously have no idea what I'm doing :D
    __asm__ __volatile__ (
        "mov (%2),%0;\n"
        "mov %3,%1;\n"
        : "=r"(c), "=r"(r)
        : "r" (Ptr), "r"(faulted)

    );
    #endif
    return r;
}
_Bool wfaulted_eh(char volatile*Ptr)
{
    _Bool volatile faulted=0;
    _Bool r;
    segv_ctrl.wfaulted_eh_ptr = &faulted;
    #if 1
    *Ptr=0;
    r = faulted;
    #else
    #endif
    return r;
}

在x86-64上使用從-O1到-O3的clang,它非常可靠地生成:

c.o:     file format elf64-x86-64


Disassembly of section .text:

0000000000000000 <rfaulted_eh>:
   0:   c6 44 24 ff 00          movb   $0x0,-0x1(%rsp)
   5:   48 8d 44 24 ff          lea    -0x1(%rsp),%rax
   a:   64 48 89 04 25 00 00    mov    %rax,%fs:0x0
  11:   00 00 
  13:   8a 07                   mov    (%rdi),%al
  15:   8a 44 24 ff             mov    -0x1(%rsp),%al
  19:   c3                      retq   
  1a:   66 0f 1f 44 00 00       nopw   0x0(%rax,%rax,1)

0000000000000020 <wfaulted_eh>:
  20:   c6 44 24 ff 00          movb   $0x0,-0x1(%rsp)
  25:   48 8d 44 24 ff          lea    -0x1(%rsp),%rax
  2a:   64 48 89 04 25 00 00    mov    %rax,%fs:0x0
  31:   00 00 
  33:   c6 07 00                movb   $0x0,(%rdi)
  36:   8a 44 24 ff             mov    -0x1(%rsp),%al
  3a:   c3                      retq   

我想拿

mov    (%rdi),%al
mov    -0x1(%rsp),%al

部分和

movb   $0x0,(%rdi)
mov    -0x1(%rsp),%al

零件,然后將它們變成可重復使用的,可插入的匯編摘要。

我非常失敗的嘗試顯示在上面省略的#if塊中。 您能否解釋為什么這是錯誤的,並且可以通過內聯匯編實現此功能?

(我正在使用它廉價地檢測段錯誤(如果不會出現段錯誤)。如果我知道可能的段錯誤指令的長度,則可以在我的SIGSEGV處理程序中跳過它,而不必花費相當大的代價sigsetjmp,但gcc不會生成如此可靠的代碼,因此我想強制執行。)

第二行只是從堆棧中加載faulted ,您不需要在asm中加載它,它也永遠不會faulted (假設以前的初始化沒有faulted )。 您可以使用

"mov (%1), %0" : "=a" (c) : "D" (Ptr)

"movb $0, (%1)" : "=m" (*Ptr): "D" (Ptr)

其中arax適當大小的子寄存器,對於8位為al Drdi寄存器。 =表示輸出。 m是一個通用的內存操作數,用於告訴編譯器asm正在*Ptr處寫入內存。 由於您的Ptrvolatile因此可以在此處省略,這樣編譯器將不會緩存該值,但不會造成損害。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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