使用FASM汇编器,代码如下:
include 'bios.inc'
include 'fs.inc'
MASTER_BOOT_RECORD_BASE = 0x7C00
MASTER_BOOT_RECORD_NEW_BASE = 0x0600
use16
ORG MASTER_BOOT_RECORD_BASE
Main:;入口,初始化,移动代码,转移控制权
;初始化段寄存器
xor ax, ax
mov ss, ax
mov es, ax
mov ds, ax
;初始化堆栈
mov sp, MASTER_BOOT_RECORD_BASE
;移动代码,转移控制权
mov si, MbrEntry
mov di, (MASTER_BOOT_RECORD_NEW_BASE + MbrEntry - $$)
push ax
push di
mov cx, (MbrEnd - MbrEntry)
rep movsb
retf;ax:di
;Main结束
MbrEntry:
sti
mov bp, (MASTER_BOOT_RECORD_NEW_BASE + par1 - $$)
mov cx, 4
.Loop_FindActivePartition:
cmp [bp + STRUCT_PARTITION_TABLE.State], 0
jl .ToLoadPbr
jne .InvalidMbr
add bp, sizeof.STRUCT_PARTITION_TABLE
loop .Loop_FindActivePartition
;从下一设备启动
int BIOS_BOOT_FROM_NEXT_DEVICE
.InvalidMbr:
mov bp, (MASTER_BOOT_RECORD_NEW_BASE + szMbrError - $$)
mov cx, 31
call DisplayMessage
jmp $
.ToLoadPbr:;bp=分区表地址
call LoadPbr
jb .LoadPbrFail
cmp word [flag], FLAG_BOOT_RECORD
jne .PbrError
push ax;ax=0
push MASTER_BOOT_RECORD_BASE
retf;转移控制权到PBR
.LoadPbrFail:
mov bp, (MASTER_BOOT_RECORD_NEW_BASE + szLoadPbrFail - $$)
mov cx, 33
call DisplayMessage
jmp $
.PbrError:
mov bp, (MASTER_BOOT_RECORD_NEW_BASE + szPbrError - $$)
mov cx, 30
call DisplayMessage
jmp $
;MbrEntry结束
LoadPbr:;bp=分区表地址
mov di, 5;尝试5次ReadPBR
mov dl, [bp + STRUCT_PARTITION_TABLE.State]
mov ah, BIOS_DDS_READ_DEVICE_PARAMETER
int BIOS_DIRECT_DISK_SERVICE
jb .ReadPBR;失败,尝试直接读取PBR
mov al, cl;AX=0
and al, 00111111B;取低6位
cbw;把AL的符号扩展到AH
mov bl, dh;磁头数
mov bh, ah;AH=0
inc bx;得出总磁头数
mul bx;扇区*磁头=ax*bx,结果=dx:ax
mov dx, cx
xchg dh, dl
shr dh, 6;取高2位
inc dx
;总的扇区数*总的磁头数*总的柱面数=磁盘容量
mul dx
cmp [bp + STRUCT_PARTITION_TABLE.InfoAreaSectors_H], dx
ja .ReadPBREx;无符号比较,大于则跳
jb .ReadPBR;无符号比较,小于则跳
cmp [bp + STRUCT_PARTITION_TABLE.InfoAreaSectors_L], ax
jnb .ReadPBREx;无符号比较,大于等于则跳
.ReadPBR:
mov ah, BIOS_DDS_READ_SECTOR
mov al, 1
mov bx, MASTER_BOOT_RECORD_BASE
mov cx, [bp + STRUCT_PARTITION_TABLE.BeginSC]
xor dx, dx
mov dl, [bp + STRUCT_PARTITION_TABLE.State];dx=FS_ACTIVE=0x80=代表硬盘
int BIOS_DIRECT_DISK_SERVICE
jnb .Ret;成功
dec di
je .Ret;尝试了5次,直接返回
;复位驱动器,继续尝试
xor ah, ah
mov dl, [bp + STRUCT_PARTITION_TABLE.State]
int BIOS_DIRECT_DISK_SERVICE
jmp .ReadPBR
.ReadPBREx:
mov dl, [bp + STRUCT_PARTITION_TABLE.State]
pusha
mov bx, 0x55AA;为什么倒过来了?
mov ah, BIOS_DDS_CHECK_EXTENSION
int BIOS_DIRECT_DISK_SERVICE
jb .Failure;不支持
;继续检查
cmp bx, FLAG_BOOT_RECORD
jne .Failure
test cl, 1;其他资料没有这个,什么意思?
je .Failure
popa
.Loop_ReadPBREx:
pusha
;使用扩展直接磁盘服务读取
;填充数据包.由于转移了代码,所以要修正数据包地址
mov si, MASTER_BOOT_RECORD_NEW_BASE + Pack_Extend - MASTER_BOOT_RECORD_BASE
mov [si + STRUCT_DDS_EXTENSION_PACK.BufferOffset], MASTER_BOOT_RECORD_BASE
mov [si + STRUCT_DDS_EXTENSION_PACK.BufferSegment], 0
push ax
mov ax, [bp + STRUCT_PARTITION_TABLE.InfoAreaSectors_L]
mov [si + STRUCT_DDS_EXTENSION_PACK.SC_L], ax
mov ax, [bp + STRUCT_PARTITION_TABLE.InfoAreaSectors_H]
mov [si + STRUCT_DDS_EXTENSION_PACK.SC_H], ax
pop ax
mov ah, BIOS_DDS_EXTENSION_READ
int BIOS_DIRECT_DISK_SERVICE
popa
dec di
je .Ret;尝试了5次,直接返回
;复位,继续尝试
xor ah, ah
mov dl, [bp + STRUCT_PARTITION_TABLE.State]
int BIOS_DIRECT_DISK_SERVICE
jmp .Loop_ReadPBREx
.Failure:
popa
stc;设置CF=1
.Ret:
retn
;LoadPBR结束
DisplayMessage:
mov ax, 0x1301
mov bx, 0xC
xor dl, dl
int 0x10
ret
;DisplayMessage结束
szMbrError db "Invalid Master Partition Table."
szLoadPbrFail db "Can't Load Partition Boot Record."
szPbrError db "Invalid Partition Boot Record."
Pack_Extend STRUCT_DDS_EXTENSION_PACK 0x10, 0, 1, 0xFF, 0xFF, 0xFF, 0xFF, 0
CodeEnd:;代码结束,四个分区表结构+结束标志
times sizeof.STRUCT_MASTER_BOOT_RECORD.Codes - ($-$$) db 0
par1 STRUCT_PARTITION_TABLE 0x80, 0x01, 0x0001, 0x07, 0xFE, 0xBFBF, 0x003F, 0, 0x00AC9281
par2 STRUCT_PARTITION_TABLE
par3 STRUCT_PARTITION_TABLE
par4 STRUCT_PARTITION_TABLE
flag dw FLAG_BOOT_RECORD
MbrEnd:
其余的代码在我的博客上
http://blog.csdn.net/sidyhe/article/details/7709903
这里有一个问题希望得到解答。
代码当中的分区表是我虚拟机里面的,当我编译出来的时候写到磁盘的MBR后重启,没有反应,或许是MBR读取了MBR再次加载到0x7C00转移控制权?
同样也看不到任何输出,求解。
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!