В 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;
}
С лязгом от -O1 до -O3 на x86-64 он очень надежно генерирует:
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 выше.Не могли бы вы объяснить, почему это не так, и возможно ли это сделать с помощью встроенной сборки?
(я использую это для дешевого обнаружения ошибок segfault (если бы не было segfault). Если я знаю длинуиз возможной инструкции segfaulting, я могу пропустить ее в моем обработчике SIGSEGV без необходимости создавать относительно дорогой sigsetjmp, но gcc не генерирует такой надежный код, поэтому я хотел бы заставить его.)