完全使用C语言编写操作系统是否可行?

18

是否可能完全使用C语言编写操作系统?

所谓“完全”,包括引导加载程序在内的所有内容,但不包括BIOS / UEFI。


1
当你说“操作系统”时,它取决于你实际的意思。我在一本与ARM相关的书中读到,对于一些Cortex-M处理器(非常有限,用于MCU),这是可能的,但很可能在许多其他核心上,你将被迫使用至少一点汇编语言进行一些基本配置。 - user35443
3个回答

20
传统的回答“你能用C语言完全编写一个程序吗?”的答案是“不行”。原因是C程序无法设置自己的堆栈。
几乎每种处理器都有至少一个寄存器指向堆栈中当前的地址(通常称为“帧指针”),有时还会有第二个寄存器(通常称为“堆栈指针”)需要指向堆栈中下一个未使用的地址。没有任何表达式或语句可以在语言本身中设置堆栈指针或帧指针的绝对值。(过程调用和返回可以添加和减去堆栈指针,但没有办法将其初始化为已知值。)
Posix定义了一组函数setcontext、getcontext、makecontext和swapcontext(几乎总是部分地用汇编语言编写),这些函数将使您能够读取和写入堆栈和帧指针。
不幸的是,setcontext函数系列并没有被广泛实现。

7
理论上是可以的,但并非所有情况都适用。
对于引导程序和实模式部分,你可以找到一些旧的16位编译器(如Turbo C),告诉它输出纯二进制文件,并使用它来编写所有这些内容。或者,你也可以在GCC中加入asm(".code16gcc"),但我不建议这样做,因为GCC无法直接输出16位代码,结果汇编程序可能会超过512字节。
对于其他内容,消除汇编的使用是不可能的。是的,你可以将所有汇编行隐藏在内联函数中(IN\OUT,CRx寄存器等),但对于其他东西,如中断,你将被迫使用汇编语言。
编辑:
现在GCC(4.9.0)支持-m16选项,可启用16位代码生成,因此可以进一步减少汇编的使用,例如引导程序/引导加载程序(尽管某些位仍需要汇编语言)。

7
这取决于你所说的C是什么意思。
如果你指的是ISO定义的标准C编程语言,仅依赖于已定义的行为,并且你正在考虑运行在硬件上的常见操作系统,那么不,用C编写实用的操作系统是不可能的,因为C缺少许多设施,特别是访问硬件和操作单独程序的能力。
可以编写由C程序组成并仅通过C设施提供输入/输出的操作系统,但这不是在实际硬件上运行的操作系统。您可以以这种方式为机器及其操作系统编写模拟器。
如果允许实现特定的行为,则答案显然是肯定的,因为允许实现添加任何它们认为合适的扩展。绝对可以有一个C实现,其中operating_system();是实现操作系统的程序的源代码。
如果你的意思是是否可能使用典型的C编译器构建一个操作系统(包括运行时环境)而不使用任何汇编语言,那么通常的答案是否定的,因为C编译器通常缺少一些仅对操作系统编写者感兴趣的基本功能,例如执行上下文切换和建立堆栈所需的内容。但这不是绝对的规则。如果愿意,它取决于运行时环境的哪些部分来自编译器编写者,哪些部分来自操作系统编写者。

在相当数量的平台上,编写操作系统而不编写一行汇编语言是可能的(仅使用编译器附带的库),但通常最好至少编写一点机器代码。例如,在许多平台上,可以定义一个jmp_buff和一个char[]的联合体,并将程序入口点单独写入其中的字符,然后执行longjmp以跳转到该地址,而不使用任何堆栈[注意,memcpy甚至结构分配可能会是子例程调用,因此不会起到任何好处]。 - supercat
使用少量的内联汇编来设置堆栈可能比逐字节创建jmp_buff更清晰(并且可能更具可移植性),但是像jmp_buff这样的技术可以使在许多实现中,无需编译除C代码以外的任何内容即可设置系统。 - supercat

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