【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. [翻译]现代Linux系统上的栈溢出攻击【转】

    转自:http://www.codeweblog.com/%E7%BF%BB%E8%AF%91-%E7%8E%B0%E4%BB%A3linux%E7%B3%BB%E7%BB%9F%E4%B8%8A%E ...

  2. C#原生加密方法: System.Security.Cryptography.CryptoStream DataSet加密解密

    采用16位密钥形式加密,把数据 dataset或文本转换为二进制流,然后进行加密解密.代码如下: using System; using System.Collections.Generic; usi ...

  3. 只用一次循环开销 将类似 1 A 、1 B 的数据返回成为 1 A,B 的拼接形式

    /// <summary> ///将类似 1 A .1 B 的数据返回成为 1 A,B 的拼接形式 /// </summary> /// <param name=&quo ...

  4. App Store 审核指南(最新)

    简介 App 正在改变世界,丰富人们的生活,并为像您一样的开发者提供前所未有的创新机会.因此,App Store 已成长为一个激动人心且充满活力的生态系统,正为数百万的开发者和超过十亿的用户提供服务. ...

  5. Codeforces 899 A.Splitting in Teams

      A. Splitting in Teams   time limit per test 1 second memory limit per test 256 megabytes input sta ...

  6. 吉首大学 问题 L: 小李子的老年生活

    时间限制: 1 Sec  内存限制: 128 MB提交: 719  解决: 27 题目描述 小李子有n-1个朋友,分别编号为1..n-1,小李子的编号是n ,小李子的表面朋友的编号会与小李子编号互质 ...

  7. 解决WordPress中字符转义的问题

    wordpress中输入两个"--"的时候会识别成一个横杠,如果此时的文章中有代码在,那么其他人在复制粘贴的时候就没法使用,于是乎我寻找了三种有效的方法解决此问题! WordPre ...

  8. YACEP相关技术工具服务技巧(上)

    这篇随笔的核心是介绍一下YACEP所用到的一些技术,工具,服务和技巧,鉴于篇幅原因,不可能面面俱到,只能点到为止,目录如下: 目录: 1. YACEP简介(上)             2. 技术篇( ...

  9. idea---搭建maven,tomcat入门

    这篇随笔讲讲idea工具的安装和使用和在idea中搭建maven的分享. 一.概念 1.IntelliJ IDEA是什么? DEA 全称 IntelliJ IDEA,是java编程语言开发的集成环境. ...

  10. 发现一个直播录制工具you-get

    地址:https://github.com/soimort/you-get 截至到今天,支持的平台如下: Site URL Videos? Images? Audios? YouTube https: ...