Linux上的NASM Hello World:对“main”的未定义引用

时间:2014-11-21 00:19:02

标签: linux nasm

我一直关注this tutorial在Linux上进行程序集介绍。

section .text
global _start ;must be declared for linker (ld)

_start:
        mov edx,len     ;message length
        mov ecx,msg     ;message to write
        mov ebx,1       ;file descriptior
        mov eax,4       ;system call number (sys_write)
        int 0x80        ;call kernel

        mov eax,1       ;system call number (sys_exit)
        int 0x080       ;call kernel

section .data

msg db 'Hello, world!', 0xa     ;the string
len equ $ - msg                 ;length of the string

我编译时遇到了问题。我环顾四周,发现(在SO上)我应该像这样编译它:

nasm -f elf64 hello.asm
gcc -o hello hello.o

但是我一直从GCC得到这个错误:

hello.o: In function `_start':
hello.asm:(.text+0x0): multiple definition of `_start'
/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../x86_64-linux-gnu/crt1.o:(.text+0x0): first defined here
/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../x86_64-linux-gnu/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: error: ld returned 1 exit status

(注意:我在64位Intel i7上运行Debian Linux)

2 个答案:

答案 0 :(得分:6)

如果您要学习汇编,那么学习使用汇编程序nasm和链接器ld而不依赖gcc会更好。使用gcc没有任何问题,但它掩盖了您需要了解的部分链接过程。

在当前环境中学习程序集(通常构建在x86_64上,但使用用x86 32-bit汇编程序编写的示例),您必须学会构建适当的目标和语言({{1} })两者之间的差异。您的代码示例是syscall汇编程序。因此,32-bit编译字符串不正确:

nasm

nasm -f elf64 hello.asm 尝试编译-f elf64目标文件,但代码中的说明是64-bit条指令。 (它不会工作)

理解和使用32-bit可以更好地理解差异。您可以使用ldgcc来完成同样的事情,而不是使用nasm。例如(稍微修改代码):

ld

使用以下命令编译和构建:

msg db 0xa, 'Hello, StackOverflow!', 0xa, 0xa     ;the string

注意nasm -f elf -o hello-stack_32.o hello-stack_32.asm ld -m elf_i386 -o hello-stack_32 hello-stack_32.o 调用中使用-f elf 32-bit代码,使用nasm链接器选项创建兼容的可执行文件。< / p>

<强>输出:

-m elf_i386

如果你认真学习汇编程序,网上有很多很好的参考资料。其中最好的是The Art of Assembly。 (它主要是为Hello, StackOverflow! 8086编写的,但它提供的基础非常宝贵)。此外,查看以二进制文件创建的可执行文件可能会有所帮助。看看Binary Vi (BVI)。这是一个很好的工具。

bvi截图

enter image description here

答案 1 :(得分:5)

链接二进制文件时应添加-nostdlib

gcc -o hello hello.o -nostdlib