02 | 几行汇编几行C:实现一个最简单的内核
LMOS
该思维导图由 AI 生成,仅供参考
你好,我是 LMOS。
我们知道,在学习许多编程语言一开始的时候,都有一段用其语言编写的经典程序——Hello World。这不过是某一操作系统平台之上的应用程序,却心高气傲地问候世界。
而我们学习操作系统的时候,那么也不妨撇开其它现有的操作系统,基于硬件,写一个最小的操作系统——Hello OS,先练练手、热热身,直观感受一下。
请注意,这节课主要是演示思路,不要求你马上动手实现。详细的环境安装、配置我们到第十节课再详细展开。有兴趣上手的同学,可以参考留言区置顶的实验笔记探索。
PC 机的引导流程
看标题就知道,写操作系统要用汇编和 C 语言,尽管这个 Hello OS 很小,但也要用到两种编程语言。其实,现有的商业操作系统都是用这两种语言开发出来的。
先不用害怕,Hello OS 的代码量很少。
其实,我们也不打算从 PC 的引导程序开始写起,原因是目前我们的知识储备还不够,所以先借用一下 GRUB 引导程序,只要我们的 PC 机上安装了 Ubuntu Linux 操作系统,GRUB 就已经存在了。这会大大降低我们开始的难度,也不至于打消你的热情。
那在写 Hello OS 之前,我们先要搞清楚 Hello OS 的引导流程,如下图所示:
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
- 深入了解
- 翻译
- 解释
- 总结
本文详细介绍了如何使用汇编和C语言编写一个最简单的操作系统内核Hello OS。作者首先解释了PC机的引导流程,然后展示了Hello OS的引导汇编代码,包括GRUB的多引导协议头和CPU工作模式的初始化。接着,作者介绍了Hello OS的主函数,展示了用C语言编写的main函数,并提到了对屏幕进行字符输出的操作。最后,作者展示了如何控制计算机屏幕,使用VESA标准和显卡的字符模式进行屏幕输出,并给出了相应的代码示例。整篇文章以实际代码和技术细节为主,展示了如何从头开始编写一个简单的操作系统内核。读者可以通过本文了解到操作系统内核的基本编写流程和技术要点。文章还介绍了make工具的使用和编译过程,以及如何安装Hello OS。通过本文,读者可以快速了解操作系统内核的基本编写流程和相关工具的使用,为进一步学习和实践打下基础。
仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《操作系统实战 45 讲》,新⼈⾸单¥68
《操作系统实战 45 讲》,新⼈⾸单¥68
立即购买
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
登录 后留言
全部留言(276)
- 最新
- 精选
- Geek_b3ad17置顶lesson2 运行在bochs 虚拟机 https://gitee.com/jiawenshi/myos
编辑回复: 感谢你分享~
2023-10-17归属地:江西51 - 孟祥毅🇨🇳Xiangyi置顶P.S. 不想每次改完程序重启看效果的同学可以考虑用qemu来boot kernel,之前有两个同学给了solution,但是好像一个制作引导镜像的步骤有点问题,另一个没用grub,用的自定义的bootloader。我follow老师的课程做了个grub版的(包括怎么制作引导镜像)放在了github上 https://github.com/xymeng16/helloOS,不想深究直接make qemu-grub就可以用,想深究的话脚本也都在repo里面~之后我会把联合gdb调试的脚本也加进去,方便找bug...
作者回复: 666666
2021-10-2124 - royalfarmer置顶也来交个作业 既然是从0到1,建议像我一样的小白用户,全部代码自己动手写一遍,哪怕很多细节不懂,但从整体上会有一个感性认识,有了框架,后面慢慢补充相关知识,这样学的会更加牢固。 那些折腾虚拟机直接copy老师的代码,是高手玩的,需要有足够的基本功才玩的转。小白一定要先练好自己的基本功,手动抄代码是练基本功非常好的方法,看一遍和写一遍感觉完全不一样。 操作系统算是比较难的了,开始学习之前,自己得先有些基本的知识储备。 首先,要对Linux有基本概念,会在物理机上装Linux,知道Linux常用的命令,知道怎么在Linux里安装程序。 说下我的作业过程: 一、个人PC上直接装的Linux,版本是ubuntu。 二、在自己的家目录下新建一个HelloOS文件夹,在里面新建5个文件,文件内容照着老师给的源码全部手抄一遍,一定要仔细,一个字母都不能差: entry.asm (汇编文件,进行一些针对电脑硬件的操作) main.c (我们自己这个操作系统的主函数源代码,里面就一个printf函数,功能是我们这个操作系统运行时显示的那句话) vgastr.c (printf函数的具体实现代码,需要调用到显卡显存) vgastr.h (主函数的头文件) Makefile (make命令编译时遵照的格式文件) install.md (确切的说,这是一段代码,有没有这个文件都行,把代码补充到/boot/grub/grub.cfg 文件的末尾,目的是更新grub 引导程序的配置文件,让grub能找到我们的helloOS,评论里出现最多的找不到文件的问题,基本都是这段代码没写对,更确切说,就是那一句 multiboot2 /boot 或改为 multiboot2 / ) 三、途中可能会遇到几个问题 1 提示没有装nasm, 无法编译汇编文件 .asm,解决方法,直接根据系统提示,输入命令安装该程序 2 提示make不是命令,无法编译,解决方法,直接根据系统提示,输入命令安装该程序 3 源代码抄写错误,都会有提示具体在哪个文件哪一行,写错字符,缺少横杠,字符大小写等(我甚至都没有用编辑器,抄起来确实比较痛苦,但完成后的成就感也更大) 四、补充一个细节,确认完挂载点后,记得把helloOS.bin文件放到挂载点的目录下,要不然,即使grub.cfg配置写对了,仍然会提示找不到文件。 五、有个小问题没搞明白,为啥我生成的helloOS.bin 文件的首字母是小写的?我看别人的截图都是大写的,不过这个貌似不影响系统启动。
作者回复: 最后一个问题 看一下代码 可改的
2021-09-25318 - De_sword置顶补充一点对于内核文件路径设定的方案。 尝试过@Vic, @陈诚 , 的方案。 进入过grub模式查看硬盘下的路径,但是仍然遇到error : file '/boot/HelloOS.bin' not found的问题。 因此,我这边参考了grub.cfg里面,“Ubuntu”的设置: menuentry 'Ubuntu' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-simple-c2b35b75-3fa4-4021-b628-65742342045e' { insmod gzio insmod part_msdos insmod ext2 set root='hd0,msdos1' initrd /initrd.img-4.4.0-57-generic } 可以发现,默认载入时就已经以/boot为根目录, 因此,我也照葫芦画瓢,没有额外设定/boot目录。 重新启动,就可以成功运行HelloOS内核了。
作者回复: 是的 要看看你的boot目录的挂载路径
2021-09-103 - 不安好心置顶有一个疑问,汇编代码那里: ;重新加载 GDTlgdt [GDT_PTR] jmp dword 0x8 :_32bits_mode 这里明明没有开启保护模式,为什么能这样跳转,而且经验证,也确实使用了gdt。 但是实模式不是cs << 4 + offset进行寻址吗?
作者回复: 因为GRUB已经在保护模式下了
2021-08-252 - 喜欢吃鱼置顶实验注意几个关键问题。 - 将作者提供的代码git到本地; - 安装nasm、gcc等工具,否则make不通过。随后执行“make -f Makefile”,得到HelloOs.bin; - 在/boot/grub/grub.cfg中添加如下引导内容: ```shell menuentry 'HelloOS' { insmod part_msdos #GRUB加载分区模块识别分区 insmod ext2 #GRUB加载ext文件系统模块识别ext文件系统 set root='hd0,msdos1' #注意boot目录挂载的分区,这是我机器上的情况 multiboot2 /boot/HelloOS.bin #GRUB以multiboot2协议加载HelloOS.bin boot #GRUB启动HelloOS.bin } ``` - ```she #其中set root='hd0,msdos1'根据/boot挂载的实际情况填写,如我的机器是: ubuntu@ubuntu-virtual-machine:~$ df /boot Filesystem 1K-blocks Used Available Use% Mounted on /dev/sda1 20509264 7482912 11961496 39% / ``` - 将HelloOs.bin拷贝到/boot/目录; - 重启机器,vmvare长按shift进入引导页面,可以看到HelloOS,选择HelloOS进入。
作者回复: 对的
2021-07-13217 - Freddy置顶我用的是CentOS 7虚拟机,有点不一样: 环境说明: gcc --version gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-44) [root@node01 ~]# cat /etc/redhat-release CentOS Linux release 7.6.1810 (Core) 下面是添加HelloOS启动项的流程: 1.在/etc/grub.d/40_custom文件中,添加HelloOS在grub2中的配置 #!/bin/sh exec tail -n +3 $0 # This file provides an easy way to add custom menu entries. Simply type the # menu entries you want to add after this comment. Be careful not to change # the 'exec tail' line above. #以下是添加内容 menuentry 'HelloOS' { insmod part_msdos #GRUB加载分区模块识别分区 insmod ext2 #GRUB加载ext文件系统模块识别ext文件系统 set root='hd0,msdos1' #注意boot目录挂载的分区,这是我机器上的情况 multiboot2 /HelloOS.bin #GRUB以multiboot2协议加载HelloOS.bin boot #GRUB启动HelloOS.bin } 2.重新生成/boot/grub2/grub.cfg文件 [root@node01 grub2]# grub2-mkconfig -o /boot/grub2/grub.cfg 3.重启VM,即可在grub引导项中看到多了HelloOS
作者回复: 你好,你这样操作也是对的
2021-05-24109 - Shinymimiq置顶我测试了一下M1的Mac也是能跑起了HelloOS的,虽然坑比较多。我大致总结了一下步骤: 首先需要安装x86版的homebrew 用Rosetta 打开iTerm 然后安装x86的homebrew `arch -x86_64 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"` 接下来是重点, Apple自带的C/C++工具链是clang,外加用的linker和GUN linker不兼容,没办法使用课程中提供的linker script,所以我们需要编译安装x86的gcc工具链,顺便可以把nasm和qemu给装了 ``` /usr/local/bin/brew tap nativeos/i386-elf-toolchain /usr/local/bin/brew install i386-elf-binutils i386-elf-gcc nasm qemu ``` 安装完成之后确认一下我们的gcc和ld ``` /usr/local/Cellar/i386-elf-gcc/9.2.0/bin/i386-elf-gcc /usr/local/Cellar/i386-elf-binutils/2.31/bin/i386-elf-ld ``` 接下来的步骤我参考了Viz的评论,代码是在 `https://github.com/vizv/learn\_os/tree/master/hello-os` 可以手动修改Makefile里面的宏 ``` ASM := /usr/local/Cellar/nasm/2.15.05/bin/nasm CC := /usr/local/Cellar/i386-elf-gcc/9.2.0/bin/i386-elf-gcc LD := /usr/local/Cellar/i386-elf-binutils/2.31/bin/i386-elf-ld ``` 顺带一提,我使用iTerm跑还需要在qemu命令上加上-nographic,不然好像没法退出 ``` qemu-system-x86_64 -nographic -curses -drive 'file=$<,format=raw,index=0,media=disk' ``` 然后直接`make all`就可以运行我们的hello-os了
作者回复: 你好,感谢你的分享,m1的同学有福了
2021-05-22757 - 青玉白露置顶写了一个基于Vmare和Ubuntu16.04的详细教程,只要手头有电脑就可以运行,大家可以看看: https://zhuanlan.zhihu.com/p/373996858
作者回复: 谢谢
2021-05-21514 - Viz置顶我也搞了份不需要 GRUB 可以直接用 QEMU 或者其他虚拟机软件跑的版本 https://github.com/vizv/learn_os/tree/master/hello-os 克隆仓库后在 hello-os 目录里 只编译链接并创建镜像: make hello-os.img 编译链接并创建镜像后用 QEMU 启动磁盘镜像: make
编辑回复: 6666,佩服佩服,感谢你的分享!教学相长,期待之后课程里,你还有更多的输出。
2021-05-15936
收起评论