assembly - 当您需要调用大于 2^32 位的函数时会发生什么?

标签 assembly linker x86 masm

我刚刚发现我们通常所说的调用指令实际上是与程序计数器相关的。然而 x86 指令使用 32 位宽的偏移量来指示相对数字。

如果我想跳到 > 4GB 之外怎么办?

最佳答案

我猜想,如果您将一些代码 JIT 到一个分配了超过 2^32 距离它需要调用的某些函数的缓冲区中,就会出现这种情况。简单的答案是:不要这样做。

例如,在 Linux 上,如果您希望 JIT 代码调用中的函数,请使用 mmap(MAP_32BIT) 在虚拟地址空间的低 2GiB 中分配内存主要可执行文件。 (假设一个位置相关的可执行文件)。

在 PIE 可执行文件或共享库(通常不会映射到虚拟地址空间的低 32 位)中,您可以尝试通过尝试 mmap 在您自己的代码附近分配内存没有 MAP_FIXEDtrying different addresses in range if that doesn't work the first timemmap(hint_address, ...)/检查它是否在需要到达的代码和/或数据的 +-2GiB 范围内/munmap 并使用不同的提示重试。

<小时/>

原因是唯一的解决方法是使用绝对地址间接调用。请参阅Call an absolute pointer in x86 machine code 。您需要将目标地址加载到寄存器中,或者将地址作为指针存储在内存中,然后跳转到该地址。请参阅 Intel 的 insn ref 手册,其中 all the available encodings of call are listed.

还有x86 tag wiki链接到https://www-ssl.intel.com/content/www/us/en/processors/architectures-software-developer-manuals.html

<小时/>

如果您不需要它非常高效,实际 JIT 绝对间接调用的一种方法是将指针表放在相对于 JIT 代码的已知位置,以便它可以使用间接 call [rel point_to_func1](RIP 相对寻址)。这就像 Unix 共享库使用的全局偏移表,以及使用 gcc -fno-plt 编译时编译器生成的代码如何调用共享库函数。

关于assembly - 当您需要调用大于 2^32 位的函数时会发生什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31819019/

相关文章:

c - 有没有办法以编程方式生成内联汇编?

c - Gdb 和外部函数

c - 在 Sparc 32 位上处理值 > 2^32 的整数

x86 - 为新指令集开发

assembly - 如何为我的引导加载程序制作内核?

c - 为什么机器代码取决于操作系统类型?

c++ - MVC++ 静态库不生成任何导出

c++ - 在另一个 header 中强制模板实例化

rust - 我如何定位我的 Rust 应用程序及其对 musl 的依赖?

c++ - 如何以编程方式检查 CPU 上是否启用了融合乘加 (FMA) 指令?