I am making some assembly code (intel) and I don't understand why this code does not work when I try to create a shared library :
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
Whereas if you modify the line with the "mov" by changing the register with a number, it works :
mov al, BYTE [rel array + 3]
I do not have any error with nasm, but when i try to link and create a shared library with ld :
relocation R_X86_64_32S against `.data' can not be used when making a shared object; recompile with -fPIC
I found this answer for the "R_X86_64_32S" error : How does C++ linking work in practice?
But what I do not understand why I can not use "rax" as an offset, whereas I can with a number.
Is there a way to browse thought the array ?
This is the commands I use to create the shared library :
nasm -f elf64 test.s
ld -shared test.o -o test.so
With long mode (64 bit mode), AMD introduced rip
relative addressing to x86. If you type
mov al, BYTE [rel array + 3]
the assembler generates a memory operand to the effect of
mov al, BYTE [array + 3 - $ + rip]
This means that when the machine code is loaded to a different address, the memory operand still goes to the right place as only the relative offset of array
from the instruction it was referenced from is encoded, not the absolute address of array
, which isn't known at link time.
Now the point why linking fails when using an index register is that this new addressing mode replaces the previous disp32
adressing mode (modr/m byte 05 +r
). It is not available with SIB (scale/index/base) adressing modes (in fact, the previous disp32
adressing mode is still available through a SIB operand with neither base nor index), so the assembler is unable to generate an appropriate memory operand for position independent code.
The solution is to first load the absolute address of array
into some register using lea
and then to access array members relative to the address just loaded:
lea rbx, [rel array]
mov al, byte [rbx + rax]