【发布时间】:2016-12-22 00:28:07
【问题描述】:
我正在尝试从机器代码调用一个函数——在编译和链接时它应该有一个绝对地址。我正在创建一个指向所需函数的函数指针并尝试将其传递给调用指令,但我注意到调用指令最多需要一个 16 位或 32 位地址。有没有办法调用绝对 64 位地址?
我正在为 x86-64 架构进行部署,并使用 NASM 生成机器代码。
如果我可以保证可执行文件肯定会映射到底部的 4GB 内存,我可以使用 32 位地址,但我不确定在哪里可以找到该信息。
编辑:我不能使用 callf 指令,因为这需要我禁用 64 位模式。
第二次编辑:我也不想将地址存储在寄存器中并调用寄存器,因为这对性能至关重要,而且我不能承受间接函数调用的开销和性能损失.
最终编辑:通过确保我的机器代码映射到前 2GB 内存,我能够使用 rel32 调用指令。这是通过带有 MAP_32BIT 标志的 mmap 实现的(我使用的是 linux):
MAP_32BIT(自 Linux 2.4.20、2.6 起) 将映射放入前 2 GB 进程地址空间。仅支持此标志 在 x86-64 上,用于 64 位程序。它被添加到 允许在某处分配线程堆栈 前 2GB 内存,以提高上下文- 在一些早期的 64 位处理器上切换性能。 现代 x86-64 处理器不再具有此特性 形成问题,所以使用这个标志不是 在这些系统上需要。 MAP_32BIT 标志是 设置 MAP_FIXED 时忽略。
【问题讨论】:
-
把它放在一个 64 位的寄存器中然后调用它?应该很容易验证。
-
为什么这个标签是 C++?
-
他可能使用 C++ 函数指针从 C++ 调用他的汇编程序,但这确实与关于 x86-64 汇编程序的问题无关。
-
@Brian 我取出了 C++ 标签
-
@RudyVelthuis 查看我对问题的第二次编辑
标签: assembly x86-64 nasm jit function-call