c - 使用 GCC 内联汇编的 PC 相关调用

标签 c gcc assembly x86-64 inline-assembly

我写了下面的示例代码。但它会生成调用指令的“接近、绝对间接、在 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/

相关文章:

c - 使用 strtok() 在 C 中分隔文件路径

c - 是否允许编译器向标准头文件添加函数?

c++ - 如何使用 DW2 构建定制的 MinGW 交叉编译器

c - 如何在ARMv6+上实现16bit立体声混音?

c++ - 从 Swift 调用 C++ 函数

c - 如何断开单个进程与共享内存对象的连接

c++ - 如何通过 .pro 文件 (Qt) 将命令传递给链接描述文件

c++ - 禁用 rtti 的后果?

assembly - STM32如何延迟一个时钟周期?

c - 内存地址计算在 "Smashing The Stack For Fun And Profit"