第二步 完善MBR

news2024/9/24 9:26:46

文章目录

  • 前言
  • 一、什么是MBR?
  • 二、我们需要什么样的MBR?
  • 三、设计我们的MBR!
    • 1、打印“1 MBR”
    • 2、加载次引导程序——loader
  • 四、实践检验!


查看系列文章点这里: 操作系统真象还原

前言

  在上一篇文章 第一步 从启动BIOS开始 中,我们介绍了BIOS系统,知道了它只负责做一些硬件检测和初始化的工作,然后控制权就到 MBR 手中了,那我们这一节就来介绍一下 MBR 是什么,又有什么作用叭!


一、什么是MBR?

  MBR 也叫做“ 主引导程序 ”,从名字不难看出,它是主要的引导程序。引导的程序就是“ 次引导程序 ”,可以叫做“ 内核加载器 ”,总的来说就是加载内核也就是操作系统的程序。

  也就是 MBR 并不加载操作系统,其原因在于有时候我们希望计算机可以在不同的分区使用不同的操作系统,所以 MBR 的工作就只能是挑选合适的“ 次引导程序 ”。至于BIOS为什么不直接完成挑选过程,原因很简单,因为空间太小不够用,心有余力不足。

二、我们需要什么样的MBR?

  知道了什么是 MBR 后,我们就来来编写属于我们的 MBR 了,首先我们先来看看真正的 MBR 是什么样的,如下所示:

  • 446字节的引导程序及参数;
  • 64字节的分区表;
  • 2字节的魔数,0x55和0xaa;

  这是真正的 MBR ,那我们的 MBR 并不需要和上述那样,因为我们注定只会加载我们自己以后编写的操作系统,因此我们不需要分区表,引导程序要实现的功能也仅仅是把“ 次引导程序 ”从磁盘加载到内存中,并跳转过去就可以了。

  但是为了方便我们看到结果,我们再在屏幕上输出一句话“1 MBR”,表示 MBR 被成功加载运行。

  解下来我们就要开始编写 MBR 了,如果你还不了解如何在屏幕输出内容请看x86 文本模式显示适配器,如果你还不知道如何操控硬盘,请看x86 汇编如何控制硬盘?。

三、设计我们的MBR!

  上一节我们已经讲了我们的 MBR 长什么样了,因此我们的程序的“ 主函数 ”就像下面展示的一样,非常简洁!

	mov eax, LOADER_START_SECTOR   ;待读入扇区的起始地址(0x2)
    mov bx, LOADER_BASE_ADDR       ;数据从硬盘读入后存放的地址(0x900)
    mov cx, 4                      ;待读入的扇区数目
                                   ;当前loader只有一点点大小,不过为了方便,直接设置为4
    call rd_disk_m_16              ;执行该函数在"16位模式下读硬盘"
    jmp LOADER_BASE_ADDR           ;跳转到LOADER程序

  可以看到我们将地址设置成了常量,因为以后还有非常多的常量,因此,我在code目录下新建目录include,并新建boot.inc文件,专门用来存储将来会用到的常量。
在这里插入图片描述

; 加载器在硬盘上的位置(LBA)
LOADER_START_SECTOR  equ 0x2

; 加载器加载到内存中的位置
LOADER_BASE_ADDR equ 0x900

  本节就一些关键步骤和代码做出解释说明,完整代码见文章末尾。

1、打印“1 MBR”

(1)清屏:

	mov ax, 0x0600   ;AL:上卷的行数(为0表示全部),AH:功能号,0x06表示清屏功能
    mov bx, 0x0700   ;上卷行属性
    mov cx, 0x0      ;左上角(0,0)
    mov dx, 0x184f   ;右下角(80,25),在VGA文本模式中,一行只能容纳80个字符,一共25行
    int 0x10         ;调用BIOS的视频服务中断

(2)打印:

	;0x1010 0100 -> 前景色(字的颜色)为红色,背景色为绿色,闪烁(字闪烁)
    mov byte [gs:0x00], '1'
    mov byte [gs:0x01], 0xA4
    mov byte [gs:0x02], ' '
    mov byte [gs:0x03], 0xA4
    mov byte [gs:0x04], 'M'
    mov byte [gs:0x05], 0xA4
    mov byte [gs:0x06], 'B'
    mov byte [gs:0x07], 0xA4
    mov byte [gs:0x08], 'R'
    mov byte [gs:0x09], 0xA4

2、加载次引导程序——loader

(1)第1步:设置带读入的扇区数

	mov dx, 0x1f2
    mov al,cl      ;使用cx寄存器存储待读入的扇区数
    out dx,al

(2)第2步:设置LBA地址

	;LBA地址7~0位写入端口0x1f3
    mov dx, 0x1f3
    out dx, al

    ;LBA地址15~8位写入端口0x1f4
    mov cl, 8
    shr eax, cl
    mov dx, 0x1f4
    out dx, al

    ;LBA地址23~16位写入端口0x1f5
    shr eax, cl
    mov dx, 0x1f5
    out dx, al

    ;设置device
    shr eax, cl
    and al, 0x0f   ;设置LB地址24~27位
    or al, 0xe0    ;0xe0 -> 11100000 ,设置7~4位为1110,表示为LBA模式
    mov dx, 0x1f6
    out dx, al     ;将配置信息写入端口0x1f6

(3)第3步:发送读命令

	mov dx, 0x1f7
    mov al, 0x20
    out dx, al

(4)第4步:检测硬盘状态

.not_ready:
    mov dx, 0x1f7   ;同一端口,写时表示写入命令,读时表示读入硬盘状态
    in al, dx
    and al, 0x88    ;第3位为1表示硬盘控制器已经准备好数据传输
                    ;第7位为1表示硬盘忙
    cmp al, 0x08
    jnz .not_ready  ;若为准备好,则跳回not_ready处继续等待

(5)第5步:从硬盘读数据

    mov ax, di   ;di为待读入的扇区数
    mov dx, 256  ;一个扇区512字节,每次读入一字,即两字节,共要读256次
    mul dx       ;乘扇区数
    mov cx, ax
    mov dx, 0x1f0

.go_on_read:
    in ax, dx
    mov [bx], ax      ;存入内存
    add bx, 2         ;指向下一个地址
    loop .go_on_read
    ret               ;返回

四、实践检验!

  现在我们来检验一下,我们的 MBR 是否编写正确,等一下,我们貌似还没有loader程序,虽然我们还不知道loader要干嘛,不过不妨碍我们验证 MBR,我们直接随便在code目录下新建一个假的loader,打印几个字符“2 LOADER”,宣告一下现在是我LOADER的天下啦!

%include "boot.inc"
; 加载器加载到内存中的位置
SECTION LOADER vstart=LOADER_BASE_ADDR

	mov byte [gs:0x50], '2'
    mov byte [gs:0x51], 0xA4
    mov byte [gs:0x52], ' '
    mov byte [gs:0x53], 0xA4
    mov byte [gs:0x54], 'L'
    mov byte [gs:0x55], 0xA4
    mov byte [gs:0x56], 'O'
    mov byte [gs:0x57], 0xA4
    mov byte [gs:0x58], 'A'
    mov byte [gs:0x59], 0xA4
    mov byte [gs:0x5a], 'D'
    mov byte [gs:0x5b], 0xA4
    mov byte [gs:0x5c], 'E'
    mov byte [gs:0x5d], 0xA4
    mov byte [gs:0x5e], 'R'
    mov byte [gs:0x5f], 0xA4
    
	jmp $

  下面我们来看看完整 MBR 长什么样。

%include "boot.inc"
SECTION MBR vstart=0x7c00
    ;初始化寄存器
	mov ax, cs
	mov ds, ax
	mov es, ax
	mov ss, ax
	mov fs, ax
	mov sp, 0x7c00
    ;图形卡文本模式的起始地址
	mov ax, 0xb800
	mov gs, ax

    ;清屏
    mov ax, 0x0600   ;AL:上卷的行数(为0表示全部),AH:功能号,0x06表示清屏功能
    mov bx, 0x0700   ;上卷行属性
    mov cx, 0x0      ;左上角(0,0)
    mov dx, 0x184f   ;右下角(80,25),在VGA文本模式中,一行只能容纳80个字符,一共25行
    int 0x10         ;调用BIOS的视频服务中断

    ;在屏幕上显示字符串"1 MBR"
    ;0x1010 0100 -> 前景色(字的颜色)为红色,背景色为绿色,闪烁(字闪烁)
    mov byte [gs:0x00], '1'
    mov byte [gs:0x01], 0xA4
    mov byte [gs:0x02], ' '
    mov byte [gs:0x03], 0xA4
    mov byte [gs:0x04], 'M'
    mov byte [gs:0x05], 0xA4
    mov byte [gs:0x06], 'B'
    mov byte [gs:0x07], 0xA4
    mov byte [gs:0x08], 'R'
    mov byte [gs:0x09], 0xA4

    ;接下来用eax,bx,cx三个寄存器传递参数,故先将值存进寄存器中
    mov eax, LOADER_START_SECTOR   ;待读入扇区的起始地址(0x2)
    mov bx, LOADER_BASE_ADDR       ;数据从硬盘读入后存放的地址(0x900)
    mov cx, 4                      ;待读入的扇区数目

    call rd_disk_m_16              ;执行该函数在"16位模式下读硬盘"
    jmp LOADER_BASE_ADDR           ;跳转到LOADER程序

; ============================================================
; 功能:读取硬盘n(由cx寄存器决定读几个扇区)个扇区
; ============================================================
rd_disk_m_16:
    ;备份eax,cx
    mov esi, eax
    mov di, cx

;第一步:设置要读取的扇区数
    mov dx, 0x1f2 
    mov al,cl
    out dx,al

	mov eax, esi

;第二步,将LBA地址存入0x1f3 ~ 0x1f6
    ;LBA地址7~0位写入端口0x1f3
    mov dx, 0x1f3
    out dx, al

    ;LBA地址15~8位写入端口0x1f4
    mov cl, 8
    shr eax, cl
    mov dx, 0x1f4
    out dx, al

    ;LBA地址23~16位写入端口0x1f5
    shr eax, cl
    mov dx, 0x1f5
    out dx, al

    ;设置device
    shr eax, cl
    and al, 0x0f   ;设置LB地址24~27位
    or al, 0xe0    ;0xe0 -> 11100000 ,设置7~4位为1110,表示为LBA模式
    mov dx, 0x1f6
    out dx, al     ;将配置信息写入端口0x1f6

;第三步:向0x1f7端口写入读命令(0x20)
    mov dx, 0x1f7
    mov al, 0x20
    out dx, al

;第四步:检测硬盘状态
.not_ready:
    ;同一端口,写时表示写入命令,读时表示读入硬盘状态
    nop
    in al, dx
    and al, 0x88    ;第3位为1表示硬盘控制器已经准备好数据传输
                    ;第7位为1表示硬盘忙
    cmp al, 0x08
    jnz .not_ready  ;若为准备好,则跳回not_ready处继续等待

;第五步:从0x1f0端口读入数据
    mov ax, di   ;di为待读入的扇区数
    mov dx, 256  ;一个扇区512字节,每次读入一字,即两字节,共要读256次
    mul dx
    mov cx, ax
    mov dx, 0x1f0

.go_on_read:
    in ax, dx
    mov [bx], ax
    add bx, 2
    loop .go_on_read
    ret

;填充空白符,保证整段程序大小为512字节
times 510-($-$$) db 0

;定义MBR中最后两个字节的魔数,表示这个扇区包含可加载的程序
db 0x55, 0xaa

  接下来就是编译和传输,如下:

  	nasm -I ./include/ -o mbr.bin mbr.S
  	dd if=./mbr.bin of=../bochs/hd60M.img bs=512 count=1 conv=notrunc

	nasm -I ./include/ -o loader.bin loader.S
	dd if=./loader.bin of=../bochs/hd60M.img bs=512 count=4 seek=2 conv=notrunc

  注意,传输loader的时候,跳过两个扇区,避免覆盖了我们的 MBR

在这里插入图片描述

  然后就可以运行我们的bochs啦!

在这里插入图片描述

  可以看到我们的 MBR 已经成功完成任务啦!


  持续更新中~~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1678016.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Centos7 配置 DNS服务器

Centos 7 配置DNS服务器 环境描述: 一台服务器和一台用于测试的客户机 服务器IP:192.168.200.132 客户机IP:192.168.200.143 服务器配置 yum install bind bind-utils -y #安装软件包vim /etc/named.conf //编辑named主配置文件listen-on p…

【校园论坛系统】分站式后台,多城市圈子论坛,校园圈子交流平台,二手发布市场,校园圈子论坛系统

简述 校园论坛系统是为学生们提供一个交流、分享信息、互相帮助的平台。它通常包括了各种分类的版块,例如学习交流、社团活动、二手交易、失物招领等等。用户可以在论坛上发帖,回复他人的帖子,也可以私信其他用户。此外,管理员还…

AIGC——Instant-Style文本到图像生成中的样式保留算法解析

0.概述 在过去的几年中,基于调整的扩散模型在广泛的图像个性化和定制任务中取得了显着的进展。然而,尽管有潜力,当前基于调整的扩散模型在生成和生成风格一致的图像方面仍然面临着一系列复杂的挑战,其背后可能有三个原因。首先&a…

单链表题-ysf-反转-中间节点-回文-合并-分割

环形链表的约瑟夫问题_牛客题霸_牛客网 经典的约瑟夫环 #include <stdint.h> #include <stdlib.h> //创建链表 typedef struct ListNode ListNode;ListNode* buyNode(int x){ListNode* newNode(ListNode*)malloc(sizeof(ListNode));if(newNodeNULL){exit(1);}newN…

特斯拉FSD的硬件演进与模型压缩技术解析

引言 随着自动驾驶技术的迅速发展&#xff0c;特斯拉的全自动驾驶&#xff08;FSD&#xff09;系统也在不断进化。最近&#xff0c;特斯拉开始采用端到端的模型来优化其FSD算法&#xff0c;这种变革引发了广泛关注。本文将探讨特斯拉FSD在车载计算能力和模型压缩技术方面的最新…

7集成学习评分卡

集成学习评分卡 学习目标 知道LightGBM基本原理掌握使用lightGBM进行特征筛选的方法1 Gradient Boosting算法回顾 Gradient Boosting 基本原理 训练一个模型m1,产生错误e1针对e1训练一个模型m2,产生错误e2针对e2训练第三个模型m3,产生错误e3 …最终预测结果是:m1+m2+m3+…GB…

基于死区补偿的永磁同步电动机矢量控制系统simulink仿真模型

整理了基于死区补偿的永磁同步电动机矢量控制系统simulink仿真&#xff0c;该模型使用线性死区补偿的PMSM矢量控制算法进行仿真&#xff0c;使用Foc电流双闭环 。 1.模块划分清晰&#xff0c;补偿前后仿真有对比&#xff0c;易于学习; 2.死区补偿算法的线性区区域可调; 3.自…

【计算机网络】HTTP协议详解实战抓包分析教程

文章目录 1.HTTP简介2.HTTP报文的结构3.HTTP协议中空行的作用4.uri和url的区别5.HTTP请求5.1 HTTP请求方法5.2 HTTP请求报头 6.HTTP响应6.1 状态码 7.HTTP位于应用层(基于TCP)8.非持久和持久连接8.1 非持久连接8.2 持久连接 1.HTTP简介 HTTP&#xff08;Hypertext Transfer Pr…

【考研数学】跟「武忠祥」真不如「张宇」吗??

现在是张宇老师强势版本&#xff01; 24年之前&#xff0c;你说跟武忠祥老师好&#xff0c;我非常赞成&#xff0c;但是24年很多同学考完出来都说&#xff0c;早知道跟张宇了&#xff0c;都说24年考研数学偏&#xff0c;怪&#xff0c;难&#xff0c;计算量还大。 武忠祥老师…

刷题之字母异位词(leetcode 哈希表)

https://leetcode.cn/problems/group-anagrams/ class Solution { public:vector<vector<string>> groupAnagrams(vector<string>& strs) {unordered_map<string,vector<string>>map;//哈希表键为排序后或者处理后的字符串&#xff0c;值为某…

Web课外练习7

<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>照片墙</title><style>body {display: …

P9748 [CSP-J 2023] 小苹果:做题笔记

目录 P9748 [CSP-J 2023] 小苹果 思路 代码 P9748 [CSP-J 2023] 小苹果 P9748 [CSP-J 2023] 小苹果 思路 先写几个看看规律 题意我们能看出来是三个三个一组的&#xff0c;然后每次取走的都是三个里面的第一个。我们应该很容易想到如果一轮的总数是三的倍数的话&#xff0…

Linux查看进程命令ps和top

Linux 是一种自由和开放源代码的操作系统&#xff0c;它的使用在全球范围内非常广泛。在 Linux 中&#xff0c;进程是操作系统中最重要的组成部分之一&#xff0c;它代表了正在运行的程序。了解如何查看正在运行的进程是非常重要的&#xff0c;因为它可以帮助你了解系统的运行状…

langchain_community FAISS保存与加载faiss index

参考: https://github.com/langchain-ai/langchain/issues/18285 https://api.python.langchain.com/en/latest/vectorstores/langchain_community.vectorstores.faiss.FAISS.html#langchain_community.vectorstores.faiss.FAISS 1、保存save_local import pandas as pd ##…

抓住无人直播带货风口,开启创业新机遇

无人直播带货&#xff0c;这一近年来在互联网浪潮中崭露头角的创业模式&#xff0c;正以其独特的魅力和优势&#xff0c;吸引着越来越多的创业者投身其中。在这个数字化、智能化的时代&#xff0c;无人直播带货 keJ0277 不仅降低了创业的门槛&#xff0c;还为创业者提供了全新的…

淘宝扭蛋机小程序:开启虚拟世界的惊喜之旅

随着科技的飞速发展&#xff0c;微信小程序已经成为了我们日常生活中不可或缺的一部分。淘宝扭蛋机小程序&#xff0c;作为这一潮流中的一颗璀璨新星&#xff0c;凭借其独特的创意和便捷的购物体验&#xff0c;迅速在电商领域崭露头角。 淘宝扭蛋机小程序的核心魅力在于其结合…

Cannot read properties of undefined (reading ‘init‘)报错

出现这个报错是印象项目没有引echarts包 npm i echarts 下包 然后在main.js中引入 import echarts from echarts Vue.prototype.$echarts echarts 如果还不行 import * as echarts from echarts; 更改一下引入方式 ok了

【Redis】数据类型

Redis数据类型&#xff08;5 3 1&#xff09; 五种基本数据类型 String字符串 特点 二进制安全&#xff0c;可以包含任何数据&#xff0c;如数字&#xff0c;字符串&#xff0c;jpg图片或者序列化的对象 应用场景 缓存&#xff1a; redis作为缓存层&#xff0c;mysql做持…

Nginx配置文件conf解释

系列文章目录 文章目录 系列文章目录前言 前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站&#xff0c;这篇文章男女通用&#xff0c;看懂了就去分享给你的码吧。 Nginx(“engine x”…

全域运营平台是什么?优缺点有哪些?

当下&#xff0c;全域运营赛道逐渐兴盛&#xff0c;全域运营服务商的数量也开始呈现爆发趋势。在此背景下&#xff0c;很多人都对某些品牌的全域运营平台优缺点产生了浓厚的兴趣。由于小编只使用过微火全域运营平台&#xff0c;因此&#xff0c;本期会着重分析微火运营平台的优…