Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays 为什么可以';我不能用寄存器作为偏移量访问数组吗?_Arrays_Assembly_Shared Libraries_X86 64_Position Independent Code - Fatal编程技术网

Arrays 为什么可以';我不能用寄存器作为偏移量访问数组吗?

Arrays 为什么可以';我不能用寄存器作为偏移量访问数组吗?,arrays,assembly,shared-libraries,x86-64,position-independent-code,Arrays,Assembly,Shared Libraries,X86 64,Position Independent Code,我正在编写一些汇编代码(英特尔),但我不明白为什么在尝试创建共享库时此代码不起作用: 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 nasm -f elf64 test.s ld -shared test.o -o test.s

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

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
nasm -f elf64 test.s
ld -shared test.o -o test.so
然而,如果您通过更改带有数字的寄存器来修改带有“mov”的行,则它可以工作:

mov  al, BYTE [rel array + 3]
nasm没有任何错误,但当我尝试使用ld链接并创建共享库时:

在进行更改时,无法使用针对“.data”的重新定位R_X86_64_32S 共享对象;用-fPIC重新编译

我找到了“R_X86_64_32S”错误的答案:

但我不明白的是,为什么我不能使用“rax”作为偏移量,而我可以使用数字

有没有办法浏览阵列

以下是我用于创建共享库的命令:

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
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]
这意味着,当机器代码加载到不同的地址时,内存操作数仍然会转到正确的位置,因为只有
数组
相对于它引用的指令的相对偏移量被编码,而不是
数组
的绝对地址,这在链接时是未知的

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

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

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

如果nasm没有为
[rel array+rax]
生成错误,那么它就是一个bug。它应该告诉您这是一个无效的寻址模式。@fuz-thx的答案,但要知道,如果您使用gcc来生成二进制文件,它是有效的,为什么?gcc需要进行链接并且应该失败吗?
[array+3-$+rip]
也不太正确
$
是当前指令的开始,但RIP相对寻址是相对于指令的结束(即下一条指令的开始)。@PeterCordes我知道。然而,添加这一点会有点复杂和乏味。@PeterCordes我的回答是“这种新的寻址模式取代了以前的
disp32
寻址模式。”这到底是怎么回事?我还明确指出,rip相对寻址模式仅在没有SIB的情况下可用。请再次阅读我的回答,您可能误解了倒数第二段。相关::PIE可执行文件对使用
[array+rax]
具有相同的限制,因为它要求地址适合32位符号扩展值。正如Jester所说,奇怪的是NASM没有在
[rel-array+rax]
上发出警告,因为rel不是一个选项,所以它被编码为
[abs-array+rax]
。顺便说一句,您可以使用
defaultrel
使NASM尽可能使用RIP relative。