使用C程序编译ASM文件的命令

4

使用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

我已经在学习汇编语言了。问题是来自我的指令还是代码?

1
Linux的哪个版本?GCC的哪个版本?file executable的输出是什么?PS:同时,您可能可以将printf更改为printf wrt ..plt,并对exit执行类似操作。 - Jester
输出结果为:可执行文件: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 - Benjamin Sx
1
问题出在你的Linux默认设置为生成PIE/PIC 64位代码,这需要以稍微复杂的方式编写与C交互的汇编代码。如果你只是在学习汇编语言,也许应该考虑关闭PIE/PIC,并生成位置相关的二进制文件,甚至在最初时静态链接,以避免PIC和.so库的动态链接的复杂性。或者更加努力地学习这个主题,学习如何以期望的方式编写这些内容,这增加了一些复杂性,但它是实际使用的当前内容,所以不像学习DOS中断那样... - Ped7g
2
是的,这意味着您的系统默认启用了PIE。您也可以尝试使用“gcc -no-pie”命令。话虽如此,在我的系统上,我遇到了链接器错误,它无法生成可执行文件。 - Jester
1
你也可以在codereview上查看我的答案,我在那里努力争取正确的PIE二进制文件,从汇编中调用C库函数,我保留了各种阶段(包括不完全正确的阶段)以及注释我必须做出的更改:https://codereview.stackexchange.com/questions/181953/adding-integers-together/181964#181964 - Ped7g
1个回答

2

我通过使用你提供的 @Jester 的解决方案解决了这个问题:

gcc -no-pie -o 可执行文件名 main.o hello.o

感谢 Ped7g 的解释。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接