【发布时间】:2021-11-22 08:20:53
【问题描述】:
我在内存中的某个地址有一个浮点值,我想通过使用该地址将 XMM 寄存器设置为该值。我正在使用asmjit。
此代码适用于 32 位构建,并将 XMM 寄存器 v 设置为正确的值 *f:
using namespace asmjit;
using namespace x86;
void setXmmVarViaAddressLocation(X86Compiler& cc, X86Xmm& v, const float* f)
{
cc.movq(v, X86Mem(reinterpret_cast<std::uintptr_t>(f)));
}
但是,当我以 64 位编译时,我在尝试使用寄存器时遇到了段错误。这是为什么呢?
(是的,我的组装能力不是很强......请善待......我已经做了一天了......)
【问题讨论】:
-
这会产生什么实际的机器代码?它是否可能会截断 64 位地址以适应
[disp32]绝对寻址模式? x86-64 不能使用任意 64 位地址作为绝对直接内存操作数,除了 mov to/from RAX/EAX/AX/AL。通常,您希望对具有 2GiB 代码的静态数据使用 RIP 相对寻址。 -
我不知道 AsmJIT,所以我宁愿不发布次优答案或只是猜测到底发生了什么。不,首先将 data 移动到 RAX 并不是我的意思,如果您最终想要 XMM0 中的数据,那么效率会降低。如果您确实需要使用 64 位绝对地址而不是普通的 RIP 相对地址来处理具有 2GiB 代码的数据(或者如果您可以将数据放在低 32 位中,则使用 32 位绝对地址,例如 Linux
mmap(MAP_32BIT),您'想要mov reg, imm64,使用任何方便的整数寄存器。然后movq xmm0, [reg]。 -
RIP 相对数据的意思是“相对于指令指针”——即嵌入到您的程序中。如果您动态加载数据,您可能无法使用它。
-
我也不知道 asmjit,但是如果你想从内存中加载“a”浮点值,你应该使用
movss而不是movq(后者移动一个四字,即64 位)——两者都将剩余元素设置为零。但这可能不是您的段错误的原因。 -
这似乎是旧版本的 asmjit,不再受支持。一般来说,JIT 编译中的规则是——如果你不知道你提供的地址是否可以通过 32 位有符号位移访问,那么不要使用这样的地址——将地址移动到注册将始终有效,所以我会推荐那。生成代码中的可访问地址通常通过标签引用。此外。当发生不好的事情时,AsmJit 总是返回一个错误,所以总是使用 ErrorHandler - 它会为你节省很多时间,尤其是在这种情况下。
标签: c++ assembly x86-64 sse asmjit