⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 复件 fat32.asm

📁 自己以前写的 引导扇区代码。包括: fat12.asm fat16.asm fat32.asm
💻 ASM
📖 第 1 页 / 共 2 页
字号:
		dd	0x44
		dd	0x45
		dd	0x46
BeginSecend:
		mov	si,	OtherInfo+1
		mov	bx,	Reg_IP_Base+0x400	;BX=7c00+400=8000(Hex)
							;跳过前2扇区内存区域
		movzx	di,	[OtherInfo]		;取扇区数
		push	di
LoadOther:
		lodsd
		inc	cx				;读一扇区
		call	Read_Disk
		jc	OtherError
		dec	di
		jnz	LoadOther			;未读完,继续
		pop	cx				;CX=[OtherInfo]
		mov	bx,	SectorFlag+1
;==================================================================================
;标志检测
;该标志为 Fans Bootsector 的固有标志,总共4字节,其值必须为46,61,55,AA
;仅检测中间2字节,即:61,55
;==================================================================================
ScanFlag:
		add	bx,	0x200
		mov	ax,	0x5561
		cmp	ax,	[bx]
		jnz	OtherError
		loop	ScanFlag
		jmp	near	BeginOther
OtherError:
		mov	si,	ERR_DSK
		mov	bp,	disk_dot
		push	word	BootFail
;==================================================================================
;		PrintCh		功能	显示字符串
;				入口:			cs:si=字符串地址
;							cs:bp=点阵信息(char>128)
;				出口:			ds=cs
;							es=cs
;可能改变的寄存器: eax,ebx,ecx,edx,esi,ebp,ds,es
;未改变的寄存器有: edi,esp,ss
;特别说明:该过程使用 BIOS INT 0x10 第11号子功能。更详细的说明参看
;		罗云彬所发表的《文本模式下图形字符的显示》一文
;		文章出处: http://asm.yeah.net
;==================================================================================
proc PrintCh:
		push	cs
		pop	ds
		push	cs
		pop	es
		cld
.Nextp:
		lodsb
		cmp	al,	0x80
		jb	.Display			; AL<0x80为 ASCII字符
		push	ax
		movzx	dx,	al
		mov	ax,	0x1100			; Bios int0x10 第11号功能
							; 设置字符点阵
		mov	bx,	0x1000
		mov	cx,	1
		int	0x10
		add	bp,	0x10
		pop	ax
.Display:
		mov	ah,	0x0e
		int	0x10
		cmp	al,	'!'
		jnz	.Nextp
		ret
endp
DISKERRMSGDOT
;==================================================================================
times Flag_Offset+0x200-($-$$)	db	0
SectorFlag				dw	'Fa'
					dw	Flag_BootSect
;==================================================================================
%define		StartFat	BP-4
%define		StartRoot	BP-8
%define		StartData	BP-12
%define		RootSectors	BP-16
;==================================================================================
;计算磁盘参数
BeginOther:
		movzx	esi,	word	[bp+ResaveSect-Reg_IP_Base]
							; 保留扇区数
		add	esi,	[bp+HidSectors-Reg_IP_Base]		
							;隐含扇区数
		push	esi				; [BP-04] = FAT 表区域的起
							;		  始扇区号
		movzx	eax,	byte	[bp+FatOfDisk-Reg_IP_Base]
							;FAT 表个数
		mov	bx,	[bp+SectPreFat-Reg_IP_Base]	
							; 每个 FAT占用扇区数
		mul	bx
		add	esi,	eax
		push	esi				; [BP-08] = 根目录区域的起
							;		  始扇区号
		movzx	eax,	word	[bp+FileOfRoot-Reg_IP_Base]
							; 根目录文件数
		mov	bx,	word	[bp+SectSize-Reg_IP_Base]
							; 每扇区字节数
		shr	bx,	5			; BX = BX/ 32  
							; 每目录登记项长度 32 字节
		cwd 
		div	bx				; EAX=根目录占用扇区数
		add	esi,	eax
		push	esi				; [BP-12] = 磁盘数据区起始
							;		      地址
		push	eax				; [BP-16] = EAX = 根目录占
							;		  用扇区数
;==================================================================================
;以下部分代码为读根目录表并且查找文件
		mov	eax,	[StartRoot]		; 根目录起始扇区号
		mov	cx,	[RootSectors]		; 根目录占用扇区数
		push	word	Seg_CS_Boot
		pop	es				; ES:BX = Seg_CS_Boot:0000
		xor	bx,	bx
		call	Read_Disk
		jc	Error_Read
		mov	si,	FileSystemDrv
		call	ScanFile			; 查找文件
		jc	Error_Drv
		push	eax				; [BP-20] = FS.DRV 的首簇号
		mov	si,	BootFilename
		call	ScanFile
		jc	Error_Kernel
;==================================================================================
;取文件FAT扇区信息到堆栈
		push	es				; ES=Seg_CS_Boot
		pop	ds				; 将DS置为缓冲区段
		push	eax
		mov	si,	-24			; [BP+SI]=[BP-24]
							; =KERNEL.SYS的首簇号
		call	SaveFat				; 存FAT信息到堆栈
		jc	Error_Kernel			; 错误处理
		mov	si,	-20			; [BP-20]=FS.DRV的首簇号
		call	SaveFat
		jc	Error_Drv
		mov	si,	[bp-24]			; 准备装载 KERNEL.SYS
		xor	bx,	bx
		push	ss				; SS=0000
		pop	ds
		mov	byte [bp+3],0xfe		; [BH+3]=-2, 文件计数器
							; 表示读2个文件
;==================================================================================
;装载文件到内存
Load_Kernel:
		std
		lodsd
		mov	cl,	[bp+SectOfCurs-Reg_IP_Base]
							; 每簇扇区数
		or	ax,	ax
		jz	Load_NF				; 装载下一个文件
		call	Read_Disk
		jnc	Load_Kernel			; 无错误,继续读
Error_Read:
		mov	bp,	disk_dot		; 磁盘错误
		mov	si,	ERR_DSK
		jmp	short	ErrCall
Load_NF:
		xor	bx,	bx
		push	word	Seg_FS_Boot		; 读第2个文件到
		pop	es				; Seg_FS_Boot:0000
		inc	byte	[bp+3]			; 文件计数器+1
		jnz	Load_Kernel
		db	0xea
		dw	0,	Seg_CS_Boot+0x20
Error_Drv:
		mov	si,	ERR_DRV			; FAT16.DRV出错
		jmp	short	ErrLeaDot
Error_Kernel:
		mov	si,	ERR_KNL			; KERNEL.SYS出错
ErrLeaDot:
		mov	bp,	Other_dot		; 错误信息的字模指针
ErrCall:
		call	PrintCh
		jmp	BootFail
;==================================================================================
;		SaveFat		功能	保存文件的FAT信息
;				入口:			[BP+SI]=文件首簇号
;				出口:	CF=0	成功	[BP+SI]=文件簇链表指针
;					CF=1	失败
;				说明:			使用 SS 寻址
;保存文件的FAT信息
;该过程使用堆栈作为缓冲区,将文件的每一簇起始位置的绝对扇区号保存到缓冲区
;堆栈:
;				|      Stack	 |
;				|----------------|<<<<<<< stack	low address
;			DI--->	|   父过程地址	 | ret; [ss:sp]-->IP;SP+=2
;				|----------------|
;				|   0x00000000   |
;				|----------------|
;				|   FAT16.DRV    |
;				|----------------|
;				|   0x00000000	 |Buffer NULL
;				|----------------|
;				|      ...	 | \
;				|      ...	 |  \
;				|     Buffer	 |   |-> KERNEL.SYS
;IF pop di & mov ebx,sp & dec bx|     Buffer	 |  /
;dec bx Then BX=Offset Buffer-->|   父过程地址   | /   ----> DI  //pop di;
;  该地址在执行后变成文\	|----------------|
;			| ----> |  KERNEL.SYS	 |\		---->low word
;  件簇连表缓冲区首指针/	|-----  &&  -----| |---> EAX //mov eax,[bp+si]
;				|     首簇号	 |/		---->high word
;  该地址在执行后变成文\	|----------------|
;			| ----> |   FAT16.DRV	 |\		---->low word
;  件簇连表缓冲区首指针/	|-----  &&  -----| |---> EAX //mov eax,[bp+si]
;				|     首簇号	 |/		---->high word
;				|----------------|<<<<<<< stack	high address
;				|   OtherBuffer	 |
;==================================================================================
proc SaveFat:
		mov	eax,	[bp+si]			; [bp+si]=文件首簇号指针
		movzx	ebx,	sp
		pop	di
		dec	bx
		dec	bx				; 计算指针首地址
		mov	[bp+si],	bx		; 存首地址
		inc	ax
.next:
		dec	ax
		push	eax
		cdq
		dec	ax
		dec	ax
		mov	dl,	[bp+SectOfCurs-Reg_IP_Base]
							; edx=每簇扇区数
		mul	edx				; eax=该簇的DOS扇区号
		add	eax,	[StartData]		; eax=该簇的绝对磁盘扇区号
		mov	edx,	eax
		pop	eax
		push	edx				; 保存绝对扇区号
		cdq
		shl	eax,	1			; eax=簇的偏移地址=簇号*2
		mov	si,	[bp+SectSize-Reg_IP_Base]
							; ecx=每扇区字节数
		div	esi				; eax=DOS扇区号
		add	eax,	[bp-4]			; eax=下一簇号的绝对扇区号
		mov	esi,	edx			; esi=下一簇号在扇区中的偏移地址
		mov	bx,	cx			; cx=0
		inc	cx
		call	Read_Disk
		jc	.Error
		lodsw
		inc	ax
		jnz	.next
		push	eax				; 置结束标志,eax=0
		clc
.Error:
		push	di
		ret
endp
;==================================================================================
;		ScanFile	功能	扫描根目录区的文件并将 es:si所指文件
;					的首簇号放在 eax中
;				入口:			ds:si=文件名
;							es:0=缓冲区地址
;				出口:	CF=0	成功,	eax=文件首簇号
;					CF=1	失败
;==================================================================================
proc ScanFile:
		xor	di,	di
		cld
.nextScan:
		push	si
		push	di
		mov	cx,	fNameSize		;CX=11
		repe	cmpsb				;IF ZR THEN REP
		pop	di
		pop	si
		clc
		jz	.ScanDown			;所有字符比较均相等
		add	di,	32			;每文件登记项长度为32
		sub	byte	[es:di],0
		jnz	.nextScan
		stc
.ScanDown
		movzx	eax,	word [es:di+0x1a]
		ret
endp
;==================================================================================
times Flag_Offset+0x400-($-$$)	db	0
				dw	'Fa'
				dw	Flag_BootSect
;==================================================================================
;ERRORMESSAGEDOT在".\language\*.inc"已有定义
ERRORMESSAGEDOT
times Flag_Offset+0x600-($-$$)	db	0
				dw	'Fa'
				dw	Flag_BootSect
;==================================================================================

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -