手写操作系统 -- 微内核

搭建操作系统框架,输出hello world

知识点:

  • CPU的两种运行模式:实模式、保护模式(普遍)
    • 操作系统或应用程序运行中用到的都是真实的物理地址,这种场景叫做实模式运行;我们的操作系统刚开机的时候就是运行在实模式下;我们自己写的操作系统也是,先在实模式下运行,载入内核,然后进入保护模式
  • 如何向屏幕输出内容?
  • BIOS中断?
    • 在实模式下,我们写的OS内核想要访问硬件,就必须借助BIOS中断

实现微内核

运行起来一个简单的框架

重点理解:

  • 汇编脚本怎么转换成内核?
  • 内核存放在硬盘什么位置?
    • 0柱面0磁道1扇区(512字节 0x200
    • 硬盘哪里来的?
    • 怎么写进硬盘?
  • 内核如何运行起来?
    • BIOS例程读取0柱面0磁道1扇区
    • 读到0x7c00(为什么?)
    • 执行权限如何给微内核?

在这里插入图片描述

具体实现:

  1. 创建一个内核项目编写boot.asm脚本(使用clion)
;基本框架
[ORG  0x7c00]   ;指定想对位置 物理地址

[SECTION .text]  ;段
[BITS 16]     	;指定16位寄存器
global _start   ;声明全全局的开始 _start可以换成别的,但一般这么写
_start:
    xchg bx, bx  ;断点调试

    jmp $

times 510 - ($ - $$) db 0   ;times指定重复次数 $: 表示当前地址 $$: 表示当前节(section)的开始地址 
db 0x55, 0xaa   ;启动扇区的标准签名,表示这是一个有效的启动扇区

(1)使用bximage -q -hd=16 -func=create -sectsize=512 -imgmode=flat hd.img 命令生成hd.img硬盘

`bximage` 是一个用于创建硬盘或软盘映像文件的工具,该工具常用于`Bochs`模拟器。这个模拟器主要用于开发操作系统或运行旧的操作系统。

让我们分解你给出的命令:

1. **bximage**: 这是调用该工具的命令名。

2. **-q**: 这个选项使`bximage`在“快速模式”下运行,意思是它不会询问任何交互式问题,只会基于提供的参数来执行。

3. **-hd=16**: 指定创建的映像文件的大小为16MB。这里的`-hd`表示硬盘映像。

4. **-func=create**: 指定你要执行的功能是创建一个新的映像文件。

5. **-sectsize=512**: 设置每个扇区的大小为512字节。这是一个常见的扇区大小。

6. **-imgmode=flat**: 这指定映像文件的模式为`flat`。在这种模式下,映像文件就是一个简单的连续字节流,没有任何特殊的结构或格式。

7. **hd.img**: 这是你要创建的映像文件的文件名。

总结一下:这个命令告诉`bximage`快速地创建一个16MB的硬盘映像文件,名为`hd.img`,每个扇区大小为512字节,映像模式为`flat`。

(2) 使用nasm boot.asm 命令生成boot.o文件;内存分布如下:

在这里插入图片描述

(3)使用 "dd if=boot of=hd.img bs=512 seek=0 count=1 conv=notrunc"内核程序(boot)写入硬盘(hd.img)当中;内存图如下:

在这里插入图片描述

![在这里插入图片描述](https://img-blog.csdnimg.cn/af037a79425b4ba8aeaa596eb549af04.png)


`dd` 是一个 Unix/Linux 下的命令行工具,用于在文件之间或者从文件和设备之间复制数据。它可以用于各种数据转换和复制任务,经常用于制作启动盘或拷贝整个硬盘或分区的数据。 

让我们详细解释你给出的命令:

1. **dd**: 调用这个命令。

2. **if=boot**: 设置输入文件为`boot`。`if`代表 "input file"。

3. **of=hd.img**: 设置输出文件为`hd.img`。`of`代表 "output file"。

4. **bs=512**: 设置块大小为512字节。`bs`代表 "block size"。这意味着`dd`每次读取和写入512字节。

5. **seek=0**: 开始从输出文件的开始位置写入。`seek`用于指定输出文件中的起始位置。

6. **count=1**: 只复制一个块。因为`bs`是512字节,所以这个命令只会复制512字节。

7. **conv=notrunc**: 不截断输出文件。`conv`用于指定一些转换操作。`notrunc`意味着它不会截断(或者缩短)输出文件。如果输出文件已经存在并且比要复制的数据大,它不会被缩短,只会在指定的位置被新数据覆盖。

综上所述,这个命令的作用是将`boot`文件的前512字节复制到`hd.img`文件的开始位置,而不会截断或者改变`hd.img`文件的其他部分。

(4)利用 bochsqemu 来运行

将命令汇总位makefile文件:

# 汇总命令执行
BUILD:=./build

HD_IMG_NAME:= "hd.img"

all: ${BUILD}/boot/boot.o
	$(shell rm -rf $(HD_IMG_NAME))
	bximage -q -hd=16 -func=create -sectsize=512 -imgmode=flat $(HD_IMG_NAME)
	dd if=${BUILD}/boot/boot.o of=hd.img bs=512 seek=0 count=1 conv=notrunc

${BUILD}/boot/%.o: %.asm
	$(shell mkdir -p ${BUILD}/boot)
	nasm $< -o $@

clean:
	$(shell rm -rf ${BUILD})

bochs: all
	bochs -q -f bochsrc

qemu: all
	qemu-system-x86_64 -hda hd.img

运行起来的样子:

在这里插入图片描述

实战BIOS中断之屏幕输出

;基本框架
[ORG  0x7c00]   ;指定想对位置 物理地址

[SECTION .text]  ;段
[BITS 16]     	;指定16位寄存器
global _start   ;声明全全局的开始 _start可以换成别的,但一般这么写
_start:
    xchg bx, bx  ;断点调试
    

    jmp $

times 510 - ($ - $$) db 0   ;times指定重复次数 $: 表示当前地址 $$: 表示当前节(section)的开始地址 
db 0x55, 0xaa   ;启动扇区的标准签名,表示这是一个有效的启动扇区

输出hello world

[ORG  0x7c00]

[SECTION .text]
[BITS 16]
global _start
_start:
    ; 设置屏幕模式为文本模式,清除屏幕
    mov ax, 3
    int 0x10


    mov     si, msg
    call    print

    jmp $

; 如何调用
; mov     si, msg   ; 1 传入字符串
; call    print     ; 2 调用
print:
    mov ah, 0x0e
    mov bh, 0
    mov bl, 0x01
.loop:
    mov al, [si]
    cmp al, 0
    jz .done
    int 0x10  ;利用中断的方式打印出来

    inc si
    jmp .loop
.done:
    ret

msg:
    db "hello, world", 10, 13, 0


times 510 - ($ - $$) db 0
db 0x55, 0xaa;

详细理解:

  • 内核如何运行起来?
    • BIOS例程读取0柱面0磁道1扇区
    • 读到0x7c00(为什么?)
    • 执行权限如何给微内核?
      在这里插入图片描述
  1. 实时模式下,Intel的早期微处理器,例如8086,它确实有20位的地址总线,这允许它访问1MB的物理内存(2^20 = 1,048,576字节或1MB);
  1. 考虑哪些内存可以用哪些不能用,参考实时模式下内存布局图。
    在这里插入图片描述

3.BIOS启动过程
在实时模式下的内存布局中可以看到在最后16字节的内容时跳转指令jmp f000:e05b
实时模式下寻址方式为 段:段内偏移,所有f000 << 4 + e05b = fe05b (真实物理地址)
跳转到fe05b去执行BIOS启动过程
在这里插入图片描述
在这里插入图片描述

BIOS(Basic Input/Output System)是计算机启动时首先运行的固件。BIOS启动过程是相对固定的,负责初始化和测试系统硬件,然后加载并执行引导加载程序来启动操作系统。以下是BIOS启动过程的简要概述:

1. **上电自检(POST,Power-On Self Test)**:当计算机上电或重启时,BIOS首先执行POST。这是一系列的硬件测试,确保关键组件(如RAM、CPU、键盘和其他设备)功能正常。

2. **硬件初始化**:BIOS将初始化系统的所有硬件设备,包括内存控制器、显示卡、硬盘、光驱等。

3. **设备检查**:BIOS检查连接到计算机的所有设备,例如键盘、鼠标、硬盘、CD/DVD驱动器等。

4. **启动顺序**:根据BIOS设置中定义的启动顺序,BIOS会尝试从各种设备上加载操作系统。例如,通常的启动顺序可能是:光驱、USB驱动器、硬盘。但这可以在BIOS设置中自定义。

5. **引导扇区加载**:当BIOS找到一个有效的启动设备后,它会加载该设备的第一个扇区——称为引导扇区。引导扇区包含引导加载程序的代码,它的任务是开始加载操作系统。

6.**转交控制权限**:一旦引导扇区的内容被加载到内存中,BIOS就将控制权转交给这段代码。这通常发生在物理内存的0x7C00地址处,因为这是BIOS加载引导扇区内容的标准位置。

7. **引导加载程序执行**:引导加载程序接管后,它会继续加载操作系统的其余部分。在某些系统中,例如使用GRUB引导加载程序的Linux系统,用户可能会看到一个菜单,允许他们选择不同的操作系统或配置。

8. **操作系统加载**:引导加载程序加载并执行操作系统。操作系统接管后,它将完成其自己的初始化并最终显示用户界面,等待用户输入。

这只是BIOS启动过程的高级概述。具体的步骤和细节可能因计算机硬件和配置的不同而异。此外,现代计算机上也有一个BIOS的替代者,称为UEFI(统一的可扩展固件接口),它提供了更多的功能和安全性,并支持更大的硬盘驱动器和现代操作系统。

总结

  • 创建一个微内核项目,编写boot.asm
    • 使用nasm boot.asm 命令生成boot.o文件。
  • 如何生成一个硬盘?
    • 使用bximage -q -hd=16 -func=create -sectsize=512 -imgmode=flat hd.img 命令生成。hd.img硬盘
  • 如何将内核写入硬盘?
    • 使用 "dd if=boot of=hd.img bs=512 seek=0 count=1 conv=notrunc"内核程序(boot)写入硬盘(hd.img)当中。
  • 如何运行起来?
    • 利用 bochsqemu 来运行 。
  • 为什么要读到0x7c00位置?
    • 查看实时实时模式下内的存布局图可以发现0x7c00BIOS例程的入口。
  • 为什么要调到0xf000:e05b处?
    • BIOS例程的内存地址
  • 13
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值