在64位模式下编译NASM代码时发生重定位错误 [英] Relocation error when compiling NASM code in 64-bit mode

查看:163
本文介绍了在64位模式下编译NASM代码时发生重定位错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我编写了一个简单的汇编代码,试图在64位模式下进行编译.这是代码:

I have written a simple assembly code which I am trying to compile in 64-bit mode. Here is the code:

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库链接):

And here are the instructions I give to nasm and gcc (as I have read on other posts, gcc automatically links the object file with the default c libraries):

nasm -f elf64 -o test.o test.asm -D UNIX
gcc -o test test.o

但是,我收到以下重定位错误:

However, I get the following relocation error:

/usr/bin/x86_64-linux-gnu-ld:test.o:针对 制作PIE对象时,不能使用`.rodata'.重新编译 -fPIC

/usr/bin/x86_64-linux-gnu-ld: test.o: relocation R_X86_64_32S against `.rodata' can not be used when making a PIE object; recompile with -fPIC

/usr/bin/x86_64-linux-gnu-ld:最终链接失败:无法表示 输出部分

/usr/bin/x86_64-linux-gnu-ld: final link failed: Nonrepresentable section on output

collect2:错误:ld返回1个退出状态

collect2: error: ld returned 1 exit status

当我使用'-no-pic'选项进行编译以禁用与位置无关的代码时,它编译时没有错误,但是执行后,我遇到了没有输出的段错误. 当我重新编译32位代码(用32位替换64位寄存器)时,没有任何错误.这些命令是:

When I compile with the '-no-pic' option to disable positionally-independent code, it compiles without errors, but after execution I get a segfault with no output. When I recompile the code in 32-bit (replacing 64-bit registers with 32-bit), I get no error. The commands are:

nasm -f elf32 -o test.o test.asm -D UNIX
gcc -o test test.o -m32

我的问题是:为什么我不能在64位模式下使用PIC编译代码?

My question is: why can't I compile the code with PIC in 64bit mode?

PS: 这不是

PS: This is not a duplicate of Can't link a shared library from an x86-64 object from assembly because of PIC , since the error is different and the solution found in that post has nothing in relation with my problem. I have edited the error output to specify.

推荐答案

错误是我使用了错误的调用约定.在体系结构x86_64中,前两个参数分别在rdi和rsi中传递,而无需使用堆栈.另外,我需要在通话中添加"wrt ..plt".以下代码有效:

The mistake was that I was using the wrong calling convention. In architecture x86_64 the first two arguments are passed in rdi and rsi, respectively, without using the stack. Also, I needed to add "wrt ..plt" to the call. The following code works:

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的命令未更改.

The commands for nasm and gcc haven't changed.

这篇关于在64位模式下编译NASM代码时发生重定位错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆