《操作系统真象还原》学习笔记:第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中:

查看段寄存器:

相关推荐
(●—●)橘子……10 小时前
力扣第503场周赛练习理解
python·学习·算法·leetcode·职场和发展·周赛
AOwhisky12 小时前
MySQL 学习笔记(第一期):数据库基础与 MySQL 初探
运维·数据库·笔记·学习·mysql·云计算
try2find13 小时前
Agent学习之补充my_plan_solve_agent
学习
想你依然心痛14 小时前
HarmonyOS 6(API 23)实战:打造“光码智学舱“——AI编程学习新范式
学习·ar·ai编程·harmonyos·智能体
一口吃俩胖子15 小时前
【脉宽调制DCDC功率变换学习笔记023】渐进分析法
笔记·学习
m0_3771081415 小时前
pid学习
学习
爱喝水的鱼丶15 小时前
SAP-ABAP:SAP基础数据校验工具开发系列博客(共5篇)第三篇:SAP接口对接开发:实现数据的实时/批量校验交互
运维·数据库·学习·性能优化·sap·abap·经验交流
TE-茶叶蛋16 小时前
学习GitNexus中优雅的自动滚动:useAutoScroll Hook 实现
学习
小陈phd16 小时前
多模态大模型学习笔记(四十八)——从自然语言到 SQL:大模型时代结构化数据查询的技术革命与落地实践
笔记·sql·学习
星夜夏空9917 小时前
FreeRTOS学习(12)——任务通知
学习·性能优化