我一直在关注本教程,介绍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)
如果您要学习汇编,那么学习使用汇编程序nasm
和链接器ld
而不依赖它会更好gcc
.使用没有任何问题gcc
,但它掩盖了您需要了解的部分链接过程.
在当前环境中学习汇编(通常建立x86_64
在x86 32-bit
汇编器上但使用汇编程序编写的示例),您必须学会构建适当的目标和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
for 32-bit
代码nasm
和-m elf_i386
链接器选项来创建兼容的可执行文件.
输出:
Hello, StackOverflow!
如果您认真学习汇编程序,那么Web上有很多很好的参考资料.其中最好的是大会艺术.(它主要是为8086
和写的x86
,但它提供的基础非常宝贵).此外,查看以二进制文件创建的可执行文件可能会有所帮助.快来看看Binary Vi(BVI)吧.这是一个很好的工具.
bvi截图
-nostdlib
链接二进制文件时应添加。
gcc -o hello hello.o -nostdlib