第二章 编写MBR主引导记录
主引导记录(MBR,Master Boot Record)是采用MBR分区表的硬盘的第一个扇区,即C/H/S地址的0柱面0磁头1扇区,也叫做MBR扇区
计算机的启动过程
为什么程序要载入内存
CPU的硬件电路被设计成只能运行处于内存中的程序,一来内存比较快且容量大,二是为了方式的统一。
什么是载入内存
BIOS
从按下主机上的power键后,第一个运行的软件就是BIOS(Base Input & Output System,基本输入输出系统)
实模式下的1MB内存布局
Intel8086 有20条地址线,故其可以访问1MB的内存空间,即2的20次方=1MB,地址范围若按十六进制来表示,是0x00000-0xfffff。
0-0x9FFFF 640KB DRAM(动态随机访问内存),动态指此种存储介质由于本身电气元件的性质,需要定期地刷新(补充电,掉电后数据会消失)物理内存
0xF0000-0xFFFFF 64KB ROM 存放BIOS代码
BIOS 的主要工作是检测、初始化硬件,建立中断向量表,BIOS建立的这些功能就是对硬件的IO操作,也就是输入输出。
在CPU眼里,为什么我们插在主板上的物理内存不是它眼里“全部的内存”
地址总线宽度决定了可以访问的内存空间大小,由于还有一些外设同样需要通过地址总线来访问,需要在地址总线上提前预留出一些地址空间给这些外设用。
地址总线是决定我们访问哪里、访问什么,以及访问范围的关键。CPU能够访问一个地址,这是地址总线给做的映射,相当于给该地址分配了一个存储单元,而该存储单元要么落在某个ROM中,要么落到了某个外设的内存中,要么落到了物理内存条上。
BIOS是如何苏醒的
实模式只能访问1MB空间,而地址0xFFFF0距1MB只有16字节,超过就会溢出。说明这里的代码只是各跳转指令,跳转到下一条待执行指令的地址。段基址0xf000左移4位+0xe05b,即跳向了0xfe05b处,这是BIOS代码真正开始的地方。
为什么是0x7c00
BIOS最后一项工作校验启动盘中位于0盘0道1扇区(磁盘上最开始的那个扇区)的内容。如果此扇区末尾的两个字节分别是魔数0x55和0xaa,BIOS便认为此扇区中确实存在可执行的程序,便加载到物理地址0x7c00,随后跳转到此地址,继续执行。
为什么是0盘0道1扇区的内容
这是磁盘的第一个扇区,离BIOS近,好找
为什么是物理地址0x7c00
BIOS规范
加载MBR的位置取决于操作系统本身所占内存大小和内存布局。
编写MBR
MBR的大小必须是512字节(每个扇区大小是512字节),这是为了保证0x55和0xaa这两个魔数恰好出现在该扇区的最后两个字节处,即第510字节处和511字节处,这是按起始偏移为0 算起的。由于bochs模拟的是x86平台,所以是小端字节序,故其最后两个字节内容是0xaa55。
$ , $$, section
$ 属于“隐式地”藏在本行代码前的标号,也就是编译器给当前行安排的地址。
$$指代本section的起始地址,此地址同样是编译器给安排的。
在默认情况下,它们的值是相对于本文件开头的偏移量。如果该section用来vstart=xxxx修饰, $ $的值则是此section的虚拟起始地址xxxx。 $的值是以xxxx为起始地址的顺延。如果没有定义section,nasm默认全部代码同为一个section,起始地址为0。
section是给开发人员逻辑上规划代码用的,只起到思路清晰的作用,最终还是在编译阶段由nasm在物理上的规划说了算。
NASM 简单用法
nasm的基本用法格式如下,-f是用来指定输出可执行文件的格式,-o是指定输出可执行文件的名称,nasm -hf
可以查看有效格式,bin是默认输出格式(不需要用-f)
MBR
代码功能:在屏幕上打印字符串“1 MBR”,背景色为黑色,前景色为绿色
设置程序起始地址,BIOS通过跳转到地址0x7c00
SECTION MBR vstart=0x7c00
用cs寄存器的值去初始化其他寄存器,cs的值赋值给ax,ax赋值给其他寄存器(CPU不能直接给它们赋值),此时cs=0
mov ax,cs
mov ds,ax
mov es,ax
mov ss,ax
mov fs,ax
初始化栈指针
mov sp,0x7c00
清屏。先把BIOS的输出清掉
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 寄存器存储的是待获取光标的页号,第0页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: 显示字符串,光标跟随移动
;(1)al=0,显示字符串,并且光标返回起始位置。
;(2)al=1,显示字符串,并且光标跟随到新位置。
;(3)al=2,显示字符串及其属性,并且光标返回起始位置。
;(4)al=3,显示字符串及其属性,光标跟随到新位置。
mov bx, 0x2 ; bh 存储要显示的页号,此处是第 0 页,
; bl 中是字符属性,属性黑底绿字(bl = 02h)
int 0x10 ; 执行 BIOS 0x10 号中断
死循环。$是本行执行指令地址, $是jmp自己的地址,一直跳自己的地址,死循环
jmp $ ; 使程序悬停在此
定义打印的字符串
message db "1 MBR"
用0将本扇区剩余空间填满
$ $是指本section的起始地址, $- $ $是本行到本section的偏移量。由于MBR最后两个字节是固定内容,分别是0x55和0xaa,要预留出2个字节,故本扇区内前512-2=510字节要填满,用510字节减去上面得到的偏移量,其结果便是本扇区内的剩余量,也就是要填充的字节。
times 510-($-$$) db 0
;主引导程序
;------------------------------------------------------------
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: 显示字符串,光标跟随移动
;(1)al=0,显示字符串,并且光标返回起始位置。
;(2)al=1,显示字符串,并且光标跟随到新位置。
;(3)al=2,显示字符串及其属性,并且光标返回起始位置。
;(4)al=3,显示字符串及其属性,光标跟随到新位置。
mov bx, 0x2 ; bh 存储要显示的页号,此处是第 0 页,
; bl 中是字符属性,属性黑底绿字(bl = 02h)
int 0x10 ; 执行 BIOS 0x10 号中断
;;;;;;;;; 打字字符串结束 ;;;;;;;;;;;;;;;jmp $ ; 使程序悬停在此message db "1 MBR"
times 510-($-$$) db 0
db 0x55,0xaa
本段关于“打印显示”的操作都利用BIOS给我们建立好的例程,0x10号中断就是负责有关打印的例程。
0x10中断是最为强大的BIOS中断,调用的方法是把功能号送入ah寄存器,其他参数按照BIOS中断手册要求放在适当的寄存器中,随后执行int 0x10即可。
编译汇编代码
nasm mbr.S -ombr.bin
查看刚才编译好的mbr.bin
正好是512字节
ls -lb mbr.bin
Linux命令:dd。用于磁盘操作的命令。
将MBR文件写入0盘0道1扇区
dd if=mbr.bin of=hd60M.img ibs=512 count=1 conv=notrunc
启动bochs
bochs -f bochsrc
相关文章:

第二章 编写MBR主引导记录
主引导记录(MBR,Master Boot Record)是采用MBR分区表的硬盘的第一个扇区,即C/H/S地址的0柱面0磁头1扇区,也叫做MBR扇区 计算机的启动过程 为什么程序要载入内存 CPU的硬件电路被设计成只能运行处于内存中的程序&…...

Android 9.0 仿ios的hotseat效果修改hotseat样式
1.概述 在9.0的系统rom定制化的产品中,在launcher3的定制化需求中,有很多功能需求点需要开发,在对一下ui的定制化的过程中,会参考ios的样式进行定制化,所以最近项目需求 要求仿ios的hotseat的样式来进行产品的定制,开发一款仿ios的hotseat,所以需要对hotseat进行分析,然…...

量化私募投资百亿头部量化私募企业在招岗位:AI算法工程师21/22/23届,校招/秋招/社招都看年base60-200万
量化私募投资百亿头部量化私募企业在招岗位:AI算法工程师21/22/23届,校招/秋招/社招都看年base60-200万bonuscut965制度应届需要985本硕博有3年以上相关ai算法经验可放宽学历"岗位职责:base 北京 上海 杭州 深圳1. 利用机器学习、深度学习和人工智能…...

百度西交大大数据菁英班目标检测竞赛
来源:投稿 作者:LSC 编辑:学姐 数据介绍 数据集共包括40000张训练图像和1000张测试图像,每张训练图像对应xml标注文件: 共包含3类:0:head, 1:helmet, 2:person。 提交格式要求,提交名为pred_r…...

Redisson实现分布式锁
目录Redisson简介Redisson实现分布式锁步骤引入依赖application.ymlRedisson 配置类Redisson分布式锁实现Redisson简介 Redis 是最流行的 NoSQL 数据库解决方案之一,而 Java 是世界上最流行(注意,没有说“最好”)的编程语言之一。…...

【HID基础知识】
蓝牙HID基础知识 一:定义 HID是Human Interface Device的缩写,由其名称可以了解HID设备是直接与人交互的设备,例如键盘、鼠标与游戏手柄等。 蓝牙HID 是属于蓝牙协议里面的一个profile, 不管在蓝牙2.0 2.1 3.0还是4.0,5.0的蓝牙中…...

工赋开发者社区 | 工业数字孪生:西门子工业网络与设备虚拟调试案例(TIA+MCD+SINETPLAN)
PART1案例背景及基本情况新生产系统的设计和实施通常是耗时且高成本的过程,完成设计、采购、安装后,在移交生产运行之前还需要一个阶段,即调试阶段。如果在开发过程中的任何地方出现了错误而没有被发现,那么每个开发阶段的错误成本…...

将闲置的Ipad作为Windows的副屏(Twomon SE)
目录一、前言二、方法第一步 安装软件第二步 使用步骤三、注意一、前言 在看网课的时候,总有种不得劲的感觉,来来回回的切换就很糟心~~无意间看见闲置的板砖(Ipad),计上心来-- _ – 期间也尝试过免费的软件ÿ…...

浮点数在内存中的存储——“C”
各位CSDN的uu们你们好呀,今天,小雅兰的内容是浮点数在内存中的存储,昨天我们已经写过了整型在内存中的存储,那么,浮点数在内存中是怎样存储的呢?现在,就让我们进入浮点数在内存中的存储的世界吧…...

华为OD机试 C++ 实现 - 租车骑绿岛
最近更新的博客 华为OD机试 - 入栈出栈(C++) | 附带编码思路 【2023】 华为OD机试 - 箱子之形摆放(C++) | 附带编码思路 【2023】 华为OD机试 - 简易内存池 2(C++) | 附带编码思路 【2023】 华为OD机试 - 第 N 个排列(C++) | 附带编码思路 【2023】 华为OD机试 - 考古…...

Spring Cloud Nacos源码讲解(三)- Nacos客户端实例注册源码分析
Nacos客户端实例注册源码分析 实例客户端注册入口 流程图: 实际上我们在真实的生产环境中,我们要让某一个服务注册到Nacos中,我们首先要引入一个依赖: <dependency><groupId>com.alibaba.cloud</groupId><…...

位运算(C/C++)
1. 基础知识 程序中的所有数在计算机内存中都是以二进制的形式储存的。位运算就是直接对整数在内存中的二进制位进行操作。比如,and运算本来是一个逻辑运算符,但整数与整数之间也可以进行and运算。举个例子,6的二进制是110,11的二…...

哈希表题目:设计哈希映射
文章目录题目标题和出处难度题目描述要求示例数据范围前言解法一思路和算法代码复杂度分析解法二思路和算法代码复杂度分析题目 标题和出处 标题:设计哈希映射 出处:706. 设计哈希映射 难度 3 级 题目描述 要求 不使用任何内建的哈希表库设计一个…...

力扣解法汇总1238. 循环码排列
目录链接: 力扣编程题-解法汇总_分享记录-CSDN博客 GitHub同步刷题项目: https://github.com/September26/java-algorithms 原题链接: 力扣 描述: 给你两个整数 n 和 start。你的任务是返回任意 (0,1,2,,...,2^n-1) 的排列 p&…...

[数据结构]时间复杂度与空间复杂度
[数据结构]时间复杂度与空间复杂度 如何衡量一个算法的好坏 long long Fib(int N) {if(N < 3)return 1;return Fib(N-1) Fib(N-2); } 这是一个求斐波那契数列的函数,使用递归的方法求得,虽然代码看起来很简洁,但是简洁真的就好吗&#…...

Codeforces Round #848 (Div. 2)(A~D)
A. Flip Flop Sum给出一个只有1和-1的数组,修改一对相邻的数,将它们变为对应的相反数,修改完后数组的和最大是多少。思路:最优的情况是修改一对-1,其次是一个1一个-1,否则修改两个1。AC Code:#i…...

第十三届蓝桥杯Java B 组国赛 C 题——左移右移(AC)
目录1.左移右移1.题目描述2.输入格式3.输出格式4.样例输入5.样例输出6.数据范围6.原题链接2.解题思路3.Ac_code1.左移右移 1.题目描述 小蓝有一个长度为 NNN 的数组, 初始时从左到右依次是 1,2,3,…N1,2,3, \ldots N1,2,3,…N 。 之后小蓝对这个数组进行了 MMM 次操作, 每次…...

第14篇:系列二—Java抽象类/接口/枚举
目录 1、继承的定义(Inheritance) 2、继承的优点 2.1 易维护性 2.2 复用性 2.3 条理性...

深入浅出C++ ——哈希
文章目录前言一、unordered系列关联式容器1. unordered_map2. unordered_set二、哈希1. 哈希概念2. 哈希冲突3. 哈希函数4. 哈希冲突解决方法三、模拟实现unordered系列容器1. 哈希表的改造2. 模拟实现 unordered_set3. 模拟实现 unordered_map前言 在C11中,STL又提…...

Tina_Linux_系统裁剪_开发指南
文章目录Tina_Linux_系统裁剪_开发指南1 概述2 Tina系统裁剪简介2.1 boot0裁剪2.2 uboot裁剪2.3 内核裁剪2.3.1 删除不使用的功能2.3.2 删除不使用的驱动2.3.3 修改内核源代码2.3.3.1 size工具.2.3.3.2 ksize.py脚本2.3.3.3 nm命令2.3.3.4 kernel压缩方式.2.4 文件系统裁剪.2.4…...

算法刷题打卡第99天:至少在两个数组中出现的值
至少在两个数组中出现的值 难度:简单 给你三个整数数组 nums1、nums2 和 nums3 ,请你构造并返回一个 元素各不相同的 数组,且由 至少 在 两个 数组中出现的所有值组成。数组中的元素可以按 任意 顺序排列。 示例 1: 输入&…...

线程池面试题
1. 什么是线程池?为什么要使用线程池? 线程池是一种用于管理线程的技术,它可以在应用程序中重复使用一组线程来执行多个任务。线程池的优点包括提高应用程序的性能和可伸缩性、避免线程创建和销毁的开销、避免线程过多导致系统负担过重等。线…...

【学习笔记】NOIP爆零赛5
说实话是不想补题的。因为每一道题都贼难写,题解又通篇写着显然,然后自己天天搞竞赛又把注意力搞差了,调一道题又调半天,考试的题又难的要死 不会正解 ,部分分又写挂了 可能心态崩了就是从那场t1t1t1签到题考高精度数位…...

【数据结构】时间复杂度
🚀write in front🚀 📜所属专栏:初阶数据结构 🛰️博客主页:睿睿的博客主页 🛰️代码仓库:🎉VS2022_C语言仓库 🎡您的点赞、关注、收藏、评论,是对…...

vector的基本使用
目录 介绍: vector iterator 的使用 增删查改 增(push_back insert): 删(pop_back erase): swap: vector的容量和扩容: 排序(sort): 介绍ÿ…...

剑指 Offer 55 - I. 二叉树的深度
摘要 剑指 Offer 55 - I. 二叉树的深度 一、深度优先搜索 如果我们知道了左子树和右子树的最大深度l和r,那么该二叉树的最大深度即为:max(l,r)1。 而左子树和右子树的最大深度又可以以同样的方式进行计算。因此我们可以用「深度优先搜索」的方法来计…...

Bean的生命周期和作用域
Bean的生命周期Bean的执行流程:Bean 执行流程:启动Spring 容器 -> 实例化 Bean(分配内存空间,从无到有)-> Bean 注册到 Spring 中(存操作) -> 将 Bean 装配到需要的类中(取…...

TestNG和Junit的区别,测试框架该如何选择?
要想知道两个框架的区别,首先分别介绍一下两个框架。 TestNG是一个java中的开源自动化测试框架,其灵感来自JUnit和NUnit,TestNG还涵盖了JUnit4整个核心的功能,但引入了一些新的功能,使其功能更强大,使用更…...

MySQL安全登录策略
MySQL密码复杂度策略设置 MySQL 系统自带有 validate_password 插件,此插件可以验证密码强度,未达到规定强度的密码则不允许被设置。MySQL 5.7 及 8.0 版本默认情况下貌似都不启用该插件,这也使得我们可以随意设置密码,比如设置为…...

优化模型验证23:带无人机停靠站的卡车无人机协同配送车辆路径问题、模型、gurobipy验证及结果可视化
带中转hub的卡车无人机车辆路径问题 模型来源为:Wang Z , Sheu J B . Vehicle routing problem with drones[J]. Transportation Research Part B: Methodological, 2019, 122(APR.):350-364. 问题描述: 这篇问题研究了一个带停靠站的卡车无人机路径问题,无人机仅能从起点…...