为什么我不能访问以寄存器作为偏移量的数组?
why can't i access an array with a register as offset?
我正在编写一些汇编代码 (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 没有任何错误,但是当我尝试 link 并使用 ld 创建共享库时:
relocation R_X86_64_32S against `.data' can not be used when making a
shared object; recompile with -fPIC
我找到了 "R_X86_64_32S" 错误的答案:How does C++ linking work in practice?
但是我不明白为什么我不能使用 "rax" 作为偏移量,而我可以使用数字。
有没有办法浏览数组?
这是我用来创建共享库的命令:
nasm -f elf64 test.s
ld -shared test.o -o test.so
对于长模式(64 位模式),AMD 引入了 rip
x86 的相对寻址。如果你输入
mov al, BYTE [rel array + 3]
汇编程序生成一个内存操作数,效果为
mov al, BYTE [array + 3 - $ + rip]
这意味着当机器代码被加载到不同的地址时,内存操作数仍然会到达正确的位置,因为只有array
相对于它被引用的指令的相对偏移量被编码,而不是array
的绝对地址,在 link 时未知。
现在使用变址寄存器时linking失败的原因是这种新的寻址模式取代了以前的disp32
寻址模式(modr/m byte 05 +r
) .它不适用于 SIB (scale/index/base) 寻址模式(事实上,之前的 disp32
寻址模式仍然可以通过既没有基数也没有索引的 SIB 操作数使用),因此汇编器无法生成位置无关代码的适当内存操作数。
解决方案是首先使用lea
将array
的绝对地址加载到某个寄存器中,然后访问相对于刚刚加载的地址的数组成员:
lea rbx, [rel array]
mov al, byte [rbx + rax]
我正在编写一些汇编代码 (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 没有任何错误,但是当我尝试 link 并使用 ld 创建共享库时:
relocation R_X86_64_32S against `.data' can not be used when making a shared object; recompile with -fPIC
我找到了 "R_X86_64_32S" 错误的答案:How does C++ linking work in practice?
但是我不明白为什么我不能使用 "rax" 作为偏移量,而我可以使用数字。
有没有办法浏览数组?
这是我用来创建共享库的命令:
nasm -f elf64 test.s
ld -shared test.o -o test.so
对于长模式(64 位模式),AMD 引入了 rip
x86 的相对寻址。如果你输入
mov al, BYTE [rel array + 3]
汇编程序生成一个内存操作数,效果为
mov al, BYTE [array + 3 - $ + rip]
这意味着当机器代码被加载到不同的地址时,内存操作数仍然会到达正确的位置,因为只有array
相对于它被引用的指令的相对偏移量被编码,而不是array
的绝对地址,在 link 时未知。
现在使用变址寄存器时linking失败的原因是这种新的寻址模式取代了以前的disp32
寻址模式(modr/m byte 05 +r
) .它不适用于 SIB (scale/index/base) 寻址模式(事实上,之前的 disp32
寻址模式仍然可以通过既没有基数也没有索引的 SIB 操作数使用),因此汇编器无法生成位置无关代码的适当内存操作数。
解决方案是首先使用lea
将array
的绝对地址加载到某个寄存器中,然后访问相对于刚刚加载的地址的数组成员:
lea rbx, [rel array]
mov al, byte [rbx + rax]