Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/59.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将生成的程序集重写为GCC内联程序集_C_Gcc_Assembly_Clang_X86 64 - Fatal编程技术网

将生成的程序集重写为GCC内联程序集

将生成的程序集重写为GCC内联程序集,c,gcc,assembly,clang,x86-64,C,Gcc,Assembly,Clang,X86 64,在C中,我有: 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

在C中,我有:

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的叮当声,它可以非常可靠地生成:

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   
部分及

movb   $0x0,(%rdi)
mov    -0x1(%rsp),%al
并将它们转换为可重用的、可内联的程序集片段

我非常不成功的尝试显示在上面的省略的#if块中。 您能解释一下为什么它是错误的,并且可以通过内联汇编实现这一点吗


(我用它来廉价地检测segfault(如果没有segfault的话)。如果我知道可能的segfaulting指令的长度,我可以在我的SIGSEGV处理程序中跳过它,而不必制作相对昂贵的sigsetjmp,但gcc不会生成如此可靠的代码,所以我想强制它。)

第二行只是从堆栈中加载出现故障的
,asm中不需要它,它也不会出现故障(假设之前的初始化没有故障)。你可以用

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


其中,
a
rax
的适当大小的子寄存器,它是8位的
al
D
rdi
寄存器<代码>=表示输出
m
是一个通用内存操作数,用于告诉编译器asm正在
*Ptr
处写入内存。这里可以省略,因为您的
Ptr
易失性的
,因此编译器不会缓存该值,但不会造成伤害。

在不知道长度的情况下,如何跳过错误指令?我想知道你在这里干什么。但考虑到我已经习惯英特尔汇编(-masm=Intel),我很难做到这一点。另外,您是否考虑过简单地在汇编中编写整个函数?@Micrified您不能。这就是我试图生成已知指令的原因。(实际上,您可以通过在sigsegv处理程序中反汇编当前指令来完成此操作-这是我以前做过的:)@Micrified这绝对是一个充分且易于实现的解决方案,但我想我会尝试并找出如何使用内联汇编来完成此操作。“现在读更多关于它的内容。”Michrified有趣的方法。
"mov (%1), %0" : "=a" (c) : "D" (Ptr)
"movb $0, (%1)" : "=m" (*Ptr): "D" (Ptr)