Gos ——BIOS与继承者MBR

文章目录

写在前面:自制操作系统Gos 第二章第二篇:主要内容是CPU中权力的移交,如何控制BIOS和MBR

BIOS

有过操作系统基础的同学都知道,当操作系统通电之后,会先加载BIOS,之后BIOS将会加载操作系统。说起来这个过程好像很简单一样,但是其实其中有很多细节是我们并不了解的,而这些细节正式掌握操作系统的屠龙技。

什么是BIOS

BIOS的全程是Base Input Output System,即基本输入输入系统。可以看到有这么几个关键词哈:基本、输入输出、系统。

不禁有这么几个疑问了:

  • 基本是什么意思?
  • 输入输出的又是什么?

我们先来看基本的意思哈。

8086的实模式内存布局 重点!!!

在Intel 8086中总共有20根地址,那么其实CPU可以访问到的地址范围也就是220 = 1M的范围。而这宝贵的1M空间又被划分为以下区域:

起始 结束 大小 用途
FFFF0 FFFFF 16B BIOS的入口地址,此处的内容主要是jmp f000:e05b
F0000 FFFEF 64KB-16B BIOS的其他地址
C8000 EFFFF 160KB 映射硬件适配器ROM或者内存映射 I/O
C0000 C7FFF 32KB 显示适配器BIOS
B8000 BFFFF 32KB 用于文本模式显示适配器
B0000 B7FFF 32KB 用于黑白显示适配器
A0000 AFFFF 64KB 用于彩色显示适配器
9FC00 9FFFF 1KB EBDA扩展BIOS数据区
7E00 7DFF 512B MBR加载区
500 4FF 256B BIOS数据区
000 3FF 1KB 中断向量表

这个表很重要,它相当于我们屠龙技的剑谱,如何屠龙都得依着他来。

我们看一开始的0xFFFF0 ~ 0xFFFFF 这段区域,这64KB内存是ROM,里面存储的就是BIOS代码。BIOS的主要工作就是检测、初始化硬件。这个过程放大来看就是BIOS调用硬件驱动提供的硬件驱动函数。除此之外,BIOS做的另一件事情就是初始化中断向量表,这样就可以通过 int 中断号这个汇编指令来调用中断函数了。

而为什么称之为基本输入输出呢,因为BIOS是工作在实模式下面的,其不用做所有工作,只用完成基本的初始化工作就好了,真正广阔的星辰大海在保护模式呢!

BIOS启动

从我们整篇文章的开头我们知道,BIOS可以说是整个计算机第一个启动的软件了,那么它又是被谁启动的呢?是自举么?

其实是硬件啦。实模式下x86的CPU通过段基址寄存器cs和段偏移寄存器ip来实现对内存的访问。在开机的一瞬间,CPU的cs:ip便被初始化为0xF000:0xFFF0,此地址便是BIOS的入口地址。


在x86模式下面有个约定,为了让16位的寄存器能够访问20位大小的内存空间,需要段基地址左移4位,那么这里0xF000:0xFFF0其实等价于0xFFFF0

之后,BIOS执行指令jmp f000:e05b,跳转到BIOS真正开始执行的地方。之后BIOS就开始检测内存、显卡等外设信息,当检测通过的时候并初始化硬件之后,BIOS会在0x000~0x3FF处建立中断向量表并填写中断例程。

MBR

当BIOS初始化成功之后,他就完成了他的工作。之后他就会把权力交给MBR。他是我们能够掌控的第一个程序。

什么是MBR

MBR即Main Boot Record,它位于整个硬盘最开始的扇区,即0盘0道1扇区,这扇区便被成为MBR引导扇区。而这个引导扇区的内容如下:

  • 446字节的引导程序及参数
  • 64字节的分区表
  • 2字节的结束标记0x550xaa

:
关于权力是怎么交接的,则是BIOS做完工作之后,从磁盘的一开始检测0x550xaa这两个标记,当检测到了,他就认为这个是继任者MBR。
之后呢,BIOS将这512字节加载到0x7c00这个位置,然后jmp过去,这样就完成了权力的交接工作了,开始执行MBR中的代码了。

MBR的内容

终于到硬菜了,我们开始掌控操作系统了,从我们的MBR程序开始。以下代码是程序的内容,看不懂评论区留言。

;主引导程序
SECTION MBR vstart=0x7c00
    mov ax,cs           ;用cs寄存器去初始化其他寄存器
    mov ds,ax
    mov es,ax
    mov ss,ax
    mov fs,ax
    mov sp,0x7c00       ;初始化栈指针

; 清屏利用0x06号功能,上卷全部行,进行清屏
; int 0x10  功能号:0x60    功能描述:上卷窗口
; 输入:
; AH 功能号: 0x06
; AL = 上卷的行数(0代表全部)
; BH = 上卷的行属性
; (CL,CH) = 窗口左上角(x,y) 的位置
; (DL,DH) = 窗口右下角(x,y)的位置
; 无返回值!
    mov ax,0x600
    mov bx,0x700
    mov cx,0        ;左上角(0,0)
    mov dx,0x184f   ;右下角(80,25)
                    ;VAG文本模式中,一行只能容纳80个字符,总共25行
                    ;下标从0开始,所以0x18=24,0x4f=79
    int 0x10        ;系统调用号10

;下面三行汇编代码获取光标位置
; .get_cursor获取当前光标的位置,在光标位置处打印字符
    mov ah,3        ;输入:3号的子功能是获取光标位置,需要存入ah寄存器
    mov bh,0        ;bh寄存器存储的是待获取光标的页号

    int 0x10        ;输出:ch=光标开始行,cl=光标结束行
                    ;dh=光标所在行号,dl=光标所在列号

;打印字符串
;还是10h中断,不过这次调用13号子功能打印字符串
    mov ax,message
    mov bp,ax       ;es:bp 为串的首地址,es此时同cs一致,开头时已经为sreg初始化

;光标位置要用到寄存器dx中内容,cs中的光标位置可以忽略
    mov cx,12        ;cx为串长度,不包括结束符0的字符个数
    mov ax,0x1301   ;子功能号13是现实字符及属性,要存入ah寄存器
                    ;al设置写字符方式al=01:显示字符串,光标跟随移动
    mov bx,0x2      ;bh存储要显示的页号,此处是第0页
                    ;bl中是字符属性,属性黑底绿字(bl=02h)
    int 0x10        ;执行BIOS 0x10号中断

;程序悬停至此处
    jmp $

    message db "hello,world!"
    times 510-($-$$) db 0		;扩充成510字节
    db 0x55,0xaa

之后,我们调用nasm编译这段汇编代码:

# 编译命令
nasm -o mbr.bin mbr.S

然后使用dd工具将其写入我们之前创建的hd60M.img这个磁盘的第一个扇区中:

# 生成的可执行文件写入 hd60M.img 这个虚拟硬盘的 0盘 0道 1扇区中
# 记得 of后面换成自己的 bochs地址
sudo dd if=/home/ik/workspace/mbr.bin of=/bochs/bo_tmp/bin/hd60M.img bs=512 count=1 conv=notrunc

之后转到自己安装bochs的地方,执行以下命令运行,我们看一下结果:
Gos ——BIOS与继承者MBR

参考文献

[1] 深入理解计算机系统
[2] 操作系统真相还原
上一篇:污水回用处理 离不开MBR平板膜组件


下一篇:双系统安装和ros安装踩坑