从0创建一个OS(十四) 裸内核框架
本节将创建一个没有内容的内核,并尝试启动该内核。
关键字: kernel,ELF format,makefile
目标: 创建一个简单的内核,并且使用一个bootsector来启动它。
内核
我们的C(语言)内核将会简单的在屏幕的左上角打印一个X
。
你可能注意到kernel.c中有一个奇怪的空函数dummy_test_entrypoint
,这是教程制作者故意安排的,因为这样的话,main函数就不会在kernel.c生成的kernel.o的地址0x0位置,这就迫使我们需要做一些额外操作,才能正确启动内核(我们这个例子里起始就是main)。这个问题先放在一旁,首先我们使用gcc将该kernel
编译成目标文件。
接下来是内核的入口程序。
对kernel_entry.asm进行编译,不过这次我们要编译为elf(Executable and Linkable Format)格式,这种格式既能链接又能执行,用途比较广。
链接器
将上面生成的2个目标文件(.o)文件链接成一个二进制文件,并且解决label的依赖问题,运行:
上面的这一串命令,能将kernel_entry.o和kernel.o放在kernel.bin的0x1000(.text)处,.text段通常用于放置内核代码,所以在启动内核时,会从镜像文件的0x1000处执行,首先执行kernel_entry.asm中的call main
,而call main又会jmp到kernel.c中的具体位置,而避免了kernel.c中dummy_test_entrypoint
的干扰。
需要注意的是,我们的内核放在0x1000处,而不是0x0处,所以在之后的bootsector中,需要指明需要启动的内核的位置。
bootsector(启动单元)
首先来看bootsector的代码。
从之前的教程中,我们知道bootsector占512个字节,上面的bootsect.asm做了以下几件事:
- 从BIOS读取启动驱动器号到BOOT_DRIVE位置
- 建立从0x9000开始的栈
- 打印MSG_REAL_MODE代表的信息
- 打印MSG_LOAD_KERNEL代表的信息
- 从BOOT_DRIVE指示的硬盘/软盘中读取内核到内存0x1000位置
- 进入保护模式并打印MSG_PROT_MODE代表的信息
- 调用内核所在位置,也就是0x1000
- 死循环
编译该源文件:
连接所有文件
到现在,我们拥有了bootsect.bin和kernel.bin,将这两个文件连接到一起,便形成了我们的第一个自制os镜像!
运行
现在就可以用qemu对该镜像进行运行了,如果运行时发生了硬盘载入错误,那么可能需要对qemu的启动选项加上-fda
,也就是floppy disk a的意思。
启动os:
注:译者没有编译qemu的i386版本,直接使用的x86_64版本,即:
运行结果:
Makefile
上面输入编译各个源文件的过程是不是很繁琐,别怕,其实有更加自动化的方法,即makefile的使用。
makefile的好处见我的另一篇博客,即Makefile Tutorial。
以后直接运行make即可启动我们的自制os.
__EOF__

本文链接:https://www.cnblogs.com/haiyonghao/p/14638330.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律