当需要系统调用时,Linux 内核是如何部分用汇编语言编写的?

当需要系统调用时,Linux 内核是如何部分用汇编语言编写的?

内核是否只是不使用系统调用,或者程序集是在新系统上之前组装的?我可能需要一些有关汇编程序的更多信息,但我只是感到困惑,如果 mov [register] 等指令是系统调用,那么如何在不必引用依赖操作系统的内核的情况下使用它?

例如,假设我正在使用 GNU/Linux 发行版制作一个汇编程序并使用它的系统调用。如果 Linux 没有内核可供系统调用,那么它本身如何使用汇编?

答案1

mov [register]类似的不是系统调用,而是汇编指令。

系统调用基本上是一个用户空间程序调用内核中的特定子例程,使用处理器内置并由内核设置的机制,该机制允许被调用的子例程具有比常规用户空间更高的特权级别程序代码。

汇编指令基本上是机器代码实际字节的人性化表示。机器代码不会被解释或编译,而是使用处理器微代码在处理器内部实现,或者使用大量逻辑门直接在硬件级别实现。

汇编语言中的单个系统调用通常是多行代码。首先,系统调用的参数被加载到适当的处理器寄存器和/或堆栈中,然后使用诸如int 0x80或 之类的特殊指令syscall来实际进行系统调用。

在32位x86架构中,int 0x80用作系统调用指令。内核为处理器准备了一个软件中断处理例程表。该表不能由常规用户空间代码直接访问,但使用int用户空间代码可以触发该表指向的例程之一。int 0x80只是告诉处理器切换到内核模式并跳转到地址位于该表的槽 #128 中的例程。该例程是 Linux 32 位 x86 架构的系统调用接口:它检查指定的参数,识别哪个进程进行了调用,然后跳转到适当的子例程。

在 x86 架构的 64 位版本中,有一条专用syscall指令用于相同目的。其实现在 32 位 x86 架构也有它,但要么是 Linus Torvalds 设计 32 位 Linux 系统调用约定时它还不存在,要么是该指令在某些处理器型号中存在硬件 bug,所以没有习惯了。但由于所有 64 位 x86 处理器都有该syscall指令并且它确实有效,因此使用它。

相关内容