操作系统实战 45 讲
彭东
网名 LMOS,Intel 傲腾项目关键开发者
65203 人已学习
新⼈⾸单¥68
登录后,你可以任选4讲全文学习
课程目录
已完结/共 60 讲
尝尝鲜:从一个Hello到另一个Hello (2讲)
特别放送 (1讲)
操作系统实战 45 讲
15
15
1.0x
00:00/00:00
登录|注册

02 | 几行汇编几行C:实现一个最简单的内核

编译和安装Hello OS
Hello OS的实现
PC机的引导过程
安装Hello OS
编译
make工具
控制计算机屏幕
main函数
控制计算机屏幕
初始化CPU的寄存器和C语言的运行环境
GRUB的多引导协议头
GRUB引导程序
BIOS固件
思考题
重点回顾
编译和安装Hello OS
Hello OS的主函数
Hello OS引导汇编代码
PC机的引导流程
参考文章

该思维导图由 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
立即购买
登录 后留言

全部留言(276)

  • 最新
  • 精选
  • Geek_b3ad17
    置顶
    lesson2 运行在bochs 虚拟机 https://gitee.com/jiawenshi/myos

    编辑回复: 感谢你分享~

    2023-10-17归属地:江西
    5
    1
  • 孟祥毅🇨🇳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-21
    2
    4
  • 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-25
    3
    18
  • 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-10
    3
  • 不安好心
    置顶
    有一个疑问,汇编代码那里: ;重新加载 GDTlgdt [GDT_PTR] jmp dword 0x8 :_32bits_mode 这里明明没有开启保护模式,为什么能这样跳转,而且经验证,也确实使用了gdt。 但是实模式不是cs << 4 + offset进行寻址吗?

    作者回复: 因为GRUB已经在保护模式下了

    2021-08-25
    2
  • 喜欢吃鱼
    置顶
    实验注意几个关键问题。 - 将作者提供的代码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-13
    2
    17
  • 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-24
    10
    9
  • 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-22
    7
    57
  • 青玉白露
    置顶
    写了一个基于Vmare和Ubuntu16.04的详细教程,只要手头有电脑就可以运行,大家可以看看: https://zhuanlan.zhihu.com/p/373996858

    作者回复: 谢谢

    2021-05-21
    5
    14
  • Viz
    置顶
    我也搞了份不需要 GRUB 可以直接用 QEMU 或者其他虚拟机软件跑的版本 https://github.com/vizv/learn_os/tree/master/hello-os 克隆仓库后在 hello-os 目录里 只编译链接并创建镜像: make hello-os.img 编译链接并创建镜像后用 QEMU 启动磁盘镜像: make

    编辑回复: 6666,佩服佩服,感谢你的分享!教学相长,期待之后课程里,你还有更多的输出。

    2021-05-15
    9
    36
收起评论
显示
设置
留言
99+
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部