【发布时间】:2018-08-09 21:54:46
【问题描述】:
使用 à 64 Linux 系统并使用 NASM。
我正在尝试将我的 ASM (hello.asm) 文件与 C 文件 (main.c) 链接并编译为执行文件。
我创建了一个 ASM 文件,它使用 printHello 函数使用 printf 打印“Hello”。
extern printf, exit
section .data
format db "Hello", 10, 0
section .text
global printHello
printHello:
sub rsp, 8
mov rsi, 0x12345677
mov rdi, format
xor rax, rax
call printf
mov rdi, 0
call exit
我创建了一个简单的 main.c 并调用我的函数“printHello”来打印“Hello”
#include <stdio.h>
void printHello();
int main()
{
printHello();
}
我的编译命令:
$ nasm -f elf64 hello.asm
$ gcc -c main.c
$ gcc -o executable main.o hello.o
$ ./executable
它会打印出来:
./executable: Symbol `printf' causes overflow in R_X86_64_PC32 relocation
./executable: Symbol `exit' causes overflow in R_X86_64_PC32 relocation
[1] 6011 segmentation fault ./executable
我已经在学习 ASM。问题出在我的命令还是我的代码?
【问题讨论】:
-
什么版本的linux什么版本的gcc,
file executable的输出是什么? PS:与此同时,您可能可以将printf更改为printf wrt ..plt,exit也是如此。 -
输出可执行:ELF 64 位 LSB 共享对象,x86-64,版本 1 (SYSV),动态链接,解释器 /lib64/ld-linux-x86-64.so.2 ,对于 GNU/Linux 2.6.32,BuildID[sha1]=f1ef9d13c6162ebb2c4085402decc5735083b483,未剥离我使用:gcc (Debian 6.4.0-2) 6.4.0 20170724 发行版是:Linux benjamin-PC 4.14.0-deepin2-amd64 # 1 SMP PREEMPT Deepin 4.14.12-2 (2018-01-06) x86_64 GNU/Linux
-
问题出在您的 linux 默认设置为生成 PIE/PIC 64b 代码,这需要以更复杂的方式编写与 C 互操作的程序集。如果您只是在学习汇编,可能会重新考虑关闭 PIE/PIC,并生成与位置相关的二进制文件,甚至可能一开始是静态链接的,以避免 PIC 的复杂性以及与 .so 库的动态链接。或者只是更努力地学习这个主题,如何以预期的方式编写这些,它有点增加复杂性,但它是实际使用的当前东西,所以它不像学习DOS中断......
-
是的,这意味着您使用的是默认使用 PIE 的系统。你也可以试试
gcc -no-pie。也就是说,在我的系统上,我收到一个链接器错误,它不会生成可执行文件。 -
您还可以在 codereview 上查看我的答案,我在其中努力争取正确的 PIE 二进制文件,从 asm 调用 Clib 函数,我保持了各个阶段(包括不完全正确的阶段)以及 cmets 发生了什么变化我不得不这样做:codereview.stackexchange.com/questions/181953/…