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

【0】README

  • 0.1) 本代码旨在演示 在boot 代码中,如何 通过 loader文件所在根目录条目 找出该文件的 在 软盘所有全局扇区号(簇号),并执行内存中的 loader 代码;
  • 0.2) 此代码非常重要,关系到bootloader的加载和运行(打印字母 L)(干货)
  • 0.3) 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.4) 就本os而言,即orange’s os ,”从扇区copy os加载程序 loader 到内存0x09000:0100“这个任务 是在 引导扇区中的引导程序boot 中完成的,而且在 boot 完成本任务之前,引导程序boot还完成 ”在根目录区寻找 加载程序loader 对应的根目录条目“的任务,注意这与linux 是不同的;
  • 0.5)即是说,orange’s os 中的启动程序boot 执行了两个任务: os引导程序boot 在根目录区寻找os加载程序文件loader 对应的根目录条目 + os引导程序boot 从扇区拷贝os加载程序loader文件到内存(boot copy kernel to mem in the same method)
  • Attention)
    • A1) loader文件所在根目录条目 是由 p109.asm 得到的, 在查找完文件名称且匹配后,di 指向文件名的后一个字节,但di还存在于当前匹配成功的 根目录条目中;
    • A2) 要死死记住 根目录条目的数据结构存储的是:(文件名 + 文件属性 + 最后一次写入时间 + 最后一次写入日期 + 此条目对应的开始簇号 + 文件大小)
      这里写图片描述

【1】SOURCE CODE

LABEL_FILENAME_FOUND: ; 找到 LOADER.BIN 后便来到这里继续

 mov    ax, RootDirSectors ; RootDirSectors=14and    di, 0FFE0h   ; di -> 当前条目的开始,每个条目=32字节,0ffe0==1111 1111 1110 0000add    di, 01Ah     ; di -> 首 Sector ,条目数据结构中,开始簇号的offset=26字节;mov    cx, word [es:di]push   cx   ; 保存此 Sector 在 FAT 中的序号 ,cx等于loader文件的开始簇号(在数据区)add    cx, axadd    cx, DeltaSectorNo   ; cl <- LOADER.BIN的起始扇区号(0-based); 这里加完之后,cx=该loader 文件相对于0号扇区的扇区号(也即相对于整个软盘而言)mov    ax, BaseOfLoadermov    es, ax   ; es <- BaseOfLoadermov    bx, OffsetOfLoader  ; bx <- OffsetOfLoadermov    ax, cx   ; ax <- Sector 号LABEL_GOON_LOADING_FILE:push   ax   ; `.push   bx   ;  | es:bp 是串地址,CX=串长度,ah= ,al= '.' 打印什么东西, bh=页号,bl=黑底红字mov    ah, 0Eh  ;  | 每读一个扇区就在 "Booting  " 后面mov    al, '.'  ;  | 打一个点, 形成这样的效果:mov    bl, 0Fh  ;  | Booting ...... int    10h  ;  |   | 一句话说完,以上对register的初始化,都是为触发10h 号中断做准备工作的, pop    bx   ;  |pop    ax   ; /mov    cl, 1

call ReadSector ; 这个ReadSector非常重要,目的就是读取cl个扇区到 es:bx中,而bx 每次都自增512字节;(这是读软盘某扇区到内存中的关键步骤)

 pop    ax  ; cur_line=154, 取出此 Sector 在 FAT 中的序号(ax <- cx),line133 push cx 已压入栈, cx=Loader文件在数据区的开始簇号;

call GetFATEntry ; 找到序号为 ax 的 Sector 在 FAT 中的条目, 结果放在 ax 中

 cmp    ax, 0FFFhjz LABEL_FILE_LOADED  ; 相等,则说明 该簇号是最后一个簇号push   ax   ; 保存 Sector 在 FAT 中的序号mov    dx, RootDirSectorsadd    ax, dxadd    ax, DeltaSectorNo   ;   DeltaSectorNo equ 17add    bx, [BPB_BytsPerSec] ;  bx加上一个扇区的字节数,即跳转到下一个扇区;因为读取地址是 es:bxjmp    LABEL_GOON_LOADING_FILE
LABEL_FILE_LOADED:mov    dh, 1    ; "Ready." 加载完毕 call   DispStr  ; 显示字符串;  

jmp BaseOfLoader:OffsetOfLoader; 这一句正式跳转到已加载到内, 开始执行loader 代码;
; 存中的 LOADER.BIN 的开始处,
; 开始执行 LOADER.BIN 的代码。
; Boot Sector 的使命到此结束**



GetFATEntry Source Code
;—————————————————————————-
; 函数名: GetFATEntry
;—————————————————————————-
; 作用:
; 找到序号为 ax 的 Sector 在 FAT 中的条目, 结果放在 ax 中
; 需要注意的是, 中间需要读 FAT 的扇区到 es:bx 处, 所以函数一开始保存了 es 和 bx

GetFATEntry:push   espush   bxpush   ax ; cur_line=269, ax 存储该文件在FAT中的开始簇号(又FAT的第0和第1项不使用,所以FAT条目的开始簇号起步价为2,且数据区的第一个簇的簇号是2)mov    ax, BaseOfLoader; `.sub    ax, 0100h   ;  | 在 BaseOfLoader 后面留出 4K 空间用于存放 FAT;  | 因为每个扇区=512B,FAT=8个扇区=4k;mov    es, ax   ; /pop    ax   ; ax恢复line269 push ax 的值,(current line=273)mov    byte [bOdd], 0   ; bOdd db  0 ; 奇数(value=1)还是偶数(value=0)mov    bx, 3mul    bx   ; dx:ax = ax * 3mov    bx, 2div    bx   ; dx:ax / 2  ==>  ax <- 商, dx <- 余数cmp    dx, 0jz LABEL_EVENmov    byte [bOdd], 1    ; 奇数(value=1)偶数(value=0)
LABEL_EVEN:;偶数; 现在 ax 是 FATEntry 在 FAT 中的偏移量,下面来; 计算 FATEntry 在哪个扇区中(FAT占用不止一个扇区); 因为 FATEntry 占用12位,解释了line276 line278 的 乘3 和 除2 操作;cur_line=285xor    dx, dx   mov    bx, [BPB_BytsPerSec] ; div    bx ;  dx:ax / BPB_BytsPerSec;  ax <- 商 (FATEntry 所在的扇区相对于 FAT 的扇区号 , FAT共有9个扇区 );  dx <- 余数 (FATEntry 在扇区内的偏移)push   dx  ; FATEntry 在扇区内的偏移mov    bx, 0   ; bx <- 0 于是, es:bx = (BaseOfLoader - 100):00add    ax, SectorNoOfFAT1 ; 此句之后的 ax 就是 FATEntry 所在的扇区号(全局); SectorNoOfFAT1 equ 1 ; FAT1 的第一个扇区号 = BPB_RsvdSecCntmov    cl, 2   call   ReadSector  ; 读取 FATEntry 所在的扇区, 一次读两个, 避免在边界; 发生错误, 因为一个 FATEntry 可能跨越两个扇区; ReadSector 从第 ax 个 Sector 开始, 将 cl 个 Sector 读入 es:bx 中, es:bx = (BaseOfLoader - 100):00pop    dx   ; 将 FATEntry 在扇区内的偏移(line292) 出栈,cur_line=300  add    bx, dx   ; 因为bx=0,偏移量 -> bxmov    ax, [es:bx]  ; es:bx = (BaseOfLoader - 100):00+dx( FATEntry 在扇区内的偏移)cmp    byte [bOdd], 1  ; 奇数(value=1)偶数(value=0)jnz    LABEL_EVEN_2    ; 偶数shr    ax, 4    ; 注意,FATEntry=12bit,占用1.5Byte, 这里很好理解
LABEL_EVEN_2:and    ax, 0FFFhLABEL_GET_FAT_ENRY_OK:pop    bxpop    esret

【2】Conclusion(本代码继p109 后,接着摆)

  • 2.0)写在前面:假设这里有个内核,loader加载该内核到内存,而且内核开始执行的时候肯定已经在保护模式下了。所以loader需要做的事情有两件:

    • 2.0.a)加载内核入内存;
    • 2.0.b)跳入保护模式;
  • 2.1)下面演示 以上代码的执行步骤:
    step1)计算该文件起始簇号对应的全局扇区号:
    从根目录条目中抽取出 该文件的起始簇号(FAT专门用于存储文件在数据区的簇号,簇号等于一个或多个扇区),该簇号是相对于数据区的簇号,(因为本FAT12文件系统中,一个簇号==一个扇区,所以簇号就等于扇区的说法,但是不管怎么,知道簇号,我就可以知道扇区号,这些设置是在 FAT12 的引导扇区中定义好了的)所以,我们要算出该簇号对应的 全局簇号(扇区号),因为第一个和第2个FAT不使用,所以全局簇号最后还要减2。

    step2)从软盘上 读取该扇区到内存地址 es:bx=9000:1000处,以便进行数据分析;(当然,每次循环后,偏移地址要增加512字节,也即连续读取该文件的扇区内容到 起始位置0x9000:1000处);
    step3)找出 step1 中算出扇区号在 FAT中的条目:

    • step3.1)首先,算出该扇区在FAT的 对应条目 FATentry 在 FAT中的偏移量(一个条目= 12bits = 1.5Bytes);(注意,这里的条目是FAT条目,不是根目录区条目,不要搞混了)
    • step3.2)然后算出该偏移量在哪个扇区,以及在该扇区的偏移量;
    • step3.3)读取对应FAT条目所在扇区和相邻扇区(也即读2个扇区,因为条目占1.5个字节,可能跨扇区存储)到 es:bx= (9000h-100h): 00 处;
    • step3.4)在es:bx处 对两个扇区求出 该扇区对应的 FAT条目值(即12位值);

    step4)比较FAT条目值 是否 == fffh:

    • step4.1)如果相等,则证明该条目是最后一个条目,即over了;
    • step4.2)如果不等,将该FAT条目压栈(因为它是一个链条,不断压栈,直到 fffh 出现),然后更新该文件的下一个全局扇区号(ax+RootDirSectors+DeltaSectorNo),然后再代入step2)进行循环;最后就可以找出该文件所对应的所有FAT条目,即该文件所占用的所有簇,也即所有扇区了,即是是压栈形成的那个链条值;

    step5)找到该文件占用的所有扇区后,跳转到es:bx的地址,即 jmp BaseOfLoader:OffsetOfLoader ,该 loader文件 仅仅是 打印了 字符 ‘L’ ,(该文件内容,就是刚才step2步骤中把软盘扇区中的内容读入内存 es:bx 的内容),(因为正如step2所说的那样,在上述循环过程中,程序已经把该文件的所有扇区内容读取到起始地址为 BaseOfLoader:OffsetOfLoader=0x90000:1000 的内容空间中去了)


jmp BaseOfLoader:OffsetOfLoader ; 这一句正式跳转到已加载到内
; 存中的 LOADER.BIN 的开始处,
; 开始执行 LOADER.BIN 的代码。
; Boot Sector 的使命到此结束

Attntion)其实你发现: 这个 BaseOfLoader : OffsetOfLoader 处的内容,是 LABEL_GOON_LOADING_FILE 标识符后的 ReadSector函数每次读一个扇区读进去的,而每次的起始扇区号由 GetFATEntry 函数 提供的,而 GetFATEntry 函数的作用:找到序号为 ax 的 Sector 在 FAT 中的条目, 结果放在 ax 中。就这样 ReadSector函数 + GetFATEntry 函数配合起来就把loader文件从 软盘的扇区读到了 起始内存地址 es:bx=9000h:0100 (每次循环后,偏移地址自增512字节);

Complementary)FAT的作用:当文件size 大于 512B,则FAT是找出该文件所占用的全部簇(簇:一个或多个扇区,引导扇区的BPB_SecPerClus记录该数字)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/332126.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Struts2的资源文件和国际化(i18n)

文章目录资源文件的命名资源文件基名的指定struts.xml 文件指定资源文件的基名struts.properties 文件指定资源文件的基名通过标签 i18n 指定资源文件的基名资源文件的位置包级资源文件类级资源文件全局级资源文件默认资源文件资源文件的加载顺序Action 中加载资源文件在 JSP 中…

java设计模式之装饰模式_Java中的装饰器设计模式

java设计模式之装饰模式装饰器设计模式允许在运行时将附加职责或行为动态附加到对象。 它是一种结构模式&#xff0c;利用聚合来组合这些行为。 在本教程中&#xff0c;我们将学习实现装饰器模式。 UML图&#xff1a; 让我们从装饰器模式的UML表示开始&#xff1a; Concrete…

qml 自定义消息框_Qt qml 自定义消息提示框

版权声明&#xff1a;本文为博主原创文章&#xff0c;遵循 CC 4.0 BY-SA 版权协议&#xff0c;转载请附上原文出处链接和本声明。本文链接&#xff1a;https://blog.csdn.net/a844651990/article/details/78376767Qt qml 自定义消息提示框QtQuick有提供比较传统的信息提示框Mes…

计算机器内存数量+引入和显示ARDS成员

【1】README 1.1&#xff09; 本代码在于读取内存中多个 内存段的地址范围描述符结构体&#xff08;ARDS&#xff09;&#xff0c;有多少个内存段可以用&#xff1b;1.2&#xff09; source code and images in the blog from orange’s implemention of a os 1.3&#xff09;…

Maven Java 项目中,pom.xml 文件的依赖标签作用解读(<dependency/>)

该标签会让 Maven 自动到本地仓库或远程仓库去查找构件&#xff0c;找到后会自动创建项目级别的资源库&#xff0c;然后会将资源库同步到依赖此构件的模块的 classpath 中&#xff0c;也就是模块的依赖库中&#xff0c;如下图所示&#xff1a; classpath 就是类路径&#xff0…

自我审视记录本_春天重新审视战略模式

自我审视记录本这篇博客文章希望展示另一种方法&#xff0c;该方法如何通过依赖注入实现策略模式。 作为DI框架&#xff0c;我选择Spring框架 首先&#xff0c;让我们看一下如何以经典方式实施策略模式。 作为起点&#xff0c;我们有一个HeroController &#xff0c;应该在He…

如何用python编程机器人培训_机器人编程怎么入门?

打个广告(更新于2017.03.30)坐标上海&#xff0c;上海微创医疗器械(集团)有限公司&#xff0c;机器人子公司在研产品主要是腹腔镜手术机器人、骨科手术机器人等招聘&#xff1a;机器人算法工程师软件工程师机器人控制工程师具体岗位要求&#xff0c;请移步另一个回答&#xff1…

Struts2的校验器详解/验证框架详解/校验框架详解

文章目录简介使用校验器步骤演示案例常用校验器requiredrequiredstringstringlengthregexintdoublefieldexpressionemailurldateconversionvisitorexpression参考简介 Struts2 的校验器是在后端对前端提交的数据进行校验&#xff0c;在调用 Action 的指定方法前会先调用校验器…

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

【0】README 0.0&#xff09; 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.asm0.1&#xff09;本代码仅用于在 根目录区条目中寻找 与 boot代码定义的LoaderFileName…

lambda层保存模型出错_保存您的lambda,以备不时之需-保存到文件

lambda层保存模型出错介绍 简短的帖子&#xff0c;描述了如何将Java lambda持久化到文件中以在不同的过程中重复使用。 序列化Lambda Java 8中引入的Lambda使函数成为Java语言的一等公民&#xff08;几乎&#xff09;。 他们不需要专门的类来保存函数。 但是&#xff0c;这是如…

angular4更改表单中显示的值_angular4 Form表单相关

ng4中&#xff0c;有两种方式去声明一个表单一&#xff1a;Template-Driven Forms - 模板驱动式表单 [引入FormsModule]1.ngForm赋值[可以方便的获取表单的值]nameusername[(ngModel)]login.usernamerequired>Name is required.2.ngModel绑定[ngModel会自动关联表单控件na…

A20地址线问题

【0】README text description from Zhaojiong’s perfect analysis of Linux kernel . 【1】A20地址线问题&#xff08;干货来了&#xff09; 1981年8月&#xff0c;IBM公司最初推出的个人计算机IBM PC 使用的CPU 是 Intel 8088。在该微机中地址线只有20根&#xff08;A0~A1…

java观察者设计模式_Java中的观察者设计模式

java观察者设计模式在本教程中&#xff0c;我们将讨论Observer设计模式。 观察者模式有两个主要方面- 主题和观察者 。 当我们的系统有多个对象&#xff08;称为观察者&#xff09;时 &#xff0c;将使用一个模式&#xff0c;即依赖于一个特定对象&#xff08; 主体&#xff0…

MacOS好用的截图工具

iShot 可以截取长图 高级功能需要付费 jietu 可以截图、录gif、MP4等等&#xff0c;自定义区域、全屏或者窗口&#xff0c;简直不要太方便。 Shottr 介绍地址&#xff1a; https://sspai.com/post/71485 https://www.appinn.com/shottr-for-macos/ cleanshot x Snipaste X…

js截取url问号前面_js截取url问号后参数并转化为对象

题目&#xff1a;js截取url问号后参数并转化为对象&#xff1b;function urlToObj(str){var obj {};var arr1 str.split("?");var arr2 arr1[1].split("&");for(var i0 ; i < arr2.length; i){var res arr2[i].split("");obj[res[0]…

HashMap的学习

文章目录HashMap特点原理示意图常用方法遍历元素LinkedHashMapHashMap 特点 1.世界上查询速度最快的数据结构 2.增删速度也很快 3.加载因子是集合存放的元素数量和散列数组长度的比值&#xff0c;建议加载因子 0.75&#xff0c;超过会自动扩容并且重新散列&#xff08;旧的数…

特权级概述(哥子就想知道CPU是如何验证特权级的)GATE+TSS

【0】README text description from orange’s implemention of a os . 【1】特权级概述 当当前代码段试图访问一个段或者门时&#xff0c;目标段的DPL将会和 CPL 以及段或门选择子的RPL相比较&#xff0c;如何比较&#xff1a;&#xff08;这里是干货&#xff09; &#xf…

java设计模式 订阅模式_Java中的复合设计模式

java设计模式 订阅模式当我们必须使用对象的树状分层结构时&#xff0c;复合设计模式非常有用。 它使我们能够统一对待单个对象和对象组成。 它属于结构设计模式的范畴&#xff0c;因为它将对象组合成树形结构以表示部分整个层次结构。 UML表示形式&#xff1a; 复合模式的UM…

python 短网址_Python实现短网址ShortUrl的Hash运算实例讲解

本文实例讲述了Python实现短网址ShortUrl的Hash运算方法。分享给大家供大家参考。具体如下&#xff1a;shorturl实现常见的做法都是将原始Url存储到数据库&#xff0c;由数据库返回一个对应ID。以下要实现的是不用数据库支持就对原始URL进行shorturl hash。说到这里我们很容易想…

xml json 比较_JSON和XML:它们如何比较?

xml json 比较JSON和XML&#xff1a;它们如何比较&#xff1f; JSON和XML是两种人类可读的文本格式&#xff0c;多年来已成为竞争对手。 XML的目的是通过可选使用模式来存储和定义文档和数据。 JSON几乎完全相反-序列化格式的要求非常简单&#xff0c;可以放在信用卡背面。 但是…