我编写了一个简单的汇编代码,试图在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:将R_X86_64_32S重定位为 制作PIE对象时不能使用`.rodata'。重新编译 -fPIC
/ usr / bin / x86_64-linux-gnu-ld:最终链接失败:无法表示 输出部分
collect2:错误:ld返回1个退出状态
当我使用'-no-pic'选项进行编译以禁用与位置无关的代码时,它编译时没有错误,但是执行后,我遇到了没有输出的段错误。 当我重新编译32位代码(将64位寄存器替换为32位)时,没有任何错误。这些命令是:
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 assembly because of PIC的重复项,因为错误有所不同,并且该帖子中找到的解决方案与我的问题无关。我已编辑错误输出以指定。
答案 0 :(得分:2)
错误是我使用了错误的调用约定。在体系结构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的命令未更改。