汇编语言,hello world问题

8

我正在学习Linux上的汇编语言(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

这是一个简单的“Hello World”程序,可以在Linux上运行,并直接调用内核(显然)。 有人能解释一下到底发生了什么吗?我认为它读取了eax和ebx处理器寄存器以及ecx、edx数据中的整数,并在调用内核时定义了系统调用。如果是这样,当调用int 0x80时,不同的整数组合是否定义了不同的系统调用?

我对man手册不熟悉,但已阅读了所有相关的手册,在任何手册中都能找到哪些组合定义了哪些系统调用吗?

任何帮助都将不胜感激。逐行解释将非常神奇... -提前致谢 Jeremy

3个回答

8
当您调用int 0x80时,内核会查看eax寄存器的值来确定您想要调用的函数(这是“系统调用号”)。根据该数字,其余寄存器被解释为特定的含义。 sys_write调用期望寄存器设置如下:
  • eax 包含4
  • ebx 包含文件描述符
  • ecx 包含要写入数据的地址
  • edx 包含字节数
如需进一步了解,请参见Linux系统调用

非常感谢,这是我的猜测,尽管很有帮助...你能告诉我在哪里可以学到更多吗?这些系统调用整数在手册页中吗? - Jeremy
你需要深入挖掘Linux源代码头文件才能找到系统调用号。目前我手边没有Linux机器,所以无法告诉你确切的位置,但在内核源代码树中类似于include/asm/syscall.h - Greg Hewgill

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*bufcount。从%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

这是数据部分,它只描述了我们程序中使用的变量。


0

系统调用太多了,不可能为每个系统调用都有一个不同的汇编语言指令。

相反,您需要调用TRAP指令。eax的值决定将调用哪个系统调用。其他寄存器是系统调用的参数。

系统调用在内核中列出。


谢谢。在内核中,我应该在哪里查看系统调用? - Jeremy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接