《操作系统真象还原》第二章——编写MBR主引导记录

2024-03-12 01:28

本文主要是介绍《操作系统真象还原》第二章——编写MBR主引导记录,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前置知识

通用寄存器介绍

如图所示,8086处理器内部有8个16位的通用寄存器,都是由16比特组成的,并分别被命名为AX、BX、CX、DX、SI、DI、BP、SP。

8个寄存器中的前4个,即AX、BX、CX和DX,又各自可以拆分成两个8位的寄存器来使用,总共可以提供8个8位的寄存器AH、AL、BH、BL、CH、CL、DH和DL。此外,将一个16位的寄存器当成两个8位的寄存器来用时,对其中一个8位寄存器的操作不会影响到另一个8位寄存器

以寄存器AX为例,它可以分成两个独立的寄存器AH和AL。寄存器AX有16比特,但是,位0到位7这8比特属于寄存器AL;位8到位15这8比特属于寄存器AH。因此,我们说,寄存器AH是寄存器AX的高字节部分;寄存器AL是寄存器AX的低字节部分。同时,寄存器AX的内容也是由寄存器AH的内容和寄存器AL的内容组合而成的。

 mov指令

  • 作用:数据传送
  • 格式
    • 目的操作数:必须是寄存器或者内存单元
    • 源操作数:和目的操作数具有相同数据宽度的寄存器、内存单元或者立即数

注意

  • mov指令的目的操作数不允许是立即数
  • 目的操作数和源操作数不允许同时为内存单元

mov只允许以下格式的指令

mov 段寄存器,通用寄存器

mov 段寄存器,内存单元

计算机的启动过程

计算机的加电和复位

计算机开始启动时,就会给处理器进行加电,同时处理器此时就会执行硬件初始化,然后将内部寄存器的内容初始化到预置的状态。

在INTEL8086处理器中,初始化操作将使代码段寄存器(CS)的内容置为0xFFFF,其他所有寄存器中的内容全部为0x0000,包括指令指针寄存器(IP)

这是有原因的,因为此时CS=0xFFFF,IP=0x0000,因此处理器要取的第一条指令就位于0xFFFF0,这正是BIOS的入口地址。如图所示,正好位于ROM中,而ROM中固化了开机时需要的指令。

另一方面,处理器取指令执行的自然顺序是从内存的低地址往高地址推进。如果从0xFFFF0开始执行,这个位置离1MB内存的顶端(物理地址0xFFFFF)只有16字节的长度,一旦IP寄存器的值超过0x000F,比如IP=0x0011,那么,它与CS一起形成的物理地址将因为溢出而变成0x00001,这将回绕到1MB内存的最底端。所以,ROM中位于物理地址0xFFFF0的地方,通常是一个跳转指令,它通过改变CS和IP的内容,使处理器从ROM中的较低地址处开始取指令执行。如:

jmp 0xf000:0xe05b

在这里,“jmp”是跳转(jump)的简化形式;0xf000是要跳转到的段地址,用来改变CS寄存器的内容;0xe05b是目标代码段内的偏移地址,用来改变IP寄存器的内容。因此,目标位置的物理地址是0xfe05b。一旦执行这条指令,处理器将开始从指定的“段:偏移”处开始重新取指令执行

ROM-BIOS的容量是有限的,当它完成自己的使命后,最后所要做的,就是从辅助存储设备(如硬盘)读取指令数据,然后转到那里开始执行。

硬盘的第一个扇区是0面0道1扇区,或者说是0头0柱1扇区,这个扇区称为主引导扇区。如果计算机的设置是从硬盘启动的,那么,ROM-BIOS将读取硬盘主引导扇区的内容,将它加载到内存地址0x0000:0x7c00(也就是物理地址0x07C00),然后用一个jmp指令跳到那里接着执行。

jmp 0x0000,0x7c00

总结

BIOS的功能

  • 内存、硬件检测
  • 硬件初始化
  • 建立中断向量表

MBR主引导扇区的内容为

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

本章节任务

  1. 完成mbr主引导记录的代码编写,并完成编译,本节完成的代码编译并非真正的MBR主引导程序,而是为了进行测试
  2. 将编译生成的主引导记录内容刻录到我们的创建的启动硬盘中

创建mbr.S文件

  • 文件功能:在屏幕上打印字符串“1 MBR”,背景色为黑色,前景色(字体颜色)为绿色
  • 功能实现方式:借助BIOS建立好的例程0x10号中断,可将0x10号中断看做一个函数,这个函数不同的输入可实现不同的功能,因此要有一个参数表示要实现的功能,也就是接下来要说的功能号参数
  • 0x10号中断调用方式:
    • 将功能号送入ah寄存器,不同的功能号代表不同的功能
    • 其余输入参数可依据具体的功能将参数送入不同的寄存器即可

内容如下

;主引导程序MBR,由BIOS通过jmp 0:0x7c00跳转;------------------------------------------
;vstart=0x7c00表示本程序在编译时,起始地址编译为0x7c00
SECTION MBR vstart=0x7c00
;使用通用寄存器中的值(0)初始化其余寄存器mov ax,csmov ds,axmov es,axmov ss,axmov fs,ax
;初始化栈指针mov sp,0x7c00
;------------------------------------------;------------------------------------------
;利用0x06号功能进行清屏
;INT 0x10 功能号:0x06 功能描述:上卷窗口清屏
;输入:;AH 功能号:0x06;AL=上卷的行数(如果为0,则表示全部);BH=上卷的行属性;(CL,CH)=窗口左上角(X,Y)位置;(DL,DH)=窗口右下角(X,Y)位置
;返回值;无返回值mov ax,0x0600mov bx,0x0700mov cx,0        ;左上角(0,0)mov dx,0x184f   ;右下角(80,25);0x18=24,0x4f=79int 0x10        ;调用BIOS中断函数
;------------------------------------------;------------------------------------------
;获取光标位置
;功能号:3
;输入:;ah:3;bh:存储待获取光标的页号
;输出:;ch=光标开始行,cl=光标结束行;dh=光标所在行号,cl=光标所在列号mov ah,3mov bh,0int 0x10
;------------------------------------------;------------------------------------------
;打印字符串,使用13号子功能mov ax,message
;es:bp为串首地址,es与cs的值一样,开始已经被初始化mov bp,ax
;光标位置使用dx中的内容,cx中的内容可忽略
;cx为串的长度,不包括结束符0的字符个数mov cx,5
;ah=13表示使用13号子功能
;AL=01表示设置写字符的方式,其中01表示显示字符串并跟随光标移动mov ax,0x1301
;bh存储要显示的页号,此处是第0页
;bl是字符属性,02h表示黑底绿字mov bx,0x2int 0x10jmp $
;定义打印的字符串message db "1 MBR"times 510-($-$$) db 0db 0x55,0xaa

编译mrb.S文件

nasm -o mbr.bin mbr.S

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

dd if=/home/minios/osCode/mbr.bin of=/home/minios/bochs/hd60M.img conv=notrunc

其中

  • notrunc 表示 "no truncate",即不截断文件。这意味着如果输出文件(/home/minios/bochs/hd60M.img)的大小小于输入文件(/home/minios/osCode/mbr.bin)的大小,那么输出文件将不会被截断,而是保留原有的大小,并且只覆盖输出文件的前面部分。

启动bochs查看结果

./bin/bochs -f boot.disk

如上所示,运行成功! 

参考

《x86汇编语言:从实模式到保护模式》

《操作系统真象还原》

这篇关于《操作系统真象还原》第二章——编写MBR主引导记录的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/799718

相关文章

Python获取中国节假日数据记录入JSON文件

《Python获取中国节假日数据记录入JSON文件》项目系统内置的日历应用为了提升用户体验,特别设置了在调休日期显示“休”的UI图标功能,那么问题是这些调休数据从哪里来呢?我尝试一种更为智能的方法:P... 目录节假日数据获取存入jsON文件节假日数据读取封装完整代码项目系统内置的日历应用为了提升用户体验,

Spring Boot 配置文件之类型、加载顺序与最佳实践记录

《SpringBoot配置文件之类型、加载顺序与最佳实践记录》SpringBoot的配置文件是灵活且强大的工具,通过合理的配置管理,可以让应用开发和部署更加高效,无论是简单的属性配置,还是复杂... 目录Spring Boot 配置文件详解一、Spring Boot 配置文件类型1.1 applicatio

MySQL INSERT语句实现当记录不存在时插入的几种方法

《MySQLINSERT语句实现当记录不存在时插入的几种方法》MySQL的INSERT语句是用于向数据库表中插入新记录的关键命令,下面:本文主要介绍MySQLINSERT语句实现当记录不存在时... 目录使用 INSERT IGNORE使用 ON DUPLICATE KEY UPDATE使用 REPLACE

Python 中的异步与同步深度解析(实践记录)

《Python中的异步与同步深度解析(实践记录)》在Python编程世界里,异步和同步的概念是理解程序执行流程和性能优化的关键,这篇文章将带你深入了解它们的差异,以及阻塞和非阻塞的特性,同时通过实际... 目录python中的异步与同步:深度解析与实践异步与同步的定义异步同步阻塞与非阻塞的概念阻塞非阻塞同步

Python Dash框架在数据可视化仪表板中的应用与实践记录

《PythonDash框架在数据可视化仪表板中的应用与实践记录》Python的PlotlyDash库提供了一种简便且强大的方式来构建和展示互动式数据仪表板,本篇文章将深入探讨如何使用Dash设计一... 目录python Dash框架在数据可视化仪表板中的应用与实践1. 什么是Plotly Dash?1.1

Spring Boot中定时任务Cron表达式的终极指南最佳实践记录

《SpringBoot中定时任务Cron表达式的终极指南最佳实践记录》本文详细介绍了SpringBoot中定时任务的实现方法,特别是Cron表达式的使用技巧和高级用法,从基础语法到复杂场景,从快速启... 目录一、Cron表达式基础1.1 Cron表达式结构1.2 核心语法规则二、Spring Boot中定

国内环境搭建私有知识问答库踩坑记录(ollama+deepseek+ragflow)

《国内环境搭建私有知识问答库踩坑记录(ollama+deepseek+ragflow)》本文给大家利用deepseek模型搭建私有知识问答库的详细步骤和遇到的问题及解决办法,感兴趣的朋友一起看看吧... 目录1. 第1步大家在安装完ollama后,需要到系统环境变量中添加两个变量2. 第3步 “在cmd中

基于.NET编写工具类解决JSON乱码问题

《基于.NET编写工具类解决JSON乱码问题》在开发过程中,我们经常会遇到JSON数据处理的问题,尤其是在数据传输和解析过程中,很容易出现编码错误导致的乱码问题,下面我们就来编写一个.NET工具类来解... 目录问题背景核心原理工具类实现使用示例总结在开发过程中,我们经常会遇到jsON数据处理的问题,尤其是

Spring Retry 实现乐观锁重试实践记录

《SpringRetry实现乐观锁重试实践记录》本文介绍了在秒杀商品SKU表中使用乐观锁和MybatisPlus配置乐观锁的方法,并分析了测试环境和生产环境的隔离级别对乐观锁的影响,通过简单验证,... 目录一、场景分析 二、简单验证 2.1、可重复读 2.2、读已提交 三、最佳实践 3.1、配置重试模板

在 Spring Boot 中使用异步线程时的 HttpServletRequest 复用问题记录

《在SpringBoot中使用异步线程时的HttpServletRequest复用问题记录》文章讨论了在SpringBoot中使用异步线程时,由于HttpServletRequest复用导致... 目录一、问题描述:异步线程操作导致请求复用时 Cookie 解析失败1. 场景背景2. 问题根源二、问题详细分