首 页 | 新 闻 | 技术中心 | 第二书店 | 《程序员》 | 《开发高手》 | 社 区 | 黄 页 | 人 才
移 动专 题SUNIBM微 软微 创精 华Donews人 邮
我的技术中心 
我的分类 我的文档
全部文章 发表文章
专栏管理 使用说明



 RSS 订阅 
最新文档列表
Windows/.NET
.NET  (rss)    
Visual C++  (rss)    
Delphi  (rss)    
Visual Basic  (rss)    
ASP  (rss)    
JavaScript  (rss)    
Java/Linux
Java  (rss)    
Perl  (rss)    
综合
其他开发语言  (rss)    
文件格式  (rss)    
企业开发
游戏开发  (rss)    
网站制作技术  (rss)    
数据库
数据库开发  (rss)    
软件工程
其他  (rss)    

积极原创作者 
Kendiv (115)
iiprogram (92)
Purpleendurer (137)
nizhigang2000 (13)
btbtd (85)
wfdmd (27)
yjz0065 (121)
lzmtw (31)
feng_sundy (165)
whoopee (60)
CSDN - 文档中心 - 其他开发语言 阅读:302   评论: 1    参与评论
标题   主引导扇区代码(MBR)     选择自 jackjoy 的 Blog
关键字   主引导扇区代码(MBR)
出处  

;====================================================================
;
; 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


;====================================================================
; 代码结束
;====================================================================

  
 
 


相关文章
对该文的评论
csdnlanser ( 2005-10-22)
好贴