通过 X86-64 的地址位置设置 XMM 寄存器
Set XMM register via address location for X86-64
我在内存中的某个地址有一个浮点值,我想通过使用该地址将 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 位编译时,我在尝试使用寄存器时遇到段错误。这是为什么?
(是的,我的组装能力不是很强...请客气...我已经用了一天了...)
最简单的解决方案是避免ptr()
中的绝对地址。原因是 x86/x86_64 需要 32 位位移,这对于任意用户地址并不总是可能的 - 位移是通过使用当前指令指针和目标地址计算的 - 如果差异在带符号的 32-位整数指令不可编码(这是一个体系结构约束)。
示例代码:
using namespace asmjit;
void setXmmVarViaAddressLocation(x86::Compiler& cc, x86::Xmm& v, const float* f)
{
x86::Gp tmpPtr = cc.newIntPtr("tmpPtr");
cc.mov(tmpPtr, reinterpret_cast<std::uintptr_t>(f);
cc.movq(v, x86::ptr(tmpPtr));
}
如果您想针对没有问题的 32 位模式优化此代码,则必须先检查目标体系结构,例如:
using namespace asmjit;
void setXmmVarViaAddressLocation(x86::Compiler& cc, x86::Xmm& v, const float* f)
{
// Ideally, abstract this out so the code doesn't repeat.
x86::Mem m;
if (cc.is32Bit() || reinterpret_cast<std::uintptr_t>(f) <= 0xFFFFFFFFu) {
m = x86::ptr(reinterpret_cast<std::uintptr_t>(f));
}
else {
x86::Gp tmpPtr = cc.newIntPtr("tmpPtr");
cc.mov(tmpPtr, reinterpret_cast<std::uintptr_t>(f);
m = x86::ptr(tmpPtr);
}
// Do the move, now the content of `m` depends on target arch.
cc.movq(v, x86::ptr(tmpPtr));
}
这样在32位模式下就省了一个寄存器,总是弥足珍贵
我在内存中的某个地址有一个浮点值,我想通过使用该地址将 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 位编译时,我在尝试使用寄存器时遇到段错误。这是为什么?
(是的,我的组装能力不是很强...请客气...我已经用了一天了...)
最简单的解决方案是避免ptr()
中的绝对地址。原因是 x86/x86_64 需要 32 位位移,这对于任意用户地址并不总是可能的 - 位移是通过使用当前指令指针和目标地址计算的 - 如果差异在带符号的 32-位整数指令不可编码(这是一个体系结构约束)。
示例代码:
using namespace asmjit;
void setXmmVarViaAddressLocation(x86::Compiler& cc, x86::Xmm& v, const float* f)
{
x86::Gp tmpPtr = cc.newIntPtr("tmpPtr");
cc.mov(tmpPtr, reinterpret_cast<std::uintptr_t>(f);
cc.movq(v, x86::ptr(tmpPtr));
}
如果您想针对没有问题的 32 位模式优化此代码,则必须先检查目标体系结构,例如:
using namespace asmjit;
void setXmmVarViaAddressLocation(x86::Compiler& cc, x86::Xmm& v, const float* f)
{
// Ideally, abstract this out so the code doesn't repeat.
x86::Mem m;
if (cc.is32Bit() || reinterpret_cast<std::uintptr_t>(f) <= 0xFFFFFFFFu) {
m = x86::ptr(reinterpret_cast<std::uintptr_t>(f));
}
else {
x86::Gp tmpPtr = cc.newIntPtr("tmpPtr");
cc.mov(tmpPtr, reinterpret_cast<std::uintptr_t>(f);
m = x86::ptr(tmpPtr);
}
// Do the move, now the content of `m` depends on target arch.
cc.movq(v, x86::ptr(tmpPtr));
}
这样在32位模式下就省了一个寄存器,总是弥足珍贵