我正在尝试使用nasm中的printf函数。我的程序是这样设置的:
section .text
global main
extern printf
main:
endbr64
push rbp
mov rdi, [array + 1 * 4]
mov rsi, specifer
mov rax, 0
call printf
pop rbp
mov rax, 0
ret
section .data
array db 1,2,3,4,5,6,7,8,9,1
arrlen equ $ - array
specifer db '%d',0xa,0
speclen equ $ - specifer
我正在运行这些命令进行编译:
nasm -f elf64 arrays.asm
gcc arrays.o
但当我这样做时,我得到这个错误:
arrays.asm:6: warning: label alone on a line without a colon might be in error [-w+orphan-labels]
/usr/bin/ld: arrays.o: relocation R_X86_64_32S against `.data' can not be used when making a PIE object; recompile with -fPIE
collect2: error: ld returned 1 exit status
我试着用-fPIE重新编译,但是我得到了字面上完全相同的错误。我做错了什么?
以下是我正在使用的工具的版本:
NASM: 2.14.02
GCC: 9.4.0
ld: 2.34
在这一点上我的目标只是让它编译。我已经尝试使用LD而不是GCC,但我只是不断得到一个segfault。
1条答案
按热度按时间58wvjzkj1#
更新您的nasm版本或删除
endbr64
指令以修复第一个错误。您的nasm版本太旧,不支持它。由于您似乎没有启用控制流实施,因此在代码中包含该指令并不重要。错误消息具有误导性;你的代码中没有编译步骤。通常编译器会生成汇编代码。如果你没有指示编译器遵守PIE(位置无关可执行文件)规则,而是试图链接一个PIE二进制文件,链接器会给你这个提示。但是,当你用汇编语言编写代码时,你就是编译器,你需要自己遵守这些规则。
有两种解决方案:或者与
-no-pie
链接以禁止生成PIE二进制文件,或修复代码以确认符合PIE规则。第二个修复是通过不引用代码中任何符号的绝对地址来完成的。出错的指令是mov rsi, specifer
,它加载将specifer
的(绝对)地址转换为rsi
。请将其替换为lea rsi, [rel specifer]
,以使用rip相对寻址来符合规则。您可以'我还必须给mov rdi, [array + 1 * 4]
添加一个rel
关键字,使其使用相同的RIP相对寻址模式。如果可能,您可以使用
default rel
指令始终使用这样的寻址模式。相关规范问题/答案: