是否可以在不使用某种类型的汇编程序(最好不使用 __asm)的情况下在 C 或 C++ 中创建引导加载程序?我正在编写一个操作系统,并希望它完全用 C 和 C++ 编写。
4 回答
这完全取决于系统。在大多数情况下,答案是否定的——在开始运行 C 代码之前,您需要编写一些自定义程序集来设置 C 运行时。然而,也有一些例外。例如,ARM Cortex-M0可以在复位后直接运行 C 代码。
不过,大概您没有使用 M0,因此您将需要编写一些程序集。同样,它取决于系统/芯片,但您可能能够摆脱以下简单的事情:
reset_vector:
mov sp, SOME_KNOWN_GOOD_STACK_ADDRESS
call c_entry_point
它只是初始化堆栈指针并调用您的 C 程序的入口点。当然,这个简单的设置取决于你的芯片有一个支持它的复位向量/向量表,在调用复位向量之前初始化 RAM(或类似 RAM),等等。在早期的系统初始化中往往有很多“陷阱”。
准备好对您的编译器、汇编器和链接器文档变得非常友好 - 生成一个平面二进制文件,您可以将其作为第一阶段引导加载程序闪存下来,这本身就是一个很大的痛苦。
祝你好运!
假设这是针对 x86 的,如果您有正确的编译器选项并设法使用正确的链接器魔法使引导扇区的布局正确,您可能可以在 16 位模式下运行某些东西。
但是使用plain(或C++)不会走得太远C
:您需要真正快速地屏蔽中断,并且没有C
用于此的功能。需要组装。
对于大多数其他架构来说,这可能是相同的:C 和 C++ 根本没有内置这些功能(尽管某些编译器扩展可能会对您有所帮助)。
您尝试做的事情的一个很好的资源:OSDev。
不,至少在 x86 上,“纯”C 是不可能的……除了 x86 机器将启动到 16 位实模式(需要编译器生成 16 位而不是 32 位代码),您将需要能够屏蔽中断、设置段寄存器、将代码从硬件设备(即磁盘)加载到内存中、设置堆栈、访问 I/O 端口等,所有这些都在 x86 和其他平台需要访问 CPU 的寄存器和/或特定的汇编命令。
其次,对于 C++,如果您决定定义任何类,您将需要手动配置某种类型并运行“构造函数”以设置内存,以便您的初始类实际上可以存在于内存中的某个位置……您也赢了'不能抛出任何异常。基本上,您将尝试使用的任何 C++ 特定功能都是无用的,因为这些更高级别的数据抽象需要操作系统运行时本身的适当支持,必须使用汇编和 C 代码的组合进行设置。
假设 x86 保护模式:
我相信答案是否定的,因为您需要执行以下操作才能切换到保护模式:
lgdt[GDTR]
jmp CODESEL:FLUSH
FLUSH:
...
我认为没有办法jmp
在纯 C/C++ 中执行指令,尽管我可能是错的。(我绝不是这里的专家;我只是引用我不久前制作的引导加载程序。)