06-07-08 - 突破512字节的限制

---- 整理自狄泰软件唐佐林老师课程

查看所有文章链接:(更新中)深入浅出操作系统 - 目录

0. 未完成的工作

第4步还未完成,这篇文章内容主要是做第4步之前的准备工作:

  1. 使用FAT12格式对软盘(data.img)进行格式化,之后可以自由得在软盘上拷贝文件
  2. 编写可执行程序Loader(loader.asm),并将其拷贝到软盘中
  3. 主引导程序Boot(boot.asm)按照FAT12的文件格式在文件系统中查找Loader
  4. 将Loader复制到内存中,并跳转到Loader入口处执行

1. 突破限制的准备工作

  • 辅助函数:
    • 字符串打印 Print
    • 软盘读取 ReadSector
    • 内存比较 MemCmp
    • 根目录区查找 FindEntry

1.1 字符串打印 Print

  • 主引导程序中如何进行字符串的打印?

1.1.1 BIOS中的字符串打印

指定打印参数(AX = 0x1301,BX = 0x0007)
指定打印字符串的内存地址(ES:BP = 串地址)
指定字符串的长度(CX = 串长度)
中断调用(int 0x10)
  • 字符串打印示例
; 指定字符串地址
mov ax, msg
mov bp, ax
mov ax, ds
mov es, ax

; 指定字符串长度
mov cx, 6

; 指定打印参数
mov ax, 0x1301
mov bx, 0x0007

; 中断调用
int 0x10

1.1.2 汇编小贴士

  • 汇编中可以定义 函数(函数名使用标签定义)
    • call function
    • 函数体的最后一条指令为 ret
  • 如果代码中定义了函数,那么需要定义 栈空间
    • 用于保存关键寄存器的值
    • 栈顶地址通过 sp寄存器 保存
  • 汇编中的 “常量定义”(equ
    • 用法:CHANGLIANG equ 0x7c00 ; #define CHANGLIANG 0x7c00
    • 与(db,dw,dd)的区别:
      • dx 定义 会占用 相应的内存空间
      • equ 定义 不会占用 任何内存空间

1.1.3 编程实验:定义打印函数print

  1. print

【参看链接】:06-07-08 - 突破512字节的限制 / 06 / 00print

只打印6个字符:

在这里插入图片描述

  1. print2

在这里插入图片描述
在这里插入图片描述

【参看链接】:06-07-08 - 突破512字节的限制 / 06 / 01print2

在这里插入图片描述

1.2 软盘读取 ReadSector

  • 主引导程序中如何读取指定扇区处的数据?

1.2.1 软盘的构造

  • 一个软盘有 2个盘面,每个盘面对应 1个磁头
  • 每一个盘面 被划分为若干个圆圈,成为 若干个柱面(磁道)
  • 每一个柱面 被划分为 若干个扇区,每个扇区512字节

在这里插入图片描述

  • 3.5寸软盘 的数据特性
    • 每一个盘面一共有80个柱面(编号0~79)
    • 每一个柱面有18个扇区(编号1~18)
    • 存储大小:2 * 80 * 18 * 512Byte = 1440 KB
1张软盘2个盘面编号0~1
1个盘面80个柱面(磁道)编号0~79
1个柱面18个扇区编号1~18
1个扇区512字节

1.2.2 软盘数据的读取

  • 软盘数据以扇区(512字节)为单位进行读取
  • 指定数据所在位置的磁头号(哪个盘面) 、柱面号、扇区号
  • 计算公式:逻辑扇区号(相对扇区号)/ 柱面扇区数

在这里插入图片描述

1.2.3 BIOS中的软盘数据读取(int 0x13)

在这里插入图片描述

注:

  • 执行:锁定/解锁驱动器
  • 输入:
    DL = 驱动器号
    AL = 00h 锁定驱动器
    AL = 01h 驱动器解锁
    AL = 02h 返回锁定/解锁状态
    AL = 03h-FFh 保留
  • 返回:
    CF = 0, AH = 0 成功
    CF = 1, AH = 错误码
  • 这个调用用来锁定指定驱动器中的介质

1.2.4 软盘数据读取流程

==> 指定逻辑扇区号AX、指定读取扇区数CX
==> 指定内存位置(ES:BX)
==> 重置软驱状态
==> 根据逻辑扇区号计算:柱面号、磁头号、扇区号
==> int 0x13
==> ret

在这里插入图片描述

1.2.5 汇编小贴士

  • 汇编中的16位除法操作 div
    • 被除数放到AX寄存器
    • 除数放到通用寄存器或内存单元(8位)
    • 结果:商位于AL,余数位于AH
      • 被除数 ➗ 除数 = 商 ...... 余数
      • AX ➗ 通用reg或内存单元 = AL ...... AH

1.2.6 编程实验:磁盘数据的读取

【参看链接】:06-07-08 - 突破512字节的限制 / 06 / 02read

在这里插入图片描述
在这里插入图片描述

  • 注解:这里简单补充一下内存的布局:
    BIOS将软盘中的引导扇区读入内存时,内存布局如下所示:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.3 内存比较 MemCmp

在这里插入图片描述

1.3.1 整体思路

FAT12文件格式数据区
根目录区
FAT2
FAT1
引导扇区

在这里插入图片描述

问题:

  • 如何在根目录区查找目标文件?
  • 通过根目录区中的 目录项的前11个字节(DIR_Name进行判断

在这里插入图片描述

1.3.2 内存内容比较

指定源起始地址(DS:SI)
指定目标起始地址(ES:DI)
判断在期望长度(CX)内每一个字节是否相等

在这里插入图片描述

1.3.3 汇编小贴士

  • 汇编中的比较和跳转
    • 比较:cmp cx, 0 ; 比较cx的值是否等于0
    • 跳转:jz equal ; 如果比较结果为真,则跳转到equal标签处

在这里插入图片描述

1.3.4 编程实验:内存比较函数

【参看链接】:06-07-08 - 突破512字节的限制 / 07 / 00mem_cmp

在这里插入图片描述

1.4 根目录区查找 FindEntry

查找根目录区是否存在目标文件
在这里插入图片描述

1.4.1 汇编小贴士

  • 访问栈空间中的栈顶数据
    • 不能使用 sp 直接访问栈顶数据
      • 这是错误的:mov cx, [sp]
    • 通过其它 通用寄存器 间接访问栈顶数据
push  cx
mov  bp, sp
mov  cx, [bp]

1.4.2 编程实验:根目录区查找函数

【参看链接】:06-07-08 - 突破512字节的限制 / 07 / 01find_entry

  1. 直接通过makefile中生成的data.img中没有loader,所以找不到,结果如下:

在这里插入图片描述

为什么没有找到loader?反汇编调试确认:
ndisasm -o 0x7c00 boot.bin > boot.txt

在这里插入图片描述
在这里插入图片描述

  1. 根据前面章节《04-05 - 主引导程序的扩展》,在data.img中写入Loader.bin文件,则可以找到:

在这里插入图片描述

1.5 备份目标文件的目录信息(内存拷贝 MemCpy)

在这里插入图片描述

1.5.1 MemCpy实现要点:拷贝方向

  • 从源内存地址处拷贝到目标内存地址处即可,但如果 地址出现重叠 怎么办 ?如下情况:

在这里插入图片描述

1.5.2 汇编小贴士

在这里插入图片描述

如果si大于di,就跳转到btoe标签处执行。

1.5.3 编程实验:内存拷贝函数

  • 无重叠

【参看链接】:06-07-08 - 突破512字节的限制 / 08 / 00mem_cpy

  • 有重叠 si < di,从头部开始拷贝

【参看链接】:06-07-08 - 突破512字节的限制 / 08 / 00mem_cpy2

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 有重叠 si > di,从尾部开始拷贝

【参看链接】:06-07-08 - 突破512字节的限制 / 08 / 00mem_cpy3

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

1.6 FAT表项的读取 FatVec

FAT表中的 每个表项占用 1.5字节,即:使用3个字节表示2个表项
在这里插入图片描述

1.6.1 FAT表项的“动态组装”

在这里插入图片描述

FatVec[j] 的动态组装:
在这里插入图片描述
在这里插入图片描述

1.6.2 汇编小贴士

  • 汇编中的16位乘法操作( mul
    • 被乘数放到AL寄存器
    • 乘数放到通用寄存器或内存单元(8位)
    • 相乘的结果放到AX寄存器中
      • 被乘数 × 乘数 = 积
      • AL × 通用reg或内存单元 = AX

1.6.3 编程实验:FAT项读取函数

【参看链接】:06-07-08 - 突破512字节的限制 / 08 / 01FatVec

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.7 小结

  • 内存拷贝时需要考虑进行拷贝的方向
    • 当 si > di 时,从前向后拷贝
    • 当 si <= di 时,从后向前拷贝
  • Fat表加载到内存中之后,需要 “ 动态组装 ” 表项
    • Fat表中使用3个字节表示2个表项
    • 起始字节 = 表项下标 / 2 * 3 ==> (这里先3个3个的算出起始字节,再判断除以2的奇偶,然后用公式算出Fat表项)

在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

uuxiang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值