`
jjchen_lian
  • 浏览: 87211 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

于渊-动手写操作系统2

 
阅读更多

既然我们能够通过根目录条目找到DIR_FstClus了,这个字段告诉了我们文件开始的簇号,它告诉我们文件存放在磁盘的什么位置,从而让我们可以找到它。其实准确来说,这里应该是它告诉了我们文件存放在磁盘数据区的什么位置。需要注意的是,数据区的第一个簇的簇号是2,而不是0或者1.也就是说,如果我们在根目录条目中发现了一个文件,该文件的开始簇号是2,那么就是说,该文件的数据开始于数据区的第一个簇。

那么既然我们可以通过根目录区找到改文件它在磁盘的位置,那么我们还要FAT做什么,原因是对于小于512字节的文件来说,FAT表用处并不大,但如果大于512字节,那么我们就需要依靠FAT表来找到所有的簇,即找到该文件分布在磁盘中的扇区。

FAT表是什么?它有点像一个位图,其中,每12位称为一个FAT项(FATEntry),代表一个簇。第0个和第1个FAT项始终不使用,从第2个FAT项开始表示数据区的每一个簇,也就是说,第2个FAT项表示数据区的第一个簇,这与数据区的第一个簇的簇号为2相呼应的。

由于每个FAT项占12位,包含一个字节和另一个字节的一半,所以显得有点别扭,假设连续3个字节分别如下,那么灰色框表示的是前一个FAT项(FATEntry1),BYTE1是FATEntry的低8位,BYTE2是FATEntry的高4位,白色框表示的是后一个FAT项(FATEntry2),BYTE2的高4位是FATEntry2的低4位,BYTE3是FATEntry2的高8位。



 

那么FAT项的值代表的是什么呢?因为我们上面说过,我们要依靠FAT表来找到这个文件分布的位置,那么很容易想到FAT项的值就是代表文件的一个簇号,有点类似链表的感觉,如果FAT项的值大于0xFF8,则表示当前簇号已经是文件的最后一个簇了,如果值是0xFF7,表示它是一个坏簇。

那么我们把之前的boot.asm的LABEL_FILENAME_FOUND:jmp做下面的修改

;; 既然发现有LOADER.BIN了,那我们就需要将它加载到内存来了
LABEL_FILENAME_FOUND:
	mov	ax, RootDirSectors ;ax=14个扇区
	and	di, 0FFE0h	  ;di -> 当前条目的开始
	add	di, 01Ah	  ;di -> 首Sector根目录条目的前26个字节放着开始的簇号
	mov	cx, word [es:di]
	push	cx		;保存此Sector在FAT中的序号
	add	cx, ax
	add	cx, DeltaSectorNo ;这句完成时cl里面编程LOADER.BIN的其实扇区号(从0开始数的序号)
	mov	ax, BaseOfLoader  ;es -> BaseOfLoader
	mov	es, ax
	mov	bx, OffsetOfLoader ;bx -> OffsetOfLoader 于是,es:bx=BaseOfLoader:OffsetOfLoader=BaseOfLoader*10h+OffsetOfLoader
	mov	ax, cx		   ;ax <- Sector号

;; 将LOADER.BIN的内容从磁盘拷贝到内存BaseOfLoader:OffsetOfLoader的位置
LABEL_GOON_LOADING_FILE:
	push	ax
	push	bx
	mov	ah, 0Eh
	mov	bl, 0Fh
	int	10h
	pop	bx
	pop	ax

	mov	cl, 1
	call	ReadSector
	pop	ax		;取出此Sector在FAT中的序号,这里存放的是cx的值
	call	GetFATEntry
	cmp	ax, 0FFFh
	jz	LABEL_FILE_LOADED
	push	ax		;保存Sector在FAT中的序号
	mov	dx, RootDirSectors
	add	ax, dx
	add	ax, DeltaSectorNo
	add	bx, [BPB_BytsPerSec] ;往后加上512个字节
	jmp	LABEL_GOON_LOADING_FILE

我们的任务就是取出每个在FAT表中的簇号,然后转换为实际的扇区号,然后把实际扇区号中的内容load到内存进来。 

GetFATEntry的实现:

;----------------------------------------------------------------------------

;----------------------------------------------------------------------------
; 函数名: GetFATEntry
;----------------------------------------------------------------------------
; 作用:
;	找到序号为 ax 的 Sector 在 FAT 中的条目, 结果放在 ax 中
;	需要注意的是, 中间需要读 FAT 的扇区到 es:bx 处, 所以函数一开始保存了 es 和 bx
;       以上部分是整个函数的难点所在,用户计算簇号在FAT表中所对应的FATENTRY相对于FAT首地址的偏移。
;       从书上可以得知,FAT12中每个FATENTRY是12位的。所以如下:
;       7654 | 3210(byte1)    7654|3210(byte2)    7654|3210(byte3)
;       byte1和byte2的低4位表示一个Entry;根据Big-Endian,Entry内容为:3210(byte2)76543210(byte1)
;       byte3和byte2的高4位表示一个Entry;根据Big-Endian,Entry内容为:76543210(byte3)7654(byte2)
;       所以这里存在一个奇偶数的问题,以字节为单位。以上为例,Entry0偏移为0,Entry1偏移为1,Entry2偏移为3。
;       以INT[“簇号”*1.5]的方式增加。这也就是为什么上面先乘3再除2来计算。
;       根据DIV指令规定,商保存在ax中,余数在dx中。所以此时ax就是FATENTRY在FAT中以字节为边界的偏移量。
GetFATEntry:
	push	es		;BaseOfLoader
	push	bx		;OffsetOfLoader
	push	ax		;存进此Sector在FAT中的序号
	mov	ax, BaseOfLoader
	sub	ax, 0100h	;在BaseOfLoader后面留出4K空间用于存放FAT
	mov	es, ax
	pop	ax
	mov	byte [bOdd], 0
	mov	bx, 3
	mul	bx		;dx:ax = ax * 2
	mov	bx, 2
	div	bx		;dx:ax / 2 ==> ax <- 商,dx <- 余数
	cmp	dx, 0
	jz	LABEL_EVEN
	mov	byte [bOdd], 1

;; 偶数处理
LABEL_EVEN:
	xor	dx, dx		;现在ax中是FATEntry在FAT中的偏移量,下面来计算FATEntry在哪个扇区中(FAT占用不止一个扇区)
	mov	bx, [BPB_BytsPerSec] ; dx:ax / BPB_BytsPerSec==>ax<-商(FATEntry 所在的扇区相对于 FAT 来说的扇区号)
	div	bx
	push	dx
	mov	bx, 0		;bx <- 0,于是es:bx=(BaseOfloader-100):00=(BaseOfloader-100)*10h
	add	ax, SectorNoOfFAT1 ;此句执行之后的ax就是FATEntry所在的扇区号
	mov	cl, 2
	call	ReadSector	;读取FATEntry所在的扇区,一次读两个,避免在边界发生错误,因为一个FATEntry可能跨越两个扇区
	pop	dx
	add	bx, dx
	mov	ax, [es:bx]
	cmp	byte [bOdd], 1
	jnz	LABEL_EVEN_2
	shr	ax, 4		;ax的值在此被更新

;7654 | 3210(byte1)    7654|3210(byte2)    7654|3210(byte3)
;根据上面这个例子,奇数的簇号,1,偏移为1,所以读要ax中的时候,因为ax是16位,所以根据Big-Endian,ax的内容为7654|3210(byte3)|7654|3210(byte2),所以右移4位就可以了。
;偶数簇号,0,偏移为0,读入ax后,ax的内容为7654|3210(byte2)7654 | 3210(byte1),我们只需要低12位即可,
;所以and ax,0FFFh
LABEL_EVEN_2:
	and	ax, 0FFFh

LABEL_GET_FAT_ENRY_OK:
	pop	bx
	pop	es
	ret

最后再来一个跳转:

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

 

 loader.asm内容如下:

org	0100h

	mov	ax, 0B800h
	mov	gs, ax
	mov	ah, 0Fh				; 0000: 黑底    1111: 白字
	mov	al, 'L'
	mov	[gs:((80 * 0 + 39) * 2)], ax	; 屏幕第 0 行, 第 39 列

	jmp	$				; 到此停住

 运行效果:




 

  • 大小: 13.4 KB
  • 大小: 143.6 KB
分享到:
评论

相关推荐

    自己动手写操作系统(于渊-含代码).rar

    本资源为《自己动手写操作系统》由于渊编写,它不仅为读者提供了一套完整的操作系统从无到有的开发教程,还附带了相应的源代码,使学习者能够在实践中深入理解操作系统的基本原理和开发过程。 首先,操作系统作为...

    Orange's一个操作系统的实现(于渊《自己动手写操作系统第二版》)随书光盘

    在《自己动手写操作系统第二版》中,于渊详细解释了这些概念并提供了实际的代码示例。通过分析和实践这些源代码,读者可以深入了解操作系统的内部运作机制,提升对计算机系统的理解,这对于想要深入学习操作系统原理...

    自己动手写操作系统_于渊_70M_高清(附源码).part3

    于渊的自己动手写操作系统真正高清版,原来csdn上有一个号称高清的版本,但是没有part1,太坑人了,后来自己花了好长时间才下到,不敢独享,特发出来与大家共同学习!

    《自己动手写操作系统》源码(0币)

    《自己动手写操作系统》是一本深受程序员喜爱的书籍,它以实践为导向,引导读者深入了解操作系统的工作原理,并通过编写操作系统来学习相关知识。源码的提供为读者提供了宝贵的实践机会,帮助他们将理论与实践相结合...

    orange's一个操作系统的实现-【自己动手写操作系统第二版】

    《orange's一个操作系统的实现-【自己动手写操作系统第二版】》是一本深入浅出的操作系统构建指南,作者为于渊。这本书旨在帮助读者通过实际操作来理解操作系统的原理和构造,适合对操作系统感兴趣的DIY爱好者和...

    自己动手写操作系统 -于渊 蓝光1080p

    非常清晰 非常清晰 非常清晰 非常清晰 非常清晰 非常清晰!

    自己动手写操作系统PDF 于渊 70M 超清晰版 part 4 of 5

    书名:自己动手写操作系统 作者:于渊 编著 来源:电子工业出版社 出版时间:2005年08月 ISBN:7-121-01577-3 定价:48元 内容介绍: 本书在详细分析操作系统原理的基础上,用丰富的实例代码,一步一步地指导读者用...

    自己动手写操作系统(于渊著)

    2. **环境设置**:在动手写操作系统之前,需要搭建开发环境,这可能包括选择合适的编程语言(如汇编语言或C语言),设置交叉编译工具链,以及理解虚拟机或模拟器的使用。 3. **引导加载器**:操作系统的启动是从...

    自己动手写操作系统PDF 于渊 70M 超清晰版 part 1 of 5

    书名:自己动手写操作系统 作者:于渊 编著 来源:电子工业出版社 出版时间:2005年08月 ISBN:7-121-01577-3 定价:48元 内容介绍: 本书在详细分析操作系统原理的基础上,用丰富的实例代码,一步一步地指导读者用...

    自己动手写操作系统PDF 于渊 70M 超清晰版 part 2 of 5

    书名:自己动手写操作系统 作者:于渊 编著 来源:电子工业出版社 出版时间:2005年08月 ISBN:7-121-01577-3 定价:48元 内容介绍: 本书在详细分析操作系统原理的基础上,用丰富的实例代码,一步一步地指导读者用...

    自己动手写操作系统PDF 于渊 70M 超清晰版 part 5 of 5

    书名:自己动手写操作系统 作者:于渊 编著 来源:电子工业出版社 出版时间:2005年08月 ISBN:7-121-01577-3 定价:48元 内容介绍: 本书在详细分析操作系统原理的基础上,用丰富的实例代码,一步一步地指导读者用...

    自己动手写操作系统 于渊 随书光盘

    自己动手写操作系统 于渊 随书光盘。 优秀国内原创图书!本书用丰富的实例代码,一步一步地指导读者用C语言和汇编语言编写出一个具备操作系统基本功能的操作系统框架,不同于其他的理论型书籍,本书提供给读者一个...

    于渊_自己动手写操作系统原代码

    《于渊_自己动手写操作系统原代码》可能是这样一本教程或书籍,旨在引导读者深入理解操作系统的原理,通过编写操作系统源码来实现这一目标。在这样的学习过程中,读者可以了解操作系统的主要组成部分和工作流程。 1...

    自己动手写操作系统PDF 于渊 70M 超清晰版 part 3 of 5

    书名:自己动手写操作系统 作者:于渊 编著 来源:电子工业出版社 出版时间:2005年08月 ISBN:7-121-01577-3 定价:48元 内容介绍: 本书在详细分析操作系统原理的基础上,用丰富的实例代码,一步一步地指导读者用...

    自己动手写操作系统 于渊 无水印 影印版

    自己动手写操作系统 于渊 无水印 影印版

    自己动手写操作系统光盘,自己动手写操作系统源代码

    在本文中,我们将深入探讨“自己动手写操作系统”的主题,这通常被看作是理解和学习操作系统原理的一种实践方法。这一项目由作者于渊发起,旨在帮助读者通过实际操作来理解操作系统的构建过程。 首先,我们要明白...

    自己动手写操作系统 于渊

    自己动手写操作系统 于渊 第一版 影印版

    自己动手写操作系统(于渊)工具和源码

    《自己动手写操作系统》是于渊先生撰写的一本经典教程,旨在帮助读者深入理解操作系统的原理和实现过程。这本书不仅包含了理论知识,还提供了实际的源代码和开发工具,使得学习更加直观和实践性强。 首先,我们要...

    自己动手编写操作系统(于渊)

    《自己动手编写操作系统》这本书由于渊所著,旨在帮助读者深入理解操作系统的原理,并通过实际编写代码来构建一个基本的操作系统框架。下面将详细探讨书中涉及的知识点。 首先,操作系统的基本概念和组成是学习的...

    自己动手写操作系统及光盘/于渊001

    于渊写的自己动手写操作系统,一本操作系统入门学习不错的书

Global site tag (gtag.js) - Google Analytics