Почему я не могу получить доступ к массиву с регистром в качестве смещения?
Я делаю некоторый ассемблерный код (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]