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

时间:2013-08-11 23:52:14

标签: c assembly operating-system interrupt nios

我的迷你操作系统的调度程序是用汇编编写的,我想知道为什么。我发现C编译器无法生成指令eret,这个可以推广到除Nios以及x86和/或MIPS架构之外的其他平台的东西吗?因为我认为os的一部分总是用汇编语言编写而我正在寻找系统程序员为什么必须知道汇编才能编写操作系统。是否存在C编译器的内置限制,无法生成某些汇编指令,如eret,它将程序返回到中断后正在执行的操作?

4 个答案:

答案 0 :(得分:3)

是的,就是这样。有些指令无法使用C语言生成。并且操作系统通常需要一个或一些指令,因此需要一些装配。对于几乎任何指令集,x86,arm,mips等都是如此。 C编译器允许您在内联汇编中执行干扰指令,但语言本身无法真正处理每个指令集的细微差别并尝试对其进行说明。一些编译器会添加编译器特定的东西,例如使用返回的中断风格返回函数。在需要的地方编写程序集要比定制语言或编译器容易得多,因此实际上没有需求。

答案 1 :(得分:3)

通用答案有以下三个原因之一:

  1. 因为这个特定类型的代码不能用C语言编写。我认为eret是一个“从异常返回”指令,因此没有C等价于此(因为硬件异常,如页面错误,除以零或类似不是C / C ++样式异常)。另一个例子可能是在任务切换时将寄存器保存到堆栈中,并将堆栈指针保存到任务控制块中。 C代码不能这样做,因为没有直接访问堆栈指针。

  2. 因为编译器不会像聪明的编写汇编程序那样产生好的代码。一些专门的操作可能难以用C编写 - 编译器可能无法生成非常好的代码,或者代码变得非常复杂以实现汇编程序中的简单操作。

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

答案 2 :(得分:3)

C语言表达了它指定要表达的内容:基本算术运算,赋值给变量,分支和函数调用。可以使用static,自动(本地)或动态(malloc)存储持续时间来分配对象。如果你想要这个概念范围以外的东西,你需要的不是纯粹的C.

C语言可以任意扩展,许多平台定义语法,例如在特定地址定义函数或变量。

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

能够在C中编写这样的东西的唯一方法是编译器提供一个生成精细调整的程序集的C函数。然后你基本上回到了方阵1,因为重要的细节仍然是汇编代码的水平。

拥有多个微控制器产品线的供应商有时会尽量允许C源兼容,即使在最低级别也是如此,以允许其客户端口代码(或相反,以防止他们在需要时转到其他供应商交换平台)。但是,当你调用生成特定指令的伪函数(称为 intrinsics )时,C和汇编之间的区别会在某一点上模糊。

答案 3 :(得分:1)

有些事情在C中无法完成,或者如果可以做到的话,最好在汇编中完成,因为它们更简单和/或可维护,包括:

  • 执行异常返回和中断返回指令。
  • 读取和写入特殊处理器寄存器(控制处理器状态,内存映射,缓存配置,异常管理等)。
  • 对与硬件设备而非内存连接的特殊地址执行原子读写操作。
  • 如上所述,对特殊地址执行特定大小或特征的加载和存储指令。 (例如,写入某些器件可能只需要使用存储16位指令而不是常规存储32位指令。)
  • 执行内存屏障或排序,缓存控制和刷新内存映射的说明。

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