64位Intel汇编:用寄存器作偏移访问数组创建共享库失败求解
问题原因与解决方案
这是因为创建共享库需要生成位置无关代码(PIC),而你使用的[rel array + rax]寻址方式在x86-64的PIC规则下是不合法的,具体原因和解决方法如下:
核心原因
x86-64平台的共享库依赖位置无关代码来实现动态加载(可以被映射到内存的任意地址),这类代码主要通过RIP相对寻址来访问全局数据。但RIP相对寻址仅支持固定偏移量,不能直接和寄存器偏移组合成单一的内存寻址指令:
- 当你写
mov al, BYTE [rel array + 3]时,nasm可以计算出当前指令到array+3的固定偏移,生成合法的RIP相对寻址指令,链接器能正常处理这种固定偏移的重定位。 - 而
[rel array + rax]试图把RIP相对的基址和寄存器偏移结合,x86-64指令集本身没有这种寻址模式的直接支持,nasm编译时不会报错,但链接器无法为这种动态偏移生成合适的重定位条目,导致链接失败。
正确的代码实现
要实现寄存器偏移访问全局数组,你需要先通过lea指令把数组的RIP相对地址加载到一个通用寄存器,再用寄存器基址+寄存器偏移的方式访问:
BITS 64 SECTION .text GLOBAL test test: push rbp mov rbp, rsp mov rax, 3 ; 先获取array的RIP相对地址到rbx寄存器 lea rbx, [rel array] ; 用寄存器基址+寄存器偏移访问数组元素 mov al, BYTE [rbx + rax] pop rbp ret SECTION .data array times 256 db 0
编译链接命令
确保编译时生成PIC代码,链接时生成共享库:
# 编译成64位ELF格式的PIC目标文件 nasm -f elf64 -fPIC your_file.asm -o your_file.o # 链接成共享库 ld -shared your_file.o -o libtest.so
内容的提问来源于stack exchange,提问作者Michael Vouriz
相关产品推荐
相关产品推荐

