我想用NASM和GCC做一个程序:

global main
extern puts

section .data
  hi db 'hello', 0

section .text
main:
  push hi
  call puts
  ret

我正在建造:
nasm -f elf64 main.asm
gcc main.o -o main
rm main.o

我得到:
/usr/bin/ld: main.o: relocation R_X86_64_32S against `.data' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: Nonrepresentable section on output
collect2: error: ld returned 1 exit status

thisthis等例子中出现的奇怪堆栈操作来看,我感觉自己做错了一些事情。不过,出于某种原因,我找不到任何能解释这一点的文档(事实上,我几乎找不到任何有用的文档来用于使用NASM进行64位开发,这使得我迄今为止所做的一切都非常麻烦),并且添加这样的东西对我的错误输出没有任何影响。
更新:
我一直在看thisthis
如果我将主菜单更改为:
  push rbp
  mov rax,0
  mov rdi, hi
  call [puts wrt ..got]
  pop rbp
  mov rax,0

  ret

它编译得很好,但是在运行而不是实际打印时会给我一个segfault。我也不明白为什么要从堆栈中推和拉rbp的值,以及为什么在这种情况下rax的值很重要。

最佳答案

rbp是被调用方保存的寄存器,因此需要保留它。您不需要更改它,因此不必在这里更改它。不过,您需要保留16字节堆栈对齐,而push是一种简单的方法。您可以使用任何其他寄存器,甚至pop
push应该是sub rsp, 8
函数是通过PLT而不是GOT调用的,也不是通过指针调用的。只要做mov rdi, hi
因此,以下措施应起作用:

global main
extern puts

section .data
  hi db 'hello', 0

section .text
main:
  push rbp
  lea rdi, [rel hi]
  call puts wrt ..plt
  pop rbp
  ret

关于c - 制作共享库(64位NASM + gcc)时,不能使用针对.data的重定位R_X86_64_32S,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/48189051/

10-15 05:31