我在Linux上学习asm(noobuntu 10.04) 我收到了以下代码:http://asm.sourceforge.net/intro/hello.html
section .text
global _start ;must be declared for linker (ld)
_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
这是一个简单的问候世界。 Linux +上的运行直接调用内核(显然)。 有谁能解释一下这里到底发生了什么?我认为它读取了eax&中的整数。 ebx处理器寄存器& ecx,edx数据和定义调用内核时的系统调用。如果是这样,当调用int 0x80时,不同的整数组合是否定义了不同的系统调用?
我对手册页不太满意,但已阅读我能找到的每一个相关内容,是否有任何手册页告诉我哪些组合定义了什么系统调用?
感谢任何帮助。一行一行的解释会很棒...... -提前致谢 杰里米
答案 0 :(得分:7)
当您调用int 0x80
时,内核会查看eax
寄存器的值以确定您要调用的函数(这是“系统调用号”)。根据该数字,其余的寄存器被解释为具体的事物。 sys_write
调用期望寄存器设置如下:
eax
包含4 ebx
包含文件描述符ecx
包含要写入的数据的地址edx
包含字节数有关更多详细信息,请参阅Linux System Calls。
答案 1 :(得分:2)
section .text
global _start ;must be declared for linker (ld)
这只是标题材料,汇编程序的“文本”部分只是机器指令(与数据,只读数据和BSS部分相对)。 global
行类似于_start
函数是“公开”。
_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
从评论中我们知道我们正在查看sys_write
函数,因此我们可以man 2 write
获取详细信息。 C原型提供以下参数:fd
,*buf
和count
。从%ebx开始,我们看到那些匹配(%ebx = fd,%ecx =要写入的字符串,%edx =字符串的长度)。然后,由于我们是一个用户进程,我们必须要求内核执行输出。这是通过SYSCALL接口完成的,write()
函数(显然)给出了数字4. INT 0x80
是一个调用Linux内核的SYSCALL例程的软件中断。
您可以在Linux头文件中找到所有系统调用的实际数量(假设您已安装它们)。在我的系统上,我检查了/usr/include/sys/syscall.h
,导致/usr/include/asm/unistd.h
,然后检查了/usr/include/asm-i386/unistd.h
。在哪里(我看),#define __NR_write 4
。
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
与前一段的最后两行一样,这只是加载系统调用ID并执行软件中断以退出程序(删除它的内存映射和清理)。
section .data
msg db 'Hello, world!',0xa ;our dear string
len equ $ - msg ;length of our dear string
这是数据部分,它只描述了我们在程序中使用的变量。
答案 2 :(得分:0)
系统调用太多,每个系统调用都有不同的汇编语言指令。
而是调用TRAP指令。 eax的值确定将调用哪个系统调用。其他寄存器是系统调用的参数。
系统调用列在内核中。