尝试使用gcc编译nasm对象代码时出错

ev7lccsx  于 2022-11-13  发布在  其他
关注(0)|答案(1)|浏览(379)

我正在尝试使用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。

58wvjzkj

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指令始终使用这样的寻址模式。
相关规范问题/答案:

相关问题