从0写一个操作系统 | 02-BIOS和MBR主引导记录

BIOS

实模式

​ 实模式是什么呢,简单来讲就是只用物理地址的模式,因为最开始开机时还不存在页表,更不存在页映射一说,所以咱们最开始的地址只能通过物理地址来进行编程,并且此时编程也只能用汇编。
​ 而在Intel 8086时期只有20条地址线,也就是说若按字节寻址的话咱们的发挥空间就只有1MB,用16进制表示就是从0x00000到0xFFFFF,以下先给出实模式下的地址分布:

开始地址结束地址大小用途
FFFF0FFFFF16BBIOS入口,这么小的一个位置实际上仅仅是一个跳转指令
F0000FFFEF64KB-16B系统BIOS
C8000EFFFF160KB映射硬件适配器的ROM或内存映射式I/O
C0000C7FFF32KB显示适配器BIOS
B8000BFFFF32KB文本显示适配器
B0000B7FFF32KB黑白显示适配器
A0000AFFFF64KB彩色显示适配器
9FC009FFFF1KBEBDA
7E009FBFF约608KB可用
7C007DFF512BMBR加载地址
5007BFF约30KB可用
4004ff256BBIOS数据区域
0003FF1KB中断向量表

BIOS

​ 在0xF0000~0xFFFFF的64KB保存的是BIOS代码,而BIOS的功能就是检测初始化硬件。但是具体是如何初始化呢,硬件自身会实现一些初始化的功能调用,这里BIOS直接调用即可。除了上述功能BIOS还做了一件事,那就是建立中断向量表,这样咱们就可以通过"int 中断号"来进行硬件调用。
​ BIOS其实也是指令流,也是个程序,所以肯定也得有入口地址,这个入口地址便是0xFFFF0,这时候就得考虑如何找到这个地址了,这里有个既定规则,那就是实模式下寄存器宽度为16位,而程序一般都是通过分段机制来进行寻址,分段机制需要用到两个寄存器,那就是cs,ip,但是如何通过两个16位宽度的寄存器来表示20位的地址呢,那就是通过将cs的值左移四位,然后再加上ip地址值,这样就刚好是20位了。

主引导记录MBR

​ BIOS最后的工作就是检验0盘0道1扇区的内容,这里历史遗留问题所以说这里扇区是从1开始,大家不用刻意管这个,只需要记住BIOS最后检验的是地一个磁盘扇区即可,在检验过程中,若BIOS检验出该磁盘末尾两个字节是0x55和0xaa则认定其为活动区,便加载到物理地址0x7c00,然后跳转过去,即可开始执行MBR。

​ 这里的0x55,0xaa是一对魔数,表明这段程序的结尾。为什么是0x55和0xaa呢,我们转成二进制可以发现,这两个数是01010101和10101010,是连续的高低电平交替,这样不容易和正常代码混在一起。

  1. MBR大小为512字节
  2. 地511以及512字节必须是0xaa,0x55,这是由于咱们模拟的是x86平台,所以采用小端序

汇编编程基础

咱们本次的汇编采用NASM编译器,所以采用他的编译规则,其中比较常用的符号这里得讲讲:

  • $:表示当前汇编代码行地址
  • $$:表示本section地址
  • section: 汇编代码中的节,这是程序员自行设定的,声明自己这个是个干什么的节

NASM简单用法

nasm -f <format><filename> [-o <output>]

其中-f就是指定输出文件格式。

编写思路

  1. 首先清屏,这里利用了BIOS所建立的中断向量表,用0x06号功能,即int 0x10,而我们实现系统调用的操作只需我们将功能号送入ah(注意是ah,也就是说向ax中传入0x600)寄存器,然后执行int 0x10即可。

  2. 而在我们编写的section后面加上vstart=0x7c00表示告诉编译器把我这个起始地址编译为0x7c00

  3. 然后我们再通过中断3号功能来获取光标位置

  4. 然后我们来实现打印字符串,此刻由于我们未使用IO知识,所以我们还是用中断向量来实现(现在知道BIOS的伟大之处了),运用13号子功能

  5. 最后两字节填充0xaa55

代码实现

;主引导程序
;------------------------------------------
SECTION MBR vstart=0x7c00   ; 向编译器表示咱们这儿起始地址应为0x7c00
  mov ax,cs
  mov dx,ax                 ; 由于BIOS通过 0:0x7c00跳转MBR,所以此时cs为0,因此借他来初始化寄存器
  mov es,ax
  mov ss,ax
  mov fs,ax
  mov sp,0x7c00
; 清屏利用0x06号子功能,上卷全部行即可清屏
;-------------------------------------------
;INT 0x10    功能号:0x06    功能:上卷窗口
;-------------------------------------------
;输入:
;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     ; 右下角(0x4f,0x18),在VGA文本模式中一行只能容纳80字符
  int 0x10

;;;;;;;; 下面三行获取光标位置 ;;;;;;;;;;;;;;;
; ,get_cursor获取光标位置,并在光标位置打印字符
  mov ah,3          ;输入: 3号子功能即为获取当前光标位置
  mov bh,0          ;bh 寄存器存储的是待获取光标的页号

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

;;;;;;;;;;; 打印字符串 ;;;;;;;;;;;;;;;;
;依旧用中断的0x13号子功能
  mov ax, message       ;文件末会声明此字符串
  mov bp, ax            ;es:bp为串首地址,es此时由于最开始的初始化,同cs一致
;光标位置需要用到dx寄存器内容,cx中的光标位置可忽略
  mov cx,0xa              ;cx 为串长度,不包括结束副\x00
  mov ax,0x1301         ;ah=13为显示字符功能号
                        ;al = 01 表示该功能的模式,具体模式有以下几种
                        ;(1)0,显示字符串,光标返回起始位置
                        ;(2)1,显示字符串,光标跟随到新位置
                        ;(3)2,显示字符串以及属性,光标返回起始位置
                        ;(4)3,显示字符串以及属性,光标跟随到新位置
  mov bx,0x2            ;bh存储要显示的页号,此时为0页,bl中是字符属性,bl=02h表示黑底绿字
  int 0x10              ; 执行BIOS 0x10中断
;;;;;;;;;; 打印字符串结束 ;;;;;;;;;;;;;;;
  jmp $                 ;悬停指针

  message  db "Hello lfh"
  times 510-($-$$) db 0     ;$-$$表示该指令行距离section起始地址的偏移,这里也可表示为目前指令大小
  db 0x55,0xaa

汇编

运用我们之前的知识

nasm -o mbr.bin mbr.S

之后咱们用ls查看下是否512字节,利用ls即可验证

-rw-rw-r-- 1 dawn dawn 512 Dec 26 07:41 mbr.bin

咱们会发现确实无误,这样咱们就可以做接下里的步骤,那就是把咱们的MBR程序给拷到磁盘上,而Linux本身提供了一个dd命令,他被成为穿甲弹,他可以深入磁盘任何一个扇区,这里给出几个选项的示意:

  • of=FILE 指定要读的文件
  • bs=BYTES 指定块大小
  • count=BLOCKS 指定块数
  • seek=BLOCKS 制定当我们把块输出到文件是要跳过多少块
  • conv=CONVS 指定如何转换文件

介绍结束,之后我们使用这个命令将mbr.bin打入相应磁盘扇区,也就是第一快512扇区,还记得之前那个0,0,1吗,就是BIOS结束的工作所找寻的快

dd if=/你的路径/mbr.bin of=/你的路径/bochs/hd60M.img bs=512 count=1 conv=notrunc

执行完出现以下提示即表示成功打入

测试代码

bin/bochs -f bochsrc.disk

我们在最开始执行的指令也可以发现这个就是jmp,跟我们最开始说BIOS执行的第一条指令的论述是完全一致的!
在这里插入图片描述
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值