gpt4 book ai didi

arrays - 为什么我不能访问以寄存器作为偏移量的数组?

转载 作者:行者123 更新时间:2023-12-02 20:28:08 26 4
gpt4 key购买 nike

我正在编写一些汇编代码(英特尔),但我不明白为什么当我尝试创建共享库时此代码不起作用:

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 链接并创建共享库时:

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 向 x86 引入了 rip 相对寻址。如果您输入

mov  al, BYTE [rel array + 3]

汇编器生成一个内存操作数,其作用是

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

这意味着当机器代码加载到不同的地址时,内存操作数仍然会到达正确的位置,因为仅对 array 相对于引用它的指令的相对偏移量进行编码,不是array的绝对地址,它在链接时是未知的。

现在使用变址寄存器时链接失败的原因在于,这种新的寻址模式取代了之前的 disp32 寻址模式(modr/m byte 05 +r)。它不适用于 SIB (scale/index/base) 寻址模式(事实上,之前的 disp32 寻址模式仍然可以通过既没有基址也没有索引的 SIB 操作数来使用),因此汇编器无法使用为位置无关代码生成适当的内存操作数。

解决方案是首先使用leaarray的绝对地址加载到某个寄存器中,然后访问相对于刚刚加载的地址的数组成员:

lea rbx, [rel array]
mov al, byte [rbx + rax]

关于arrays - 为什么我不能访问以寄存器作为偏移量的数组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49390580/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com