实现最简单内核HelloOS

该博客是操作系统45讲学习笔记(极客时间)
代码:https://gitee.com/lmos/cosmos/tree/master/lesson02/HelloOS
参考:https://blog.csdn.net/chenchengwudi/article/details/116707122

实现最简单内核HelloOS

img

​ hello OS引导流程

1、进入grub引导界面

2、编写引导汇编代码

hello os引导汇编代码

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. 代码 1~40 行,用汇编定义的 GRUB 的多引导协议头,其实就是一定格式的数据,我们的 Hello OS 是用 GRUB 引导的,当然要遵循 GRUB 的多引导协议标准,让 GRUB 能识别我们的 Hello OS。之所以有两个引导头,是为了兼容 GRUB1 和 GRUB2。

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

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

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

编写主函数

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

控制计算机屏幕

显卡:集显(主板内)、核显(CPU内)、独显(PCIE接口);

VESA标准:字符模式和图形模式

img

​ 显卡字符模式

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;
}

编译和安装OS

image-20210616183536460

  • entry.asm:供grub调用的引导程序,用于设置CPU工作模式与工作环境,并调用C语言编写的main函数
  • hello.lds:链接器脚本,用于指导链接过程,设定不同程序段的布局
  • main.c:实现main函数
  • vgastr.c / vgastr.h:实现字符串在显示器上的输出
  • makefile:编译脚本,用于指导编译过程

执行make命令

makefile

MAKEFLAGS = -sR
MKDIR = mkdir
RMDIR = rmdir
CP = cp
CD = cd
DD = dd
RM = rm

ASM		= nasm
CC		= gcc
LD		= ld
OBJCOPY	= objcopy

ASMBFLAGS	= -f elf -w-orphan-labels
CFLAGS		= -c -Os -std=c99 -m32 -Wall -Wshadow -W -Wconversion -Wno-sign-conversion  -fno-stack-protector -fomit-frame-pointer -fno-builtin -fno-common  -ffreestanding  -Wno-unused-parameter -Wunused-variable
LDFLAGS		= -s -static -T hello.lds -n -Map HelloOS.map 
OJCYFLAGS	= -S -O binary

HELLOOS_OBJS :=
HELLOOS_OBJS += entry.o main.o vgastr.o
HELLOOS_ELF = HelloOS.elf
HELLOOS_BIN = HelloOS.bin

.PHONY : build clean all link bin

all: clean build link bin

clean:
	$(RM) -f *.o *.bin *.elf

build: $(HELLOOS_OBJS)

link: $(HELLOOS_ELF)
$(HELLOOS_ELF): $(HELLOOS_OBJS)
	$(LD) $(LDFLAGS) -o $@ $(HELLOOS_OBJS)
bin: $(HELLOOS_BIN)
$(HELLOOS_BIN): $(HELLOOS_ELF)
	$(OBJCOPY) $(OJCYFLAGS) $< $@

%.o : %.asm
	$(ASM) $(ASMBFLAGS) -o $@ $<
%.o : %.c
	$(CC) $(CFLAGS) -o $@ $<

img

​ hello os编译过程

​ 编译完后生成Hello OS.bin可执行文件。 GRUB启动时会加载一个 grub.cfg 的文本文件,根据其中的内容执行相应的操作,其中一部分内容就是启动项。

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

menuentry 'HelloOS' {
     insmod part_msdos 			 #GRUB加载分区模块识别分区
     insmod ext2 				#GRUB加载ext文件系统模块识别ext文件系统
     set root='hd0,msdos5' 		 #注意boot目录挂载的分区,这是我机器上的情况
     multiboot2 /boot/HelloOS.bin #GRUB以multiboot2协议加载HelloOS.bin
     boot 						#GRUB启动HelloOS.bin
}

以管理员修改文本

重启,进入HelloOS

image-20210616211130504
image-20210616204510389

总结

  • 修改修改/etc/default/grub文件

    • grub_timeout_style=hidden给删除或者注释掉
    • grub_cmdline_linux_default修改为text
    • sudo update-grub重新更新grub配置
  • 编译文件

  • 修改启动项/boot/grub/grub.cfg

坑:确定挂载点,如果挂载点是/boot,需要把路径改为multiboot2 /HelloOS.bin

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值