当前位置: 首页 > news >正文

营销网站功能深圳市住房和建设局工程交易服务主页

营销网站功能,深圳市住房和建设局工程交易服务主页,企业网站的模块功能,wordpress cdn缓存更好的阅读体验,请点击 YinKai s Blog | 实现一个最简单的内核。 ​ 这篇文章带大家实现一个最简单的操作系统内核—— Hello OS。 PC 机的引导流程 ​ 我们这里将借助 Ubuntu Linux 操纵系统上的 GRUB 引导程序来引导我们的 Hello OS。 ​ 首先我们得了解一下&a…

更好的阅读体验,请点击 YinKai 's Blog | 实现一个最简单的内核。

​ 这篇文章带大家实现一个最简单的操作系统内核—— Hello OS。

PC 机的引导流程

​ 我们这里将借助 Ubuntu Linux 操纵系统上的 GRUB 引导程序来引导我们的 Hello OS。

​ 首先我们得了解一下,Hello OS 的引导流程:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

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

Hello OS 引导汇编代码

​ 我们的 Hello OS 总有 6 个文件,下面一一讲解。

Hello OS 的主函数
main.c
#include "vgastr.h"
void main()
{printf("Hello OS! I am YinKai");return;
}
entry.asm
; 多引导协议头(GRUB)
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 _entryALIGN 8
; GRUB 所需的多引导协议头
mbt_hdr:dd MBT_HDR_MAGICdd MBT_HDR_FLAGSdd -(MBT_HDR_MAGIC+MBT_HDR_FLAGS)dd mbt_hdrdd _startdd 0dd 0dd _entryALIGN 8
; GRUB2 所需的多引导协议头
mbt2_hdr:DD MBT_HDR2_MAGICDD 0DD mbt2_hdr_end - mbt2_hdrDD -(MBT_HDR2_MAGIC + 0 + (mbt2_hdr_end - mbt2_hdr))DW 2, 0DD 24DD mbt2_hdrDD _startDD 0DD 0DW 3, 0DD 12DD _entryDD 0DW 0, 0DD 8mbt2_hdr_end:ALIGN 8
_entry:; 关中断cli; 关不可屏蔽中断in al, 0x70or al, 0x80out 0x70, al; 重新加载GDTlgdt [GDT_PTR]jmp dword 0x8 :_32bits_mode_32bits_mode:; 初始化C语言可能会用到的寄存器mov ax, 0x10mov ds, axmov ss, axmov es, axmov fs, axmov gs, axxor eax,eaxxor ebx,ebxxor ecx,ecxxor edx,edxxor edi,edixor esi,esixor ebp,ebpxor esp,esp; 初始化栈,C语言需要栈才能工作mov esp,0x9000; 调用C语言函数maincall main; 让CPU停止执行指令
halt_step:haltjmp halt_step; GDT 全局描述符表
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

​ 这是一个引导加载程序,它是计算机启动过程中的第一个软件,它的主要任务是在计算机启动时,通过 GRUB 或 GRUB2 多引导协议头,初始化系统环境,设置 GDT,然后调用 C 语言的 main 函数。

控制计算机屏幕

​ 首先我们得知道显卡的字符模式的工作细节。

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

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

​ 了解原理之后,我们来自己实现 printf 函数:

vgastr.c
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;
}

​ 代码很简单,我们在 printf 把传入的字符串作为参数,传给 _strwrite 函数,然后把字符串中的每个字符依次写入 0xb8000 地址开始的显存中。p_strdst 每次加 2 ,是为了跳过表示颜色值的字符,直接指向下一个字符的 ASCII 值。

​ 为了编译器能够正确识别我们的函数,我们还需要另写一个文件,保证函数调用的正确性。

vgastr.h
void _strwrite(char* string);
void printf(char* fmt, ...);
链接
hello.lds
ENTRY(_start)
OUTPUT_ARCH(i386)
OUTPUT_FORMAT(elf32-i386)
SECTIONS
{. = 0x200000;__begin_start_text = .;.start.text : ALIGN(4) { *(.start.text) }__end_start_text = .;__begin_text = .;.text : ALIGN(4) { *(.text) }__end_text = .;__begin_data = .;.data : ALIGN(4) { *(.data) }__end_data = .;__begin_rodata = .;.rodata : ALIGN(4) { *(.rodata) *(.rodata.*) }__end_rodata = .;__begin_kstrtab = .;.kstrtab : ALIGN(4) { *(.kstrtab) }__end_kstrtab = .;__begin_bss = .;.bss : ALIGN(4) { *(.bss) }__end_bss = .;
}

​ 这段代码是一个链接脚本,用于告诉链接器如何将各个目标文件组合成最终的可执行文件。

编译

​ 我们这里使用 make 工具进行系统编译,将每个代码模块编译最后链接成可执行的二进制文件。

Makefile
MAKEFLAGS = -sR
MKDIR = mkdir
RMDIR = rmdir
CP = cp
CD = cd
DD = dd
RM = rmASM		= nasm
CC		= gcc
LD		= ld
OBJCOPY	= objcopyASMBFLAGS	= -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 binaryHELLOOS_OBJS :=
HELLOOS_OBJS += entry.o main.o vgastr.o
HELLOOS_ELF = HelloOS.elf
HELLOOS_BIN = HelloOS.bin.PHONY : build clean all link binall: clean build link binclean:$(RM) -f *.o *.bin *.elfbuild: $(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 $@ $<

安装 Hello OS

​ 不同的系统,可能操作不同,我这里用的是 ubuntu。

安装编译环境
  • 安装汇编编译器
sudo apt-get install nasm
  • 安装gcc(该命令会安装包括gcc在内的所有软件)
sudo apt install build-essential
修改启动项等待时间

​ 修改启动项等待时间,以供我们选择启动项文件

sudo vim /etc/default/grub,打开文件,修改为 10 s

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

​ 使用 sudo update-grub 更新我们的修改。

:::warning

​ 每次使用这个命令之后,我们追加的启动项(后面会说到)就会被清除,需要重新添加。

:::

构建 HelloOS.bin 文件

​ 在自己的家目录下创建一个 HelloOS 文件夹,放入我们依赖的 6 个文件,代码及文件命名见上。

使用 make 构建

​ 在 HelloOS 目录下,使用 make 命令,即可获得 HelloOS.bin 文件,并将该文件移动到 /boot/ 目录下。(如果原本就有要将其删除,再放入。)

追加 GRUB 启动项

​ 使用 df /boot 获取文件系统名,以及文件系统的挂载点,我的如下:

文件系统          1K-块    已用    可用 已用% 挂载点
/dev/sda5      19947120 9921616 8986912   53% /

​ 写 grub 的引导文件,将下面的启动项代码插入到 /boot/grub/grub.cfg 文件末尾

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

:::warning

① 这里的 hd0,msdos? 需要根据 (4)中的 /dev/sda? 对应起来;

② 如果挂载点是 / 就需要在文件中写 /boot/HelloOS.bin;如果挂载点是 /boot,则直接写 /HelloOS.bin 即可

③ 如果该文件不可修改,可以用 root 权限修改该文件为可写文件。

:::

​ 最后使用 reboot 命令,即可重启系统,看到我们的 Hello OS 选项:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

​ 选择后,即可看到我们在主函数 main.c 中写的字符串啦~

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

小结

Hello OS 启动的流程主要包括以下步骤:

  1. 计算机上电: 当计算机上电时,主板上的 BIOS 固件开始执行。
  2. BIOS 初始化: BIOS 负责检测和初始化计算机硬件,包括处理器、内存等。
  3. 加载引导扇区: BIOS 根据启动设备配置加载引导扇区,通常是硬盘上的 MBR。
  4. 引导加载程序执行: 引导加载程序(如 GRUB)被加载,负责加载操作系统内核。
  5. GRUB 加载 Hello OS: GRUB 通过配置文件加载 Hello OS 的二进制文件(HelloOS.bin)。
  6. Hello OS 入口点: Hello OS 的入口点在 entry.asm 中,负责初始化系统环境。
  7. 切换到 32 位保护模式: _start 调用 _32bits_mode 将处理器切换到 32 位保护模式。
  8. C 语言的 main 函数: main.c 包含操作系统的主要逻辑,调用了输出字符串的函数。
  9. 屏幕输出: vgastr.c 中的 _strwriteprintf 负责向屏幕输出字符串。
  10. 系统初始化完成: Hello OS 在初始化完成后,等待主要逻辑执行完毕。
  11. CPU 停止执行指令: 使用 halt 指令让 CPU 停止执行,操作系统启动过程结束。
  12. 系统运行或重新启动: 如果需要,可以继续执行其他操作系统功能或重新启动计算机。
http://www.yayakq.cn/news/629/

相关文章:

  • 石泉政协网站建设方案江西网站做的好的企业文化
  • 有效的网站需要做到什么意思陕西工程造价信息网
  • 如何做充值网站如何禁止ip访问网站
  • cms网站后台管理系统莱芜在线论坛莱芜话题凤城高中
  • 织梦网站后台logo删除网站对接qq群 虚拟主机
  • 上海建设银行网站招聘南京 网站制作公司
  • asp.net不适合做网站WordPress商用收费吗
  • wordpress动漫网站模板工商局注册公司网站
  • 外贸网站推广有用吗安卓开发软件
  • 免费外贸网站模板下载网站建设外包还是自己做
  • 网站美工做专题尺寸多少?南昌营销型网站
  • php 网站建设 教学定制型网站设计
  • 深圳 福田 网站建设辽宁省建设培训中心网站
  • 怎么建设自己收费网站海报设计模板网站
  • 韩版做哪个网站好微电影制作
  • 伍佰亿网站建设织梦免费企业网站
  • 微网站设计网店装修时如何进行文案策划
  • 网站权重排行开发网站的经济可行性
  • 鹤岗做网站精准获客
  • 建设厅官方网站新资质标准建设企业高端网站
  • php源码网站修改辽阳建设银行网站
  • 四川长昕建设工程有限公司网站忻州免费建网站
  • 免费做cpa单页网站筑梦网站建设
  • 网站制作用什么语言微信网站是多少
  • 杭州网站设计公司联系亿企邦婚庆公司简介
  • 仿站网站公司网站建设费如何入账
  • 中国大唐集团公司招聘网站网站建设专员招聘
  • 把网站传到服务器上怎么做企业网站多少钱
  • 海市科技网站建设用tornado做网站
  • 安卓手机做网站服务器吗网站建设评价标准