为什么操作系统的某些部分必须用汇编语言编写?

7
我的迷你操作系统的调度程序是用汇编语言编写的,我想知道为什么。我发现指令eret无法由C编译器生成,这是否适用于除Nios和x86以及MIPS体系结构之外的其他平台?由于我相信操作系统的部分始终是用汇编语言编写的,因此我正在寻找为什么系统程序员必须了解汇编语言才能编写操作系统。是否存在C编译器的内置限制,无法生成某些汇编指令,例如返回程序到中断后执行的eret指令?

1
这不是“真正”的事实。在C语言中完全有做到的选项,但可能会很棘手。即使内联汇编模块不支持某个指令,通常也可以使用可执行字符串。 - Brian Knoblauch
4个回答

4
通常情况下,有以下三个原因:
  1. 因为特定类型的代码无法用C语言编写。我认为eret是一种“从异常返回”的指令,因此没有C语言等价物(因为硬件异常如页面故障、除零或类似问题不属于C/C++风格的异常)。另一个例子可能是在任务切换时将寄存器保存到堆栈中,并将堆栈指针保存到任务控制块中。C语言无法做到这一点,因为没有直接访问堆栈指针的方式。

  2. 因为编译器生成的代码不如聪明人编写的汇编代码好。某些专业操作可能很难用C语言编写 - 编译器可能无法生成非常好的代码,或者代码变得非常复杂,以实现在汇编语言中简单的操作。

  3. C语言代码的启动需要用汇编语言编写,因为在运行实际C语言代码之前,需要设置C程序所需的某些内容。例如配置堆栈指针和其他一些寄存器。


3

没错,就是这样。有些指令用C语言无法生成。对于大多数指令集(如x86、arm和mips),操作系统通常需要一些汇编指令来完成某些任务。虽然C编译器可以让你使用内联汇编来添加指令,但语言本身不能处理每个指令集的细节并加以考虑。一些编译器会添加特定于编译器的内容,例如使用中断型返回函数。在需要时编写汇编代码比自定义语言或编译器要容易得多,因此实际上没有这方面的需求。


3

C语言仅能表达其规定表达的内容:基本算术运算、将值赋给变量、跳转和函数调用。对象可使用静态、自动(局部)或动态(malloc)存储期分配。如果要超出此概念范围,你需要除纯C之外的其他东西。

C语言可以任意扩展,许多平台定义了类似于在特定地址定义函数或变量的语法。

但是CPU硬件关心很多细节,例如标志寄存器的值。切换线程的调度程序部分需要能够在执行任何操作之前将所有寄存器保存到内存中,因为覆盖任何寄存器都会丢失被中断的线程中的重要数据。

唯一能够在C中编写这样的代码的方式是编译器提供生成精密调整的汇编代码的C函数。然后,你基本上回到了起点,因为重要的细节仍然处于汇编代码的级别。

拥有多个微控制器产品系列的供应商有时会尽力在最低级别上允许C源代码兼容性,以使其客户能够移植代码(或者相反,当他们需要切换平台时防止他们去找另一个供应商)。但是,在调用生成特定指令(称为内部函数)的伪函数时,C和汇编之间的区别在某种程度上变得模糊。


1

在C语言中无法完成或者如果可以完成,最好使用汇编语言来完成的一些任务,因为这样做更加直观/可维护,包括:

  • 执行从异常返回和从中断返回的指令。
  • 读取和写入特殊处理器寄存器(控制处理器状态、内存映射、缓存配置、异常管理等)。
  • 对连接到硬件设备而不是内存的特殊地址进行原子读写操作。
  • 根据上述描述,对特定大小或特性的特殊地址执行装载和存储指令。(例如,写入某个设备可能需要仅使用store-16-bits指令而不是常规的store-32-bits指令。)
  • 执行内存屏障或排序、缓存控制以及刷新内存映射的指令。

通常,C语言主要设计用于计算(读取输入、计算、输出),而不是用于控制机器(与机器中的所有控件和设备交互)。


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