linux - 在 64 位模式下编译 NASM 代码时出现重定位错误
问题描述
我编写了一个简单的汇编代码,我试图在 64 位模式下编译。这是代码:
extern printf
section .rodata
readinfo db `%d\n`, 0
section .text
global main
main:
mov rbp, rsp ; for correct debugging
mov rax, 5
push rax
push readinfo
call printf
add rsp, 8
xor rax, rax
mov rsp, rbp
ret
以下是我给 nasm 和 gcc 的说明(正如我在其他帖子中所读到的,gcc 会自动将目标文件与默认的 c 库链接):
nasm -f elf64 -o test.o test.asm -D UNIX
gcc -o test test.o
但是,我收到以下重定位错误:
/usr/bin/x86_64-linux-gnu-ld: test.o: relocation R_X86_64_32S 对 `.rodata' 不能在制作 PIE 对象时使用;使用 -fPIC 重新编译
/usr/bin/x86_64-linux-gnu-ld:最终链接失败:输出中不可表示的部分
collect2:错误:ld 返回 1 个退出状态
当我使用“-no-pic”选项编译以禁用与位置无关的代码时,它编译时没有错误,但执行后我得到一个没有输出的段错误。当我以 32 位重新编译代码(用 32 位替换 64 位寄存器)时,我没有收到任何错误。命令是:
nasm -f elf32 -o test.o test.asm -D UNIX
gcc -o test test.o -m32
我的问题是:为什么我不能在 64 位模式下用 PIC 编译代码?
PS:这不是Can't link a shared library from an x86-64 object from an assembly because of PIC的重复,因为错误是不同的,并且在该帖子中找到的解决方案与我的问题无关。我已经编辑了要指定的错误输出。
解决方案
错误是我使用了错误的调用约定。在架构 x86_64 中,前两个参数分别在 rdi 和 rsi 中传递,而不使用堆栈。另外,我需要在通话中添加“wrt ..plt”。以下代码有效:
extern printf
section .rodata
readinfo db `%d\n`, 0
section .text
global main
main:
mov rbp, rsp ; for correct debugging
mov rsi, 5
mov rdi, readinfo
xor rax, rax
call printf wrt ..plt
xor rax, rax
mov rsp, rbp
ret
nasm 和 gcc 的命令没有改变。
推荐阅读
- list - 如何在 Python3 中检查一个空列表
- r - 在 R 中使用管道运算符重命名变量
- c# - 下载文件时防止 UI 冻结
- javascript - React Checkbox Component返回唯一键道具错误
- javascript - 在wixsite的javascript中循环遍历数组
- java - Java Spring,如何检索记录并使用新的唯一键发布重复项?
- qt - QCursor::pos() 和 event->globalPos() 有什么区别?
- windows - 有没有办法在 Windows 中设置 awsglue 模块以在本地测试 Python Glue 作业
- mongodb - MongoDB查找部门的最高工资
- python - 如何将列表中的所有整数乘以它们的索引相加?