Установите регистр XMM через расположение адреса для X86-64
У меня есть значение с плавающей запятой по некоторому адресу в памяти, и я хочу установить регистр XMM на это значение, используя адрес. Я использую асмджит .
Этот код работает для 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 бита, я получаю segfault при попытке использовать регистр. Это почему?
(И да, я не очень силен в сборке ... Будьте добры ... Я вот уже день за этим занимаюсь ...)
1 ответ
Самое простое решение — не указывать абсолютный адрес в
Пример кода:
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-битном режиме, что всегда ценно.