section .text
global _start ;must be declared for using gcc
_start: ;tell linker entry point
mov edx, len ;message length
mov ecx, msg ;message to write
mov ebx, 1 ;file descriptor (stdout)
mov eax, 4 ;system call number (sys_write)
int 0x80 ;call kernel
mov eax, 1 ;system call number (sys_exit)
int 0x80 ;call kernel
section .data
msg db 'Hello, world!',0xa ;our dear string
len equ $ - msg ;length of our dear string
This is a basic 32-bit x86 Linux assembly code to print "Hello, World!" on the screen (standard output). Build + run it with
nasm -felf -g -Fdwarf hello.asm
gcc -g -m32 -nostdlib -static -o hello hello.o
./hello
(Editor's note: or gdb ./hello
to debug / single-step it. That's why we used nasm -g -Fdwarf
and gcc -g
. Or use layout reg
inside GDB for disassembly+register view that doesn't depend on debug symbols. See the bottom of https://stackoverflow.com/tags/x86/info)
Now I want to ask about how is this code working behind the scenes. Like what is the need for all these instructions
_start: ;tell linker entry point
mov edx, len ;message length
mov ecx, msg ;message to write
mov ebx, 1 ;file descriptor (stdout)
mov eax, 4 ;system call number (sys_write)
int 0x80 ;call kernel
mov eax, 1 ;system call number (sys_exit)
int 0x80 ;call kernel
just to print "Hello, World!" and the statement
_start:
above! Is it the main function?
and the statement
int 0x80
why is it used at all? Can you guys give me a deep explaination of the basic working of this program.
答案 0 :(得分:10)
在机器代码中,没有功能。至少,处理器对功能一无所知。程序员可以根据自己的喜好构建代码。 _start
是一种称为符号的东西,它只是程序中某个位置的名称。符号用于指代您还不知道地址的位置。它们在链接期间得到解决。符号_start
用作入口点(参见this answer),这是操作系统跳转以启动程序的位置。除非您通过其他方式指定入口点,否则每个程序都必须包含_start
。程序使用的其他符号为msg
,链接器将其解析为字符串Hello, world!
所在的地址和len
的长度msg
。
该计划的其余部分做了以下事情:
write(1, msg, len)
的寄存器。 write
具有系统调用号4,存储在eax
中以让操作系统知道您想要系统调用4.此系统调用将数据写入文件。提供的文件描述符编号为1,表示标准输出。int $0x80
执行系统调用。该指令会中断您的程序,操作系统会选择该程序并执行其编号存储在eax
中的功能。这就像调用OS内核的函数调用。调用约定与其他函数with args passed in registers. _exit(?)
的寄存器。其系统呼叫号码为1,进入eax
。遗憾的是,代码忘记设置_exit
的参数,该参数应该为0表示成功。相反,之前使用的ebx
中的任何内容都会被使用,这似乎是1。int $0x80
执行系统调用。因为_exit
结束程序,所以它不会返回。你的课程在这里结束。指令db
告诉汇编程序将以下数据放入我们当前所在的程序中。这会将字符串Hello, world!
后跟换行符放入程序中,这样我们就可以告诉write
系统调用写入该字符串。
行len equ $ - msg
告诉汇编程序而不是len
is the difference between $
(where we currently are) and msg
。这是定义的,因此我们可以传递给write
我们想要打印的文本多长时间。
程序中的分号(;
)之后的所有内容都是汇编程序忽略的注释。