Почему я не могу получить доступ к массиву с регистром в качестве смещения?

Я делаю некоторый ассемблерный код (intel), и я не понимаю, почему этот код не работает, когда я пытаюсь создать общую библиотеку:

BITS 64
SECTION .text
GLOBAL test
test:
push rbp
mov  rbp, rsp

mov rax, 3
mov  al, BYTE [rel array + rax]

pop  rbp
ret

SECTION  .data
array times 256 db 0

Принимая во внимание, что если вы изменяете строку с помощью "mov", изменяя регистр с номером, это работает:

mov  al, BYTE [rel array + 3]

У меня нет никаких ошибок с Nasm, но когда я пытаюсь связать и создать общую библиотеку с ld:

перемещение R_X86_64_32S к `.data'не может быть использовано при создании общего объекта; перекомпилировать с -fPIC

Я нашел этот ответ для ошибки "R_X86_64_32S": Как работает связывание C++ на практике?

Но что я не понимаю, почему я не могу использовать "rax" в качестве смещения, тогда как я могу с числом.

Есть ли способ просмотреть мысли массива?

Это команды, которые я использую для создания общей библиотеки:

nasm -f elf64 test.s
ld -shared test.o -o test.so

1 ответ

Решение

В длинном режиме (64-битный режим) AMD представила rip относительная адресация к x86. Если вы печатаете

mov  al, BYTE [rel array + 3]

ассемблер генерирует операнд памяти с эффектом

mov  al, BYTE [array + 3 - $ + rip]

Это означает, что когда машинный код загружается по другому адресу, операнд памяти по-прежнему перемещается в нужное место как только относительное смещение array из инструкции, из которой он был получен, кодируется, а не абсолютный адрес array, который не известен во время ссылки.

Теперь причина неудачного связывания при использовании регистра индекса заключается в том, что этот новый режим адресации заменяет предыдущий disp32 режим адресации (мод / м байт 05 +r). Он недоступен в режимах адресации SIB (масштаб / индекс / основание) (фактически, предыдущий disp32 режим адресации по-прежнему доступен через операнд SIB без базы и индекса), поэтому ассемблер не может сгенерировать соответствующий операнд памяти для кода, независимого от позиции.

Решение состоит в том, чтобы сначала загрузить абсолютный адрес array в какой-то регистр, используя lea а затем получить доступ к членам массива относительно только что загруженного адреса:

lea rbx, [rel array]
mov al, byte [rbx + rax]
Другие вопросы по тегам