Установите регистр 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 ответ

Самое простое решение — не указывать абсолютный адрес в . Причина в том, что 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-битном режиме, что всегда ценно.

Другие вопросы по тегам