这个 x86 Hello World using 32-bit int 0x80 Linux system calls from _start 的解释是什么?
What is the explanation of this x86 Hello World using 32-bit int 0x80 Linux system calls from _start?
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
这是一个基本的 32 位 x86 Linux 汇编代码,用于在屏幕上打印 "Hello, World!"(标准输出)。用
构建+ 运行
nasm -felf -g -Fdwarf hello.asm
gcc -g -m32 -nostdlib -static -o hello hello.o
./hello
(编者注:或 gdb ./hello
调试/单步执行。这就是我们使用 nasm -g -Fdwarf
和 gcc -g
的原因。或者在 GDB 中使用 layout reg
进行反汇编+注册不依赖于调试符号的视图。请参阅 https://whosebug.com/tags/x86/info)
的底部
现在我想问一下这段代码在幕后是如何工作的。就像所有这些说明需要什么
_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
只是为了打印 "Hello, World!" 和声明
_start:
以上!是主函数吗?
和声明
int 0x80
为什么要使用它?你们能不能给我深入解释一下这个程序的基本工作原理。
在机器代码中,没有函数。至少,处理器对函数一无所知。程序员可以按照自己的喜好构造代码。 _start
是一种叫做 symbol 的东西,它只是程序中某个位置的名称。符号用于指代您还不知道其地址的位置。它们在链接期间被解析。符号 _start
用作 入口点 (参见 ),这是操作系统跳转以启动程序的地方。除非您通过其他方式指定入口点,否则每个程序都必须包含 _start
。您的程序使用的其他符号是 msg
,它由链接器解析为字符串 Hello, world!
所在的地址,len
是 msg
.[= 的长度。 40=]
程序的其余部分执行以下操作:
- 为系统调用
write(1, msg, len)
设置寄存器。 write
有存储在 eax
中的系统调用号 4,让操作系统知道你想要系统调用 4。这个系统调用将数据写入文件。提供的文件描述符编号为 1,代表标准输出。
- 使用
int [=20=]x80
执行系统调用。该指令会中断您的程序,操作系统会选择它并执行编号存储在 eax
中的函数。这就像调用 OS 内核的函数调用。调用约定与其他函数不同,with args passed in registers.
- 为系统调用
_exit(?)
设置寄存器。它的系统调用号是 1,进入 eax
。遗憾的是,代码忘记为 _exit
设置参数,该参数应为 0 以指示成功。相反,使用之前 ebx
中的任何内容,这似乎是 1.
- 使用
int [=20=]x80
执行系统调用。因为 _exit
结束程序,它不会 return。您的程序到此结束。
指令db
告诉汇编程序将以下数据放入我们当前所在的程序中。这会将字符串 Hello, world!
后跟一个换行符放入程序中,这样我们就可以告诉 write
系统调用写入该字符串。
行 len equ $ - msg
告诉汇编程序比 len
is the difference between $
(where we currently are) and msg
。这是定义的,因此我们可以传递给 write
我们要打印的文本的长度。
程序中分号 (;
) 后的所有内容都是 注释,被汇编程序忽略。
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
这是一个基本的 32 位 x86 Linux 汇编代码,用于在屏幕上打印 "Hello, World!"(标准输出)。用
构建+ 运行nasm -felf -g -Fdwarf hello.asm
gcc -g -m32 -nostdlib -static -o hello hello.o
./hello
(编者注:或 gdb ./hello
调试/单步执行。这就是我们使用 nasm -g -Fdwarf
和 gcc -g
的原因。或者在 GDB 中使用 layout reg
进行反汇编+注册不依赖于调试符号的视图。请参阅 https://whosebug.com/tags/x86/info)
现在我想问一下这段代码在幕后是如何工作的。就像所有这些说明需要什么
_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
只是为了打印 "Hello, World!" 和声明
_start:
以上!是主函数吗?
和声明
int 0x80
为什么要使用它?你们能不能给我深入解释一下这个程序的基本工作原理。
在机器代码中,没有函数。至少,处理器对函数一无所知。程序员可以按照自己的喜好构造代码。 程序的其余部分执行以下操作: 指令 行 程序中分号 (_start
是一种叫做 symbol 的东西,它只是程序中某个位置的名称。符号用于指代您还不知道其地址的位置。它们在链接期间被解析。符号 _start
用作 入口点 (参见 _start
。您的程序使用的其他符号是 msg
,它由链接器解析为字符串 Hello, world!
所在的地址,len
是 msg
.[= 的长度。 40=]
write(1, msg, len)
设置寄存器。 write
有存储在 eax
中的系统调用号 4,让操作系统知道你想要系统调用 4。这个系统调用将数据写入文件。提供的文件描述符编号为 1,代表标准输出。int [=20=]x80
执行系统调用。该指令会中断您的程序,操作系统会选择它并执行编号存储在 eax
中的函数。这就像调用 OS 内核的函数调用。调用约定与其他函数不同,with args passed in registers. _exit(?)
设置寄存器。它的系统调用号是 1,进入 eax
。遗憾的是,代码忘记为 _exit
设置参数,该参数应为 0 以指示成功。相反,使用之前 ebx
中的任何内容,这似乎是 1.int [=20=]x80
执行系统调用。因为 _exit
结束程序,它不会 return。您的程序到此结束。db
告诉汇编程序将以下数据放入我们当前所在的程序中。这会将字符串 Hello, world!
后跟一个换行符放入程序中,这样我们就可以告诉 write
系统调用写入该字符串。len equ $ - msg
告诉汇编程序比 len
is the difference between $
(where we currently are) and msg
。这是定义的,因此我们可以传递给 write
我们要打印的文本的长度。;
) 后的所有内容都是 注释,被汇编程序忽略。