在某些编译器上(我最感兴趣的是GCC/clang)使用void *jmp = &&label
,您可以获得标签的地址,稍后可以使用goto jmp
。对于使用指针标记的解释器,我希望将这些标签与下一个8字节边界对齐,因此标签值都具有0b...000。通常,您可以将指令位置与汇编对齐,例如,__asm__ volatile(".p2align 8");
将使用NOP
s等填充2^8
字节的下一条指令。但是,由于解释器在跳转块之间没有代码,因此汇编得到了优化(或其他-即使使用volatile
,它也不会出现在输出中)。
void test() {
void *next = &&LABEL_A;
goto *next;
/* won't get reached – optimized away? */
__asm__ volatile(".p2align 8");
LABEL_A:
goto *next;
}
在godbolt上,它显示编译器没有对齐LABEL_A
。
void test() {
unsigned long foo = (unsigned long)&&LABEL;
void *next = &&LABEL_A;
goto *next;
LABEL:
__asm__ volatile(".p2align 8");
LABEL_A:
goto *next;
}
output将显示LABEL_A
得到了正确的填充-大概是因为LABEL
和下面的语句无法得到优化。然而,这似乎非常脆弱,不适用于-O3
。有更好的方法吗?
我尝试了几个__attribute__(aligned(8), used)
属性、块之间的volatile
值/访问,尽管只有LABEL
引用阻止了代码消除。
1条答案
按热度按时间vfwfrxfs1#
对于GCC,应该使用
-falign-labels=8
或较弱的-falign-jumps=8
选项。您可以将它们放在函数属性中:
__attribute__((optimise ("-falign-labels=8"))
.