我写了下面的示例代码。但它会生成调用指令的“接近、绝对间接、在 r/m32 中给出的地址”(如 [1] 中给出)变体,该变体因段错误而失败,因为地址被解释为绝对地址。有没有办法用 GCC 内联汇编生成 PC 相关调用?顺便说一句,代码正确计算了相对距离,因此没有问题。
#include <stdio.h>
void print_fn() {
printf("Hello there..\n");
}
int main() {
long relative = (long) ((unsigned char*)&&label - (unsigned char*)print_fn);
__asm__ volatile ("call *%0;"
:
: "r"(relative)
);
label:
;
return 0;
}
反汇编器输出如下。
Dump of assembler code for function main:
0x00000000004004d4 <+0>: 55 push %rbp
0x00000000004004d5 <+1>: 48 89 e5 mov %rsp,%rbp
0x00000000004004d8 <+4>: ba f5 04 40 00 mov $0x4004f5,%edx
0x00000000004004dd <+9>: b8 c4 04 40 00 mov $0x4004c4,%eax
0x00000000004004e2 <+14>: 48 89 d1 mov %rdx,%rcx
0x00000000004004e5 <+17>: 48 29 c1 sub %rax,%rcx
0x00000000004004e8 <+20>: 48 89 c8 mov %rcx,%rax
0x00000000004004eb <+23>: 48 89 45 f8 mov %rax,-0x8(%rbp)
0x00000000004004ef <+27>: 48 8b 45 f8 mov -0x8(%rbp),%rax
0x00000000004004f3 <+31>: ff d0 callq *%rax
0x00000000004004f5 <+33>: b8 00 00 00 00 mov $0x0,%eax
0x00000000004004fa <+38>: c9 leaveq
0x00000000004004fb <+39>: c3 retq
[1] http://x86.renejeschke.de/html/file_module_x86_id_26.html
最佳答案
所有 near 和 direct call
指令都使用相对寻址。所以你真的不需要任何东西:
__asm__ volatile ("call %P0" : : "i" (print_fn)
: "rax", "rcx", "rdx", "rsi", "rdi",
"r8", "r9", "r10", "r11",
"xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5",
"xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11",
"xmm12", "xmm13", "xmm14", "xmm15", "memory", "cc");
这将创建一个 call
指令,其相对于 print_fn
有一个位移。它还告诉编译器该指令将破坏内存和一大堆寄存器,即那些在 Linux 上调用时未保留的寄存器。
关于c - 使用 GCC 内联汇编的 PC 相关调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25456929/