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

📄 mbr.asm

📁 自己以前写的 引导扇区代码。包括: fat12.asm fat16.asm fat32.asm
💻 ASM
字号:
;goto batend
;==================================================================================
;			Bats 硬盘主引导记录源代码文件
;文件名:	mbr.s
;位    置:	\batsdev\src\bootsect
;版    本:	测试版,0.01
;功    能:	读入Bats分区或活动分区引导记录到 0000:7c00,并转移控制权
;入口参数:	dl=驱动器号,由int19h提供
;出口参数:	自举驱动器号=[ss:bp-2]=0000:7bfe
;		cf=1
;		[ss:bp-4]='BF'
;		满足以上两条说明为本引导程序所引导,否则,BFS分区引导记录
;		需要从新读卷索引到 0000:7e00
;配置要求: 	80386及以上CPU
;编    译:	nasm 0.98
;命    令:	nasm -fbin fat12.s -o fat12.bin
;说    明:
;		1: 关于.struc,char,unsigned宏的定义在 .\inc\macro.inc中已有说明。
;		2: PART_TAB(硬盘分区表) ,在 .\inc\disk.inc中有定义
;						Bats工作组2004年7月
;另外说一下:这个程序有待完善。能正常引导计算机,而且能正常启动,也有正常的错误处理
;但还不知道对linux的兼容性如何
;==================================================================================
%include ".\inc\macro.inc"
%include ".\inc\disk.inc"

%define		Offset_BatsF	[bp-8]
%define		Extint13Flag	[bp-6]
%define		BatsMBRFlag	[bp-4]
%define		BootDriver		[bp-2]
%define		PBRSectFlag	[0x7dfa]
;==================================================================================
COUNT_Retry		EQU	5	;出现错误的最多重试次数

IP_BootMove		EQU	0x0600	;代码被移动后的偏移地址 	0000:0600
IP_BootBase		EQU	0x7c00	;移动数据前的偏移地址		0000:7c00
Quan_Sector		EQU	2	;读2个扇区,专为 BATS分
					;区引导程序而设计
OldInt13_SectQuan	EQU	0x202	;使用旧的INT13H读盘功能号及扇区数
;----------------------------------------------------------------------------------
org 0x600
Realboot:
	xor ax,ax
	mov es,ax
	mov ds,ax
	mov di,IP_BootMove
	mov bp,IP_BootBase
	cli
	mov ss,ax
	mov sp,bp
	sti
	mov si,bp
	mov ch,1
	cld
	repnz	movsw		;将代码本身移到 0000:0600
	jmp near $+IP_BootMove+3-IP_BootBase
				;转移到新的代码地址
;======================================================================================
	push dx			;BootDriver
	push word 'BF'		;BatsMBRFlag
	push word 0x0a13	;Extint13Flag
	mov si,@MBR_PART	;取分区表地址
	mov cl,4		;设置检索分区表的次数
Check_BATS:
	cmp byte [si .PT_SystFlag],Flag_BATSPART
				;检查分区的操作系统是否是 BATS
				;Flag_BATSPART=0xbf
	jz BATS_PartBOOT	;是--->从 BFS 分区启动
	add si,size_PART_TAB	;检查下一个表,size_PART_TAB=0x10
	loop Check_BATS
	push bp
BATS_Active:			;如果从BATS分区读出的引导记录不正确,
					;则从活动分区引导
	mov  word Extint13Flag,bp
	mov  word BatsMBRFlag,bp
	push word 0x80		;设置标志,从活动分区引导
	mov si,@MBR_PART	;找不到 BATS 分区就从活动分区启动
	mov cl,4
Check_Active:
	cmp byte [si],Flag_HdiskActive
					;检查是否活动分区
	jz Check_EXTint13
	add si,size_PART_TAB	;检查下一个表
	loop	Check_Active
	mov si,@No_Active	;没有活动分区:显示错误信息
	jmp ERROR_MESSAGE
BATS_PartBOOT:
	mov	ax,IP_BootBase-0x600+4
	add	ax,si
	push	ax			;Offset_BatsF
	push word 0xbf		;设置标志,从BFS分区引导
Check_EXTint13:			;检查是否可以使用扩展int13h读盘
	mov ah,0x41
	mov bx,0x55aa
	int 0x13
	jc Old_Int13_Read	;驱动器不支持扩展int13h--->转
	cmp bh,0xaa
	jnz Old_Int13_Read	;BIOS无扩展int13h--->转
	test cl,1
	jnz Old_Int13_Read	;不支持第一个子集--->转
;==========================================================================
USE_ExtInt13:			;采用扩展int13h读盘
	mov word Extint13Flag,0x0e13;标志。可以使用扩展INT13H
	mov cx,Quan_Sector	;把要读的扇区数保存到 cx 中
	mov bx,bp		;读到 0000:7c00
	mov eax,[si .PT_LStasect]
				;取分区第一个扇区的绝对扇区号
	call Fun_ExtInt13	;调用子过程
	jc Old_Int13_Read	;不正确,转int13h(旧)读盘
Read_True:
	pop ax
	cmp al,0x80		;
	jz CHECK_SECTFLAG	;是活动分区:无法在确定从其他分区引导
	cmp dword PBRSectFlag,0x73746142;[0x7dfa]
	jnz BATSFLAGERROR	;有一个不是则跳转错误处理
	jmp short CHECK_SECTFLAG
BATSFLAGERROR:
	mov dx,BootDriver		;dx=[bp-2]=引导的物理驱动器号
	jmp BATS_Active		;不是?选择活动分区再次重试
;==========================================================================	
CHECK_SECTFLAG:
	cmp word [MBR_BootFlag],Flag_BootSect
				;分区引导扇区的最后2个字节是否0xaa55
	jnz Inva_BootFlag	;否--->检查上一次的引导分区(是否是BFS分区)
	push cs			;CS入栈		0000
	push bp			;BP入栈		7c00
	stc			;设置标志
	retf			;转到 0000:7c00 开始执行分区引导程序
Old_Int13_Read:			;int13h读盘
	mov bx,bp		;读到 0000:7c00
	mov dh,[si .PT_StartTra];取磁道号
	mov cx,[si .PT_StartSec];取柱面号和扇区号
	mov si,COUNT_Retry	;读5次
Error_Next:
	mov ax,OldInt13_SectQuan
				;读盘功能号及扇区数
	int 0x13
	jnc Read_True		;读成功--->转
	dec si			;不成功计数器减1
	jnz Error_Next		;不到5次,继续读
	mov si, @Bad_Disk	;很遗憾,5次都没有读成功,肯定买到Y硬盘...
	jmp ERROR_MESSAGE	;显示错误信息
;===========================================================================
Inva_BootFlag:			;无效的分区引导扇区标志
	mov si, @Sect_Error
	jmp ERROR_MESSAGE
;===========================================================================
Fun_ExtInt13:			;使用扩展int13读盘子程序
	push si			;保存si到堆栈(si指向活动分区表地址)
	push cs			;cs=0
	push cs			;cs=0
	push eax		;eax=绝对扇区号
	push es			;读数据到指定的段
	push bx			;段内的偏移
	push cx			;读多少扇区
	push word 0x10		;说明这个数据包的大小为 16字节
	mov si,sp		;ds:si指向数据包的位置
	push dx			;保存驱动器号到堆栈
	mov ah,0x42		;扩展int13h的读盘功能号
	int 0x13		;扩展读盘
	pop dx			;弹出驱动器号
	add sp,0x10		;跳过堆栈中的数据包位置
	pop si			;弹出 活动分区表地址
	ret			;返回
ERROR_MESSAGE:
	lodsb			;从 ds:si中读入一个字符到 al
	or al,al		;检测字符是否为0
	jz ReBoot		;显示完毕, 退出过程
	mov bl, 12
	mov ah, 0eh
	int 10h
	jmp short ERROR_MESSAGE	;重复操作
ReBoot:
	xor ax,ax
	int 0x16
	int 0x18
;=======================================================================
;是错误信息
@Sect_Error	EQU	$-0
 DB 0dh,0ah,"Invalid Partition Boot Sector ...",0
@Bad_Disk 	EQU	$-0
 DB 0dh,0ah,"Disk I/O error or bad disk ...",0
@No_Active 	EQU	$-0
 DB 0dh,0ah,"Can't find Active Parttion ..."
;=======================================================================
;分区表
SETADD 442
	DB "Bats"
SETADD Offset_PARTAB
	.PART_TAB	MBR_PART, 4
;=======================================================================
;引导扇区有效的结束标志
MBR_BootFlag	EQU $-0
		dw Flag_BootSect
;:batend
;\batsdev\bin\nasm -fbin %0 -o mbr.bin -E \batsdev\src\debug\mbr.err
;\batsdev\bin\nasm -e %0 -o \batsdev\src\debug\mbr.dbg

⌨️ 快捷键说明

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