《一个操作系统的实现》笔记(4)-- Boot&Loader
一个操作系统从开机到开始运行,大致经历引导->加载内核入内存->跳入保护模式->开始执行内核
这样一个过程。
引导扇区(Boot)负责把Loader加载入内存并且把控制权交给它,其它工作放心地交给Loader来做,因为没有512字节的限制,将会灵活得多。
FAT12文件系统
几乎所有的文件系统都会把磁盘划分为若干层次以方便组织和管理,这些层次包括: - 扇区(Sector):磁盘上的最小数据单元。 - 簇(Cluster):一个或多个扇区。 - 分区(Partition):通常指整个文件系统。
要让引导扇区找到Loader这个二进制文件,并把文件内容全部读出来放进内存里,首先需要了解FAT12的文件格式。
这里存储的都是二进制数据,我们必须要按照FAT12的规范在指定的偏移处填充数据,这样它在读这里的数据时就会现在指定偏移处找到元数据,接着找到真实的数据部分。 FAT12引导扇区的部分格式:
根目录区中的条目格式
很明显,我们在寻找Loader时,只要扫描根目录区这里的条目,发现文件名正确就认为它是我们要找的那个文件,然后根据这个条目的FstClus
(它告诉我们文件存放在磁盘的什么位置)字段去数据区找真实的数据内容。
如果文件内容大于512字节(一个扇区),这时候就需要用到FAT表了。
FAT表有两个,FAT2可看做FAT1的备份,它们通常是一样的。
FAT的结构有点像一个位图。每12位称为一个FAT项,从第2项开始表示数据区的每一个簇,FAT项的值代表的是文件的下一个簇号,但如果值大于或等于0xFF8,则表示当前簇已经是本文件的最后一个簇了,所以只需要一直在FAT表里找下去直到最后一个簇号就能把该文件在数据区的所有簇号找到从而读出完整的数据内容。如果值为0xFF7,表示它是一个坏簇。
加载Loader到内存
BIOS中的中断int 13h可以完成读软盘的任务,从而把文件加载到内存中。 从磁盘将数据读入es:bx指向的缓冲区中,每次读出一个簇,直到Loader文件的所有数据都读到缓冲区为止。
向Loader交出控制权
;boot.asm
BaseOfLoader equ 09000h ; LOADER.BIN 被加载到的位置 ---- 段地址
OffsetOfLoader equ 0100h ; LOADER.BIN 被加载到的位置 ---- 偏移地址
;...
jmp BaseOfLoader:OffsetOfLoader ; 这一句正式跳转到已加载到内
; 存中的 LOADER.BIN 的开始处,
; 开始执行 LOADER.BIN 的代码。
; Boot Sector 的使命到此结束。
这里的org 0100h
是什么意思呢?
这段代码在编译阶段就会告诉编译器,将来我们的这段程序要被加载到内存偏移0x100h处的,org
没有设置段地址。可以看到OffsetOfLoader
正好设置成了0100h
。此时程序的指令、数据就以这个偏移为起始点在内存中存放。
;loader.asm
org 0100h
;...具体的loader逻辑
Linux的引导扇区代码Boot.s比我们的要简单许多,它直接把内核移动到目标内存。
- Gym 100952I&&2015 HIAST Collegiate Programming Contest I. Mancala【模拟】
- bootstrap + requireJS+ director+ knockout + web API = 一个时髦的单页程序
- Gym 100952E&&2015 HIAST Collegiate Programming Contest E. Arrange Teams【DFS+剪枝】
- Gym 100952H&&2015 HIAST Collegiate Programming Contest H. Special Palindrome【dp预处理+矩阵快速幂/打表解法】
- Gym 100952G&&2015 HIAST Collegiate Programming Contest G. The jar of divisors【简单博弈】
- Gym 100952F&&2015 HIAST Collegiate Programming Contest F. Contestants Ranking【BFS+STL乱搞(map+vector)+
- Gym 100952D&&2015 HIAST Collegiate Programming Contest D. Time to go back【杨辉三角预处理,组合数,dp】
- Gym 100952B&&2015 HIAST Collegiate Programming Contest B. New Job【模拟】
- 51 Nod 1008 N的阶乘 mod P【Java大数乱搞】
- 【AlphaGo Zero 核心技术-深度强化学习教程代码实战06】给Agent添加记忆功能
- Gym 100952A&&2015 HIAST Collegiate Programming Contest A. Who is the winner?【字符串,暴力】
- [开源,学习,分享]UWP第三方简书客户端分享
- HDU 1024 Max Sum Plus Plus【动态规划求最大M子段和详解 】
- 51 Nod 1057 N的阶乘【Java大数乱搞】
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 别再用OFFSET和LIMIT分页了
- 别再用大小比较时间了
- Redis快速入门
- 捉虫记:Unexpected end of JSON input while parsing
- 重新思考日志:业务系统竟然是一个大数据库?
- 测试面试题集-Linux常用命令
- 「真香警告」鱼头手摸手教你在小程序里用composition-api
- 【技术文】SSL握手中的几个密码
- 分布式监控系统SkyWalking
- 文献笔记二十九:银合欢(Leucaena trichandra)线粒体基因组
- Docker Swarm群集配置实战——第一战
- 文献笔记五十:vcf2poptree根据vcf文件构建进化树的网页工具
- typescript基础篇(6):泛型
- Flutter 初学者必读的高级布局规则
- Docker Swarm群集配置实战——第二战