将Linux x86-64程序集hello world程序与ld链接失败

时间:2013-03-17 21:05:44

标签: linux assembly 64-bit x86-64 nasm

我最近在linux上玩x86 64位汇编,在编译了一个看似简单的程序之后,我不得不摸不着头脑:P

虽然我编译并链接它但不会抛出任何错误并生成一个linux ELF 当我尝试运行它时,我得到:

.:[ h4unt3r@sp3ctr4l-h0st asm ]:.
#(0)> ./hello 
bash: ./hello: No such file or directory

我认为它生成了一个无效的ELF文件,这就是为什么它报告你好即使它不存在。不知道为什么 - 我可能会继续玩它,只是好奇如果这可以通过简单的方法解决^ _ ^

这是我的编译/链接命令行:

nasm -f elf64 hello.s -g
ld -o hello hello.o -lc

以下是代码:

section .data
    msg: db "Hello, world!",0xa,0

section .text
    extern printf
    global main

main:
    push rbp
    mov rbp, rsp

    mov rdi, msg
    xor rax, rax
    call printf
    xor rax, rax

    pop rbp
    ret

编辑 - 我不想使用gcc:)

3 个答案:

答案 0 :(得分:4)

我正在运行32位硬件,无法测试64位内容。我在32位代码中看到了这个“没有这样的文件”错误。默认情况下,ld使用“/lib/ld-linux.so.1” - 您可以在可执行文件中以纯文本形式查看此字符串。这是不存在的文件(显然“你好”就在那里!)。解决方案是告诉ld -I/lib/ld-linux.so.2。我怀疑类似的解决方案适用于64位,但我不知道你需要什么“解释器”或“动态链接器”。尝试在可执行文件中查找类似的字符串,并在libs中查找类似的.so。你不应该“需要”使用gcc ......但是gcc知道在哪里可以找到这些东西!可能更容易使用它。看到一个令人困惑的错误,不是吗?

(我希望你的入口点为_start,而不是main,如果你打算这样做。你将无法ret从这里开始 - 使用sys_exit或exit()。)

我不熟悉nrz提到的关于“符号表0”的错误。当然不是故意改变纳斯姆! Nasm开发人员在http://www.nasm.us或其周围闲逛,很高兴听到那里的反馈和错误报告。 (好吧,或许对bug报告并不“高兴”。)我会看看能不能找到任何东西......

FWIW,Nasm默认只用-g开关“刺”调试信息。要启用“矮人”调试信息,-F dwarf ...假设工作得更好......

答案 1 :(得分:3)

首先,要使用printf,您需要与gcc而不是ld建立关联:

gcc -o hello hello.o

然后,另一个问题可能与我遇到的情况相同。我不确定这是NASM中的错误还是预期的变化:

user@computer:~/code/asm$ nasm -f elf64 hello.asm -g; gcc -o hello hello.o
/usr/bin/ld: error: relocation section 9 uses unexpected symbol table 0
collect2: error: ld returned 1 exit status

我已经解决了这个问题,转移到YASM,并以这种方式进行汇编和链接:

yasm -f elf64 hello.s -g dwarf2
gcc -o hello hello.o

生成具有预期输出的可执行文件:

./hello
Hello, world!

答案 2 :(得分:2)

稍微修改一下代码。

section .data
        msg:    db "Hello, world!",0xa,0
section .text
        extern  printf
        global main
main:
        push    rbp
        mov     rbp, rsp
        mov     rdi,msg
        xor     rax,rax
        call    printf
        xor     rax,rax
        pop     rbp

        mov     rax,60  ; use exit syscall
        mov     rdi,0   ; error code 0
        syscall         ; call kernel

并使用

ld -e main hello.o -o hello -lc --dynamic-linker /lib64/ld-linux-x86-64.so.2