手写简单操作系统内核

简介: 本文目的在于自定义一个简易操作系统,通过引导程序启动后打印一行字符串,先演示操作,最后介绍原理。

1 操作过程


我的环境:

 在virtualBox上面先安装好虚拟机Ubuntu 16.04



源码:

 https://gitee.com/hnuwjw/os-hello-os



1.1 设置grub进入引导菜单


安装nasm,才能执行make

先安装nasm:


sudo apt-get install -y nasm


然后在HelloOS目录下执行:

make -f Makefile


就可以得到HelloOS.bin文件了


0.png


配置下启动项,不然无法选择HelloOS菜单


先修改文件:


/etc/default/grub


1.png


如果修改的时候报错“readonly option is set XXXXX”,则使用超级管理员角色编辑文件:

sudo vim grub

然后执行:


sudo update-grub


1.2 增加HelloOS启动选项

修改/boot/grub/grub.cfg,增加HelloOS启动项:


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
}


2.png


3.png


文件系统          1K-块        已用        可用      已用%   挂载点
/dev/sda4      48752308   8087584   38158536    18%       /


其中的“sda1”就是硬盘的第四个分区,但是GRUB的menuentry中不能写sda4,而是要写“hd0,msdos1”,这是GRUB的命名方式,hd0表示第一块硬盘。


然后把HelloOS.bin文件复制到/boot/目录下,最后重启计算机


只要我们的PC机上安装了Ubuntu Linux操作系统,GRUB就已经存在了,就不用我们从引导程序开始写了。


4.png


5.png

2 原理


2.1 Hello OS的引导流程



6.png

PC机BIOS固件是固化在PC机主板上的ROM芯片中的,掉电也能保存,PC机上电后的第一条指令就是BIOS固件中的,它负责检测和初始化CPU、内存及主板平台,然后加载硬盘中的第一个扇区数据,到0x7c00地址开始的内存空间,再接着跳转到0x7c00处执行指令,这里就是GRUB引导程序。


2.2 Hello OS引导汇编代码


对应entry.asm文件:


MBT_HDR_FLAGS EQU 0x00010003
MBT_HDR_MAGIC EQU 0x1BADB002 ;多引导协议头魔数
MBT_HDR2_MAGIC  EQU 0xe85250d6 ;第二版多引导协议头魔数
global _start ;导出_start符号
extern main ;导入外部的main函数符号
[section .start.text] ;定义.start.text代码节
[bits 32] ;汇编成32位代码
_start:
  jmp _entry
ALIGN 8
mbt_hdr:
  dd MBT_HDR_MAGIC
  dd MBT_HDR_FLAGS
  dd -(MBT_HDR_MAGIC+MBT_HDR_FLAGS)
  dd mbt_hdr
  dd _start
  dd 0
  dd 0
  dd _entry
;以上是GRUB所需要的头
ALIGN 8
mbt2_hdr:
  DD  MBT_HDR2_MAGIC
  DD  0
  DD  mbt2_hdr_end - mbt2_hdr
  DD  -(MBT_HDR2_MAGIC + 0 + (mbt2_hdr_end - mbt2_hdr))
  DW  2, 0
  DD  24
  DD  mbt2_hdr
  DD  _start
  DD  0
  DD  0
  DW  3, 0
  DD  12
  DD  _entry
  DD      0
  DW  0, 0
  DD  8
mbt2_hdr_end:
;以上是GRUB2所需要的头
;包含两个头是为了同时兼容GRUB、GRUB2
ALIGN 8
_entry:
  ;关中断
  cli
  ;关不可屏蔽中断
  in al, 0x70
  or al, 0x80
  out 0x70,al
  ;重新加载GDT
  lgdt [GDT_PTR]
  jmp dword 0x8 :_32bits_mode
_32bits_mode:
  ;下面初始化C语言可能会用到的寄存器
  mov ax, 0x10
  mov ds, ax
  mov ss, ax
  mov es, ax
  mov fs, ax
  mov gs, ax
  xor eax,eax
  xor ebx,ebx
  xor ecx,ecx
  xor edx,edx
  xor edi,edi
  xor esi,esi
  xor ebp,ebp
  xor esp,esp
  ;初始化栈,C语言需要栈才能工作
  mov esp,0x9000
  ;调用C语言函数main
  call main
  ;让CPU停止执行指令
halt_step:
  halt
  jmp halt_step
GDT_START:
knull_dsc: dq 0
kcode_dsc: dq 0x00cf9e000000ffff
kdata_dsc: dq 0x00cf92000000ffff
k16cd_dsc: dq 0x00009e000000ffff
k16da_dsc: dq 0x000092000000ffff
GDT_END:
GDT_PTR:
GDTLEN  dw GDT_END-GDT_START-1
GDTBASE dd GDT_START


代码1~40行,用汇编定义的GRUB的多引导协议头,之所以有两个引导头,是为了兼容GRUB1和GRUB2。


代码44~52行,关掉中断,设定CPU的工作模式。


代码54~73行,初始化CPU的寄存器和C语言的运行环境。


代码78~87行,从GDT_START开始是CPU工作模式所需要的数据。


2.3 主函数


#include "vgastr.h"
void main()
{
  printf("Hello OS!");
  return;
} 

其中的printf不是应用程序库中的那个printf,而是需要我们自己实现。


2.4 控制计算机屏幕


我们要在屏幕上显示字符,就要编程操作显卡。


显卡把屏幕分成24行,每行80个字符,把这(24*80)个位置映射到以0xb8000地址开始的内存中,每两个字节对应一个字符,其中一个字节是字符的ASCII码,另一个字节为字符的颜色值。


7.png


void _strwrite(char* string)
{
  char* p_strdst = (char*)(0xb8000);//指向显存的开始地址
  while (*string)
  {
    *p_strdst = *string++;
    p_strdst += 2;
  }
  return;
}
void printf(char* fmt, ...)
{
  _strwrite(fmt);
  return;
}


_strwrite函数正是将字符串里每个字符依次定入到0xb8000地址开始的显存中,而p_strdst每次加2,这也是为了跳过字符的颜色信息的空间。


2.5 编译过程


微信图片_20220422224627.png





相关文章
|
2月前
|
消息中间件 存储 算法
【软件设计师备考 专题 】操作系统的内核(中断控制)、进程、线程概念
【软件设计师备考 专题 】操作系统的内核(中断控制)、进程、线程概念
84 0
|
4月前
|
Go 调度
go-issues#14592 runtime: let idle OS threads exit 内核线程暴增与线程回收问题
go-issues#14592 runtime: let idle OS threads exit 内核线程暴增与线程回收问题
26 0
|
7月前
|
存储 缓存 Linux
操作系统与内核、系统编程与应用编程
操作系统与内核、系统编程与应用编程
64 0
|
3月前
|
Linux
操作系统 | 编写内核
操作系统 | 编写内核
45 0
|
3月前
|
C语言
操作系统 | 编写内核模块
操作系统 | 编写内核模块
34 1
|
5天前
|
关系型数据库 分布式数据库 数据库
|
1月前
|
存储 虚拟化 Anolis
Anolis OS 23.1 Alpha2 预览版:内核配置升级与软件选型新进展
Anolis OS 23.1 Alpha2 预览版本 全面集成了软件包的收敛成果和内核配置参数整理成果。
|
2月前
|
算法 Linux 调度
根基已筑!Anolis OS 23.1 预览版本搭载 Linux 6.6 内核和工具链升级完成
Anolis OS 23.1 对软件包的选择和组合进行了重新规划与决策,满足更为广泛的应用场景需求。
|
6月前
|
测试技术 KVM 开发工具
【OS Pintos】Pintos 内核库基本数据结构 | 运行测试用例 alarm-multiple
【OS Pintos】Pintos 内核库基本数据结构 | 运行测试用例 alarm-multiple
77 0
|
3月前
|
IDE Linux 开发工具
DP读书:鲲鹏处理器 架构与编程(十三)操作系统内核与云基础软件
DP读书:鲲鹏处理器 架构与编程(十三)操作系统内核与云基础软件
72 1