《操作系统真象还原》学习笔记:第2章——编写MBR主引导记录

2.1 计算机的启动过程

载入内存:

(1) 程序被加载器(软件或硬件)加载到内存某个区域

(2)CPU 的 cs:ip 寄存器被指向这个程序的起始地址

2.2 软件接力第一棒,BIOS

2.2.1 实模式下的 1MB 内存布局

Intel 8086 有 20 条地址线,故其可以访问 1MB 的内存空间,即2的20次方=1048576=1MB。

实模式下的内存布局如下:

(1)在电脑未开机前,BIOS就被事先写入到内存的F0000~FFFFF中,此区域为ROM,这里面存的是 BIOS 的代码。BIOS的主要工作是检测、初始化硬件,建立中断向量表。

(2)除了内存条,还有一些外设同样是需要通过地址总线来访问。

2.2.2 BIOS 是如何苏醒的

在开机的一瞬间,CPU的cs:ip寄存器被强制初始化为0xF000: 0xFFF0,由于开机的时候处于实模式,按照实模式的寻址方式段基地址要乘以16,也就是左移4位,然后再加上段内偏移地址,则计算得这个实际的物理地址为0xFFFF0,此地址便是BIOS程序的入口地址。而从地址0xFFFF0~0xFFFFF只有16B的空间,这说明BIOS真正的执行脚本并不存储在这里,开机后执行的第一条语句一定是跳转语句jmp,其实执行的第一条语句是:

bash 复制代码
jmp far f000:e05b

跳转到了0xfe05b处,说明这里才是BIOS代码真正开始的地方。接下来就是BIOS不断进行检测内存,显卡等外设信息,然后初始化硬件的过程了。

2.2.3 为什么是 0x7c00

BIOS 最后一项工作校验启动盘中位于0盘0道1扇区的内容。如果此扇区末尾的两个字节分别是魔数0x550xaa,BIOS便认为此扇区中确实存在可执行的程序,并把这个扇区的内容加载到物理地址0x7c00的内存中。

2.3 实验

任务:

(1)完成mbr主引导记录的代码编写,并完成编译,完成的代码编译并非真正的MBR主引导程序,而是为了测试mbr程序是否会被加载到0x07c00处被正确执行。

(2)将编译生成的主引导记录内容刻录到我们的创建的启动硬盘中。
创建mbr.s文件:

(1)文件功能:在屏幕上打印字符串"1 MBR",背景色为黑色,前景色(字体颜色)为绿色.

(2)功能实现方式:借助BIOS建立好的例程0x10号中断,可将0x10号中断看做一个函数,这个函数不同的输入可实现不同的功能,因此要有一个参数表示要实现的功能,也就是接下来要说的功能号参数。
代码:

bash 复制代码
; ~/d2los/src/mbr.S
; MBR主引导程序
;------------------------------------------------------------
SECTION MBR vstart=0x7c00         
   mov ax,cs      
   mov ds,ax
   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      ; 右下角: (80, 25),
                           ; VGA文本模式中, 一行只能容纳80个字符, 共25行.
                           ; 下标从0开始, 所以0x18=24, 0x4f=79
   int     0x10            ; int 0x10

; 获取光标位置
; -----------------------------------------------------------
; .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寄存器中的内容, cx中的光标位置可忽略
   mov cx, 5                ; cx 为字符串长度, 不包括结束符0的字符个数
   mov ax, 0x1301           ; 子功能号13是显示字符串及属性, 要存入ah寄存器,
                            ; al设置显示字符方式 ah=01: 显示字符串,光标跟随移动
   mov bx, 0x2              ; bh存储要显示的页号, 此时是第0页,
                            ; bl中是字符属性, 属性黑底绿字(bl = 02h)
   int 0x10                 ; 执行BIOS 0x10 号中断

; 打印字符串结束
; -----------------------------------------------------------

   jmp $                    ; 使程序停在此处

   message db "1 MBR"
   times 510-($-$$) db 0
   db 0x55,0xaa

编译mrb.S文件:

bash 复制代码
nasm -o test mbr.s

将文件内容写入0盘0道1扇区:

bash 复制代码
dd if=/home/abc/Desktop/Bochs/mbr.bin of=/home/abc/Desktop/Bochs/Seven.img bs=512 count=1 seek=0 conv=notrunc

启动bochs查看结果:

bash 复制代码
bin/bochs -f bochsrc.disk

0x7c00处打断点,可以看到将0x0000的值移入cs中:

查看段寄存器:

相关推荐
xiaoyalian19 分钟前
横截面数据回归
笔记·学习·数据挖掘·回归·r语言
王红花x30 分钟前
STL——list模拟实现
c++·学习·list
Sam902940 分钟前
《昇思 25 天学习打卡营第 11 天 | ResNet50 图像分类 》
学习·分类·数据挖掘
鸽芷咕1 小时前
【python学习】快速了解python基本数据类型
开发语言·python·学习
我是陈泽1 小时前
AI教你如何系统的学习Python
开发语言·数据结构·人工智能·python·学习·青少年编程
hello-alien2 小时前
ASP.NET Core----基础学习04----Model模型的创建 & 服务的注入
学习·c#·asp.net·model
细心的莽夫3 小时前
集合复习(java)
java·开发语言·笔记·学习·java-ee
Caramel_biscuit3 小时前
C++专业面试真题(1)学习
c++·学习·面试
yours_Gabriel3 小时前
java基础:面向对象(二)
java·开发语言·笔记·学习
古月居GYH3 小时前
Autoware内容学习与初步探索(一)
学习