【0】README

  • 0.0) source code from orange’s implemention of a os and for complete code , please visit https://github.com/pacosonTang/Orange-s-OS/blob/master/boot.asm
  • 0.1)本代码仅用于在 根目录区条目中寻找 与 boot代码定义的LoaderFileName 相同文件名 的 条目,仅此而已,该文件名是loader.bin,需要加载入内存继续运行的代码文件;(因为找到该文件后, 最后一句指令执行了 jmp $,所以处理器执行后就停在那里不动,所以这里没有给出运行结果示意图)
  • 0.2) 就本os而言,即orange’s os ,”在根目录区寻找某文件对应的根目录条目“这个任务 是在 引导扇区中的引导程序boot 中完成的,而且 boot 后面还要完成 ”把 os 的 加载程序loader copy 到 0x09000:0100处“的任务,注意这与linux 是不同的
  • 0.3)即是说,orange’s os 中的启动程序boot 执行了两个任务: os引导程序boot 在根目录区寻找os加载程序文件loader 对应的根目录条目 + os引导程序boot 从扇区拷贝os加载程序loader文件到内存(boot copy kernel to mem in the same method)

【1】Source Code

;—————————————————————————-

; 函数名: ReadSector

;—————————————————————————-

; 作用:

; 从第 ax 个 Sector 开始, 将 cl 个 Sector 读入 es:bx 中, ax初始值=19

ReadSector:

; ———————————————————————–

; 怎样由扇区号求扇区在磁盘中的位置 (扇区号 -> 磁道=柱面号, 起始扇区, 磁头号=磁面)

; 注意扇区号和起始扇区号不同;扇区号对于整个磁盘的全局索引值,而起始扇区号是本磁道的扇区索引值

; ———————————————————————–

; 设扇区号为 x

; ┌ 柱面号 = y >> 1

; x ┌ 商 y ┤

; ————– => ┤ └ 磁头号 = y & 1

; 每磁道扇区数 │

; └ 余 z => 起始扇区号 = z + 1

 push   bp
mov bp, sp
sub esp, 2 ; 辟出两个字节的堆栈区域保存要读的扇区数: byte [bp-2] mov byte [bp-2], cl ; 在调用者中, cl 被赋值为1, mov cl, 1
push bx ; 保存 bx
mov bl, [BPB_SecPerTrk] ; bl: 除数 , BPB_SecPerTrk DW 18 ; 每磁道扇区数
div ; y 在 al 中, z 在 ah 中 , div 被除数A 默认存放在AX中(16位以内) 或 AX 和 DX中(32位,DX存放高16位,AX存放低16位)
inc ah ; z ++
mov cl, ah ; cl <- 起始扇区号
mov dh, al ; dh <- y
shr al, 1 ; y >> 1 (y/BPB_NumHeads)
mov ch, al ; ch <- 柱面号
and dh, 1 ; dh & 1 = 磁头号
pop bx ; 恢复 bx
; 至此, "柱面号, 起始扇区, 磁头号" 全部得到
mov dl, [BS_DrvNum] ; 驱动器号 (0 表示 A 盘) ,BS_DrvNum DB 0; 中断 13 的驱动器号
.GoOnReading:
mov ah, 2 ; 读
mov al, byte [bp-2] ; 读 al 个扇区
int 13h
jc .GoOnReading ; 如果读取错误 CF 会被置为 1,
; 这时就不停地读, 直到正确为止
add esp, 2
pop bp ret

【2】把文件加载到内存的步骤:寻找文件 + 定位文件 + 读入内存

  • 2.1)寻找文件方法:
    • 2.1.a) 将根目录的第一个扇区(如第19个全局扇区)读入到起始地址为 es:bx=9000h:0100(该地址其实 是在软盘中的数据区去了) ,循环下去的话,读第20、21、….扇区,而es:bx=9000h:0100 永不改变;
    • 2.1.b) 因为一个 sector = 512Bytes, 而根目录条目=32Bytes,所以一个扇区就含有16个条目,我们要遍历这16个条目,并将条目中的DIR_NAME属性(即文件名)和boot 代码中静态的 LoaderFileName 做比较,如果完全匹配的话,那该DIR_NAME所在的条目就是我们要找的根目录条目, 如果不匹配话,转向 步骤c;
    • 2.1.c) add di, offeh , 使得di 指向该条目开头(因为在发现条目中的DIR_NAME 与 LoaderFileName 不等的时候,di指向的是DIR_NAME 的下一个字节),然后 add di, 20h(32个字节,一个条目大小为32字节) , di指向下一条目开头,继续循环比较;如果 第一个扇区的16个根目录条目都比较完了,转向步骤a,只不过该读当前扇区的下一个扇区了;

      Return)该步骤完成后,若寻找文件成功,返回的是 满足 DIR_NAME==LoaderFileName 的 根目录条目;

      (Attention): 你要知道根目录条目是多么 的重要,因为它存储有 (文件名 + 文件属性 + 最后一次写入时间 + 最后一次写入日期 + 此条目对应的开始簇号 + 文件大小) 等信息;这个根目录条目 ,不可小觑;
  • 2.2)定位文件方法(本代码还未涉及到):(参见 http://blog.csdn.net/pacosonswjtu/article/details/48391467 【2.2】文件分配表-FAT 看个荔枝)“

  • 如FAT所在扇区(一个扇区512字节)存储值为:F0 FF FF FF 8F 00 FF FF FF FF FF FF 09 A0 00 FF , 0F 00 00 ;

    则簇号分别为:0-FF0 1-FFF 2-FFF 3-008 4-FFF 5-FFF 6-FFF 7-FFF 8-009 9-00A A-FFF

    如果根目录去中有条目记载某文件A 的 DIR_FstClus=3的话,则对应第3个FAT项,结合上一行,我们知道FAT3==008,所以下一个簇号是8-009 , 以此类推9-00A、 A-FFF。FFF就表示这个簇是最后一个簇了。

    Conclusion:找出该文件在数据区中对应的所有簇,就定位了该文件了;

  • 2.3)读入内存方法(先定位全局扇区,再对寄存器编程):



    (上图错误更正)应该是怎样由扇区号求扇区在磁盘中的位置,不是定位文件;

  • 如何读取扇区内容到内存? 参见 source code 中的 ReadSector 函数。


【3】总结

  • 3.1)首先你要想,寻找文件? 为什么要寻找文件,是因为,我们boot代码要加载loader 代码进入内存,而loader代码在软盘上(硬盘)上,所以我们就要在软盘上寻找该文件。

    为什么boot和loader 不写在同一个程序中?因为 引导扇区只装的下最多 512B,所以要把boot程序和 loader 程序分开来存放,然后再由 boot 跳转到 loader程序去执行;

  • 3.2)怎样寻找? 要知道FAT12软盘中的 根目录区条目存储有 所有文件的相关信息,最重要的就是文件名。通过 利用ReadSector函数 实现 “怎样由扇区号求扇区在磁盘中的位置 (扇区号 -> 磁道=柱面号, 起始扇区, 磁头号=磁面)”的功能【暂且叫定位扇区功能,因为一个扇区最直观的表示是全局扇区号,而扇区在软盘中的表示是由3个维度来进行:磁头号(盘面号0,1),磁柱=磁道号,该磁道的上的扇区号来确定】,

    我们就把根目录区的第一个全局扇区号(循环,就进入当前扇区的下一个扇区号),如FAT12 的根目录区第一个扇区号为19(相对于根目录区而言是1,而对于全局而言是19),传入ReadSector函数,将传入的扇区内容读入到 es:bx;下一步,我们就把 es:bx中的根目录条目的FIR_NAME 和 boot代码中静态写死的文件名LoaderFileName 进行比较;

    • 3.2.1)若相等,则文件寻找成功,返回当前所比较的根目录条目(即是LoaderFileName ==DIR_NAME所在的条目)。要知道一个扇区=512Bytes,一个根目录条目=32Bytes,所以一个扇区==16个根目录条目, 所以要在es:bx 处比较16次,是个循环比较;
    • 3.2.2)如果比较不成功,全局扇区号加1(当前为19,加1为20,以此类推),循环下去,直到找到与LoaderFileName 相等的 根目录条目,或者,遍历完 根目录条目的所有扇区(如 根目录条目扇区数量为14,当然,这个是由FAT12的引导扇区设置的,可以变化的)
  • (Attention):其实,你也看到了,要寻找文件,免不了要去定位全局扇区号(磁头号,磁道号,该磁道上的扇区号),定位后,还要读取该扇区到内存的某个位置,读入后,还要对该内存的某些特定值进行比较操作,比较结果有成功,有失败;成功后,返回的是比较成功的当前根目录条目值;这就知道了Loader文件在 根目录区的描述了,包括(文件名 + 文件属性 + 最后一次写入时间 + 最后一次写入日期 + 此条目对应的开始簇号 + 文件大小),接下来,我们就把 Loader 文件加载到内存,准备开始运行该Loader文件了。source code 参见 p114.asm >> https://github.com/pacosonTang/Orange-s-OS/blob/master/p114.asm

版权声明:本文为博主原创文章,未经博主允许不得转载。

os引导程序boot 在根目录区寻找os加载程序文件loader 对应的根目录条目的更多相关文章

  1. os引导程序boot从扇区拷贝os加载程序loader文件到内存(boot copy kernel to mem in the same method)

    [0]README 0.1) 本代码旨在演示 在boot 代码中,如何 通过 loader文件所在根目录条目 找出该文件的 在 软盘所有全局扇区号(簇号),并执行内存中的 loader 代码: 0.2 ...

  2. CAD调试时抛出“正试图在 os 加载程序锁内执行托管代码。不要尝试在 DllMain 或映像初始化函数内运行托管代码”异常的解决方法

    这些天重装了电脑Win10系统,安装了CAD2012和VS2012,准备进行软件开发.在调试程序的时候,CAD没有进入界面就抛出 “正试图在 os 加载程序锁内执行托管代码.不要尝试在 DllMain ...

  3. 正尝试在 OS 加载程序锁内执行托管代码。不要尝试在 DllMain 或映像初始化函数内运行托管代码,这样...

    出错提示: 正尝试在 OS 加载程序锁内执行托管代码.不要尝试在 DllMain 或映像初始化函数内运行托管代码,这样做会导致应用程序挂起. 原因分析: .NET2.0中增加了42种非常强大的调试助手 ...

  4. 检测到 LoaderLock:DLL"XXXX"正试图在OS加载程序锁内执行

    解决方法: ctrl+D+E或alt+ctl+e或使用菜单调试——>异常——>异常窗口——>Managed Debugging Assistants——>去掉LoaderLoc ...

  5. 正试图在 os 加载程序锁内执行托管代码。不要尝试在 DllMain 或映像初始化函数内运行托管代码

    来自:http://www.cnblogs.com/lcxu2/archive/2011/01/16/2004016.html 正试图在 os 加载程序锁内执行托管代码.不要尝试在 DllMain 或 ...

  6. 在AE二次开发中出“正试图在 OS 加载程序锁内执行托管代码。不要尝试在 DllMain 或映像初始化函数内运行托管代码,这样做会导致应用程序挂起。”异常解决方案

    今天的一个项目总用到了AE的开发组件,也就是ESRI公司提供的一系列的开发包(组件)都是以dll(动态链接库的形式)然后今天在调试的时候却出现了“正试图在 OS 加载程序锁内执行托管代码.不要尝试在 ...

  7. 正试图在 os 加载程序锁内执行托管代码

    正试图在 os 加载程序锁内执行托管代码.不要尝试在 DllMain 或映像初始化函数内运行托管代码... 当我在窗体初始化的时候,调用了一个外部的dill时,它就不知什么原因的 抛出一个“正试图在 ...

  8. spring boot 加载配置 文件

    在springboot启动的过程中,默契情况下会在classpath路径下加载application.properties当做系统配置文件,但有时候我们想要替换成另一个文件,可以 通过以下方式:   ...

  9. Spring boot 国际化自动加载资源文件问题

    Spring boot 国际化自动加载资源文件问题 最近在做基于Spring boot配置的项目.中间遇到一个国际化资源加载的问题,正常来说只要在application.properties文件中定义 ...

随机推荐

  1. LeetCode Weekly Contest 70 A B C D

    A. K-th Symbol in Grammar Description On the first row, we write a 0. Now in every subsequent row, w ...

  2. VS Code开发技巧集锦【转】

    转自:http://blog.csdn.net/tiantangyouzui/article/details/52163175 入门 自定义 扩展 文件/文件夹管理 编辑技巧 智能感应功能 代码片段 ...

  3. MSP430 G2553 寄存器列表与引脚功能

    USCI_B0 USCI_B0 发送缓冲器UCB0TXBUF 06Fh USCI_B0 接收缓冲器UCB0RXBUF 06Eh USCI_B0 状态UCB0STAT 06Dh USCI B0 I2C ...

  4. 剖析CPU温度监控技术【转】

    转自:http://blog.csdn.net/hunanchenxingyu/article/details/46476545 迄今为止还没有一种cpu散热系统能保证永不失效.失去了散热系统保护伞的 ...

  5. hdu1465 动态规划

    题目 一个人写了n封不同的信及相应的n个不同的信封,他把这n封信都装错了信封,问都装错信封的装法有多少种? 解体思路 用A.B.C--表示写着n位友人名字的信封,a.b.c--表示n份相应的写好的信纸 ...

  6. angular6安装

    中文 https://www.angular.cn/ 二.下载 1.安装 node.js https://nodejs.org/en/ 2.删除老angular-cli npm uninstall - ...

  7. Codeforces 911F Tree Destruction(贪心 && 树的直径)

    题目链接  Tree Destructi 题意  给定一棵树,每次可以选定树上的两个叶子,并删去其中的一个.答案每次加上两个选定的叶子之间的距离. 求最后答案的最大值. 首先求出树的某一条直径,令其端 ...

  8. OBS插件开发以及OBS插件的选择(obs直播插件)研究思路

    obs版本的选择: 工作室版,优化了很多东西,缺点是不能用插件,在部分机型不稳定,因为更新的很频繁.不过这个插件不能用的说法还是停留在早起,截至到今天已经完美支持,所以在不久的将来会越来越好,如果是开 ...

  9. 【IntelliJ IDEA】spring boot项目在idea实现自动部署

    转载参考自:https://www.cnblogs.com/winner-0715/p/6666579.html spring-boot-devtools是一个为开发者服务的一个模块,其中最重要的功能 ...

  10. leetCode 58.Length of Last Word (最后单词的长度) 解题思路和方法

    Length of Last Word  Given a string s consists of upper/lower-case alphabets and empty space charact ...