我一直关注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)
答案 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
可以更好地理解差异。您可以使用ld
和gcc
来完成同样的事情,而不是使用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截图
答案 1 :(得分:5)
链接二进制文件时应添加-nostdlib
。
gcc -o hello hello.o -nostdlib