分享
 
 
 

主引导扇区代码(MBR)

王朝other·作者佚名  2006-01-10
窄屏简体版  字體: |||超大  

;====================================================================

;

; FlyingDragon MBR ( Master Boot Record )

;

; Author : Jack

; History:

; 0.01 - 2005-08-13 19:34 采用传统的CHS磁盘调用

; 0.02 - 2005-08-23 19:44 优先采用扩展磁盘调用

;

; Build : nasm -f bin MBR.ASM -oMBR.BIN

;

;====================================================================================

;

; MBR( Master Boot Record )主引导记录包含两部分的内容,前446字节为启动代码及数据,而

; 从446(0x1BE)开始则是分区表,分区表由四个分区项组成,每个分区项数据为16字节,记录了

; 启动时需要的分区参数。

;

; 在CPU上电之后,若由硬盘启动,则BIOS将硬盘的主引导记录(位于0柱面、0磁道、1扇区)读

; 入7C00处,然后将控制权交给主引导代码。主引导代码的任务包括:

; (1) 扫描分区表,找到一个激活(可引导)分区;

; (2) 找到激活分区的起始扇区;

; (3) 将激活分区的引导扇区装载到内存7C00处;

; (4) 将控制权交给引导扇区代码;

;

; 如果主引导代码无法完成上述任务,它将显示以下错误信息之一:

; No active partition.

; Invalid partition table.

; Error loading operating system.

; Missing operating system.

;

;====================================================================================

; FAT16分区尺寸与LBA

;====================================================================================

; LBA HeadsPerCylinder SectorsPerTrack Maximum Size for Boot Partition

; Disabled 64 32 1GB

; Enabled 255 63 4GB

;

; 为了适应超过8G的硬盘,Windows2000忽略了Start CHS和End CHS,而使用StartLBA和TotalSector

; 来确定分区在整个磁盘中的位置和大小。

;

;====================================================================================

; 分区表项结构(16字节)

;====================================================================================

;

; typedef struct _PARTITION_ENTRY

; {

; UCHAR BootIndicator; // 能否启动标志

; UCHAR StartHead; // 该分区起始磁头号

; UCHAR StartSector; // 起始柱面号高2位:6位起始扇区号

; UCHAR StartCylinder; // 起始柱面号低8位

; UCHAR PartitionType; // 分区类型

; UCHAR EndHead; // 该分区终止磁头号

; UCHAR EndSector; // 终止柱面号高2位:6位终止扇区号

; UCHAR EndCylinder; // 终止柱面号低8位

; ULONG StartLBA; // 起始扇区号

; ULONG TotalSector; // 分区尺寸(总扇区数)

; }PARTITION_ENTRY,*PPARTITION_ENTRY;

;

;====================================================================================

; 主引导记录(MBR)结构

;====================================================================================

; typedef struct _MASTER_BOOT_RECORD

; {

; UCHAR BootCode[446];

; PARTITION_ENTRY Partition[4];

; USHORT Signature;

; }MASTER_BOOT_RECORD,*PMASTER_BOOT_RECORD;

;

;====================================================================================

BITS 16 ; 生成16位代码而不是32位代码

SECTION .text ; 代码段

ORG 0600H ; 指定程序被装入内存的起始位置

;====================================================================

;

; 宏和常量定义

;

;====================================================================

? EQU 0 ; NASM不支持DW ?这样的语法,可以使用这样的定义

; 模拟,以使代码的可读性更强

ACTIVE_FLAG EQU 80H ; 激活(可引导)分区标志

NOT_ACTIVE_FLAG EQU 00H ; 不激活标志

MBR_MOVE_ADDR EQU 0600H ; MBR先移动自身到该位置然后再运行

BOOT_SIGNATURE EQU 0AA55H ; 启动标志

SEC_SIG_OFF EQU 01FEH ; 启动扇区的标志位置

;====================================================================

; 分区表项结构偏移

;====================================================================

BootIndicator EQU 0 ; 能否启动标志

StartHead EQU 1 ; 该分区起始磁头号

StartSector EQU 2 ; 起始柱面号高2位:6位起始扇区号

StartCylinder EQU 3 ; 起始柱面号低8位

PartitionType EQU 4 ; 分区类型

EndHead EQU 5 ; 该分区终止磁头号

EndSector EQU 6 ; 终止柱面号高2位:6位终止扇区号

EndCylinder EQU 7 ; 终止柱面号低8位

StartLBA EQU 8 ; 起始扇区号

TotalSector EQU 12 ; 分区尺寸(总扇区数)

;====================================================================

; 常用的分区类型

;====================================================================

PARTITION_TYPE_EMPTY EQU 00H ; 空分区

PARTITION_TYPE_FAT12 EQU 01H ; FAT12 ( < 32680 sectors )

PARTITION_TYPE_FAT16 EQU 04H ; FAT16 ( 32680 - 65535 sectors )

PARTITION_TYPE_EXTENDED EQU 05H ; DOS EXTENDED

PARTITION_TYPE_BIGDOS_FAT16 EQU 06H ; FAT16 ( 33MB - 4GB )

PARTITION_TYPE_NTFS EQU 07H ; NTFS

PARTITION_TYPE_FAT32 EQU 0BH ; FAT32

PARTITION_TYPE_FAT32_LBA EQU 0CH ; FAT32 LBA

PARTITION_TYPE_FAT16_LBA EQU 0EH ; FAT16 LBA

PARTITION_TYPE_EXTENDED_LBA EQU 0FH ; LBA EXTENDED

PARTITION_TYPE_DYNAMIC_DISK EQU 42H ; Dynamic Disk Volume

;====================================================================

; 主引导记录的入口

;====================================================================

_ENTRY_POINT:

; 初始化相关寄存器及标志位

CLI ; 先关掉中断

CLD ; 方向为向前递增

XOR AX,AX ; AX = 0

MOV DS,AX ; 设置数据段寄存器 DS:SI

MOV ES,AX ; 设置附加段寄存器 ES:DI

MOV SS,AX ; 设置堆栈段寄存器

MOV BP,7C00H ; 设置基址寄存器

MOV SP,BP ; 设置堆栈栈顶

; 将MBR代码移动到0600H处

MOV SI,BP ; SI = 7C00H

MOV DI,MBR_MOVE_ADDR; DI = 0600H

MOV CX,512 ; 待移动的字节数

REP MOVSB

JMP 0:.RealStart

; 真正开始

.RealStart:

; 保存引导驱动器号

MOV BYTE [ DriveNumber ] , DL

;====================================================================

; 检查是否支持磁盘中断INT 13H的扩展

;====================================================================

MOV AH,41H

MOV BX,055AAH

INT 13H

JC .LookupActive ; 如果失败,进位标志为1

MOV BYTE[DiskExtension],01H ; 设置支持磁盘扩展标志

.LookupActive:

; 查找激活分区

MOV BP,PartitionTable ; 指向分区表

MOV BL,4 ; 最多4个分区

;检查激活分区

.CheckNext:

CMP BYTE [BP+BootIndicator],ACTIVE_FLAG ; 检查该分区是否激活

JZ .FoundActive ; 找到激活分区

CMP BYTE [BP+BootIndicator],NOT_ACTIVE_FLAG ; 检查该分区是否激活

JNZ .InvalidTable ; 无效值

ADD BP,10H ; 指向下一个分区表项

DEC BL

JZ .NoActive ; 没有找到激活分区

JMP .CheckNext

;找到了激活分区

.FoundActive:

; 保存分区表项

MOV AL,4

SUB AL,BL ; AL = 4-BL = 第一个激活分区表项索引(0-3)

MOV BYTE [ActivePartition],AL ; 保存激活分区表项索引

MOV DI,BP ; DI = 激活分区项

MOV DH,BYTE[BP+StartHead] ; 该分区起始磁头号

MOV CL,BYTE[BP+StartSector] ; 起始柱面号高2位:6位起始扇区号

MOV CH,BYTE[BP+StartCylinder] ; 起始柱面号低8位

; 保存起始扇区号

MOV AX,WORD[BP+StartLBA+2]

MOV WORD[DAP_SECTOR_LOW+2],AX

MOV AX,WORD[BP+StartLBA]

MOV WORD[DAP_SECTOR_LOW],AX

; 检查确信只有一个激活分区

.Recheck:

ADD BP,10H ; 指向下一个分区项

DEC BL

JZ .LoadBootSector ; 装载该分区的引导扇区

CMP BYTE [BP+BootIndicator],NOT_ACTIVE_FLAG ; 检查该分区是否激活

JNZ .InvalidTable ; 无效值

JMP .Recheck

; 装载激活分区的引导扇区

.LoadBootSector:

; 设置驱动器号

MOV DL,BYTE [DriveNumber]

; 检查是否支持扩展磁盘调用

CMP BYTE [DiskExtension],01H

JNZ .NoDiskExtension

; 使用扩展磁盘调用读取引导扇区

;

; INT 13H

; AH = 42H

; DL = Drive Number

; DS:SI = 指向磁盘地址包的指针

;

MOV SI,DAP_PACKET_SIZE

MOV AH,42H

INT 13H

JC .ErrorLoadOS

JMP .CheckBootSector

.NoDiskExtension:

;====================================================================

;

; INT 13H

; AH = 2 柱面号:0 - 1023

; AL = 要读取的扇区数 磁头号:0 - 255

; CH = 柱面号低8位 扇区号:1 - 63

; CL = 柱面号高2位 : 6位扇区号

; DH = 磁头号

; DL = 驱动器号

; ES:BX = 缓冲区

;

;====================================================================

; 读取引导扇区

MOV BX,7C00H

MOV AX,0201H

INT 13H

JC .ErrorLoadOS

; 检查引导扇区是否合法

.CheckBootSector:

; 装载引导扇区成功,检查引导标志

MOV BX,7C00H

CMP WORD [BX+SEC_SIG_OFF], BOOT_SIGNATURE ; 检查引导标志

JNZ .MissingOS

; 准备跳转到激活扇区的引导扇区代码

; DL = 磁盘驱动器号

; DH = 激活分区号

; DI = 激活分区项

MOV DL,BYTE [DriveNumber]

MOV DH,BYTE [ActivePartition]

JMP 0:7C00H

; 没有激活分区

.NoActive:

MOV SI,MsgNoActive

CALL ShowMessage

JMP .Hang

; 无效分区表

.InvalidTable:

MOV SI,MsgPartitionTable

CALL ShowMessage

JMP .Hang

; 装载引导扇区失败

.ErrorLoadOS:

MOV SI,MsgLoadingOS

CALL ShowMessage

JMP .Hang

; 引导扇区不合法

.MissingOS:

MOV SI,MsgMissingOS

CALL ShowMessage

.Hang:

JMP .Hang

;====================================================================

;

; 显示一个字符串

; 输入:

; DS:SI = 字符串的起始地址(以NULL结束)

;

;====================================================================

ShowMessage:

LODSB ; AL = DS:[SI] SI = SI+1

OR AL,AL ; 检测是否遇到NULL字符串

JZ .ShowEnd

MOV AH,0EH

MOV BX,07H

INT 10H

JMP ShowMessage

.ShowEnd:

RET

;====================================================================

; 调试例程

;====================================================================

%IFDEF DEBUG

;====================================================================

;

; 显示一个字符

; 输入: AL = 待显示字符

;

;====================================================================

PrintChar:

PUSH AX

PUSH BX

MOV AH,0EH

MOV BX,7

INT 10H

POP BX

POP AX

RET

;====================================================================

;

; 显示16进制的值(将一个BYTE变为两个ASCII字符打印出来,用于调试)

; 输入: AL = 待显示的字节

;

;====================================================================

PrintByte:

PUSH BX

MOV BH,AL

; 显示高4位

SHR AL,4

AND AL,0FH

ADD AL,30H

CMP AL,39H

JLE .PrintIt

ADD AL,07H

.PrintIt:

CALL PrintChar

; 显示低4位

MOV AL,BH

AND AL,0FH

ADD AL,30H

CMP AL,39H

JLE .PrintItAgain

ADD AL,07H

.PrintItAgain

CALL PrintChar

POP BX

RET

%ENDIF ; DEBUG

;====================================================================

; 数据区

;====================================================================

MsgNoActive DB "No active partition.",00H

MsgPartitionTable DB "Invalid partition table.",00H

MsgLoadingOS DB "Error loading operating system.",00H

MsgMissingOS DB "Missing operating system.",00H

;====================================================================

;临时数据

;====================================================================

DriveNumber DB 00H ; 启动磁盘启动器号

ActivePartition DB 00H ; 激活分区表索引(0-3)

DiskExtension DB 00H ; 是否支持磁盘扩展调用

;====================================================================

; 扩展磁盘服务所使用的地址包

;====================================================================

DAP_PACKET_SIZE DB 10H ; 包的大小为16字节

DAP_RESERVED1 DB 00H ; 保留字节

DAP_READ_SECTORS DB 01H ; 要处理的扇区数(1 - 127 )

DAP_RESERVED2 DB 00H ; 保留字节

DAP_BUFFER_OFF DW 7C00H ; 缓冲区偏移

DAP_BUFFER_SEG DW 0000H ; 缓冲区段地址

DAP_SECTOR_LOW DD 0000H ; 起始扇区号的低32位

DAP_SECTOR_HIGH DD 0000H ; 起始扇区号的高32位

;====================================================================

; 填充字节

Padding TIMES 440-($-$$) db 00H

;====================================================================

;====================================================================

; 标志字节

;====================================================================

UniqueMbrSignature DD 4B43414AH

UnknownWord DW 00H

;====================================================================

; 分区表(偏移为446)

;====================================================================

PartitionTable TIMES 64 DB 00H

;====================================================================

; 扇区最后的标记字节(NASM不支持重复ORG)

;====================================================================

BootSignature dw 0AA55H

;====================================================================

; 代码结束

;====================================================================

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有