比划着书,反汇编着NTLDR,大概写一个MBR出来了,但貌似进入了死循环???
我把编译出来的文件写入磁盘MBR中,重启,没反应,各种调试输出没错
很大可能是:MBR读取了MBR再次加载到0x7C00转移控制权?
我明明读取的是分区表的PBR呀?贴代码吧。
bios.inc
include 'macro/struct.inc'
;BIOS服务中断定义
;从下一设备启动
BIOS_BOOT_FROM_NEXT_DEVICE = 0x18
;直接磁盘服务,功能号=AH,下面列出
BIOS_DIRECT_DISK_SERVICE = 0x13
;复位驱动器
BIOS_DDS_RESET_DEVICE = 0x00
;读取驱动器参数
;成功返回值:DH=磁头,DL=驱动器数,CL低6位=扇区
BIOS_DDS_READ_DEVICE_PARAMETER = 0x08
;读扇区
;参数:AL=扇区数,CH=柱面,CL=扇区,DH=磁头
;DL=驱动器,00H~7FH:软盘;80H~0FFH:硬盘
;ES:BX=缓冲区的地址
BIOS_DDS_READ_SECTOR = 0x02
;检测扩展DDS是否存在
;参数:DL=驱动器,0x80=第一块硬盘,0x81=第二块硬盘......
BIOS_DDS_CHECK_EXTENSION = 0x41
;扩展直接硬盘读写数据包结构
struct STRUCT_DDS_EXTENSION_PACK
;大小必须=0x10
Size db ?
;保留
Resvered1 db ?
;数据块数量
BlockCount dw ?
;缓冲区段偏移
BufferOffset dw ?
;缓冲区段值
BufferSegment dw ?
;要读的数据,扇区(低6位)和柱面(高10位)
SC_L dw ?
SC_H dw ?
;未知=0
Unknown1 dd ?
ends
BIOS_DDS_EXTENSION_READ = 0x42
BIOS_DDS_EXTENSION_WRITE = 0x43
fs.inc
include 'macro/struct.inc'
;文件系统定义
FSID_FAT12 = 0x01
FSID_FAT16 = 0x04
FSID_FAT16_2 = 0x06
FSID_FAT16_3 = 0x0E
FSID_FAT32 = 0x0B
FSID_FAT32_2 = 0x0C
FSID_NTFS = 0x07
FSID_HPFS = FSID_NTFS
FSID_EXTENDED = 0x05
FS_ACTIVE = 0x80
;分区表结构=16字节
struct STRUCT_PARTITION_TABLE
;分区状态,0=未激活,0x80=激活
State db ?
;起始磁头号
BeginHead db ?
;起始扇区(低6位)和柱面号(高10位)
BeginSC dw ?
;分区类型
FSID db ?
;结束磁头号
EndHead db ?
;结束扇区和柱面号,同BeginHead
EndSC dw ?
;相对扇区地址,低16+高16=32位
InfoAreaSectors_L dw ?
InfoAreaSectors_H dw ?
;总扇区数
Sectors dd ?
ends
FLAG_BOOT_RECORD = 0xAA55
;主引导记录,512字节
struct STRUCT_MASTER_BOOT_RECORD
Codes rb 446
Partition1 STRUCT_PARTITION_TABLE
Partition2 STRUCT_PARTITION_TABLE
Partition3 STRUCT_PARTITION_TABLE
Partition4 STRUCT_PARTITION_TABLE
;结束标志=0x55AA
Flag dw ?
ends
;FAT磁盘参数表,25字节,FAT12和FAT16应该是一样的
struct STRUCT_BIOS_PARAMETER_BLOCK_FAT
;每扇区字节数
BytsPerSec dw ?
;每簇扇区数
SecPerClus db ?
;Boot记录占用多少扇区
RsvdSecCnt dw ?
;共有多少FAT表
NumFATs db ?
;根目录文件数最大值
RootEntCnt dw ?
;扇区总数
TotSec16 dw ?
;介质描述符
Media db ?
;每FAT扇区数
FATSz16 dw ?
;每磁道扇区数
SecPerTrk dw ?
;磁头数(面数)
NumHeads dw ?
;隐藏扇区数
HiddSec dd ?
;如果TotSec16=0则由这个记录扇区数
TotSec32 dd ?
ends
;分区引导记录=512字节
struct STRUCT_PARTITION_BOOT_RECORD
;短跳转代码
CodeJmp rb 3
;厂商名(字符串)
OEMName rb 8
;BIOS_PARAMETER_BLOCK
BPB STRUCT_BIOS_PARAMETER_BLOCK_FAT
;中断13的驱动器号
DrvNum db ?
;磁头号(书上说这一字节是保留的)
Head db ?
;扩展引导标记=0x29
BootSig db ?
;卷序列号
VolID dd ?
;卷标(字符串)
VolLab rb 11
;文件系统类型(字符串)
FileSysType rb 8
;代码,数据等
Others rb 448
;标志=0x55AA
Flag dw ?
ends
;根目录结构,32字节
struct STRUCT_ROOT_DIRECTORY_FAT
;文件名8字节,扩展名3字节
Name rb 11
;文件属性
Attr db ?
;保留
Reserved1 rb 10
;最后写入时间
WrtTime dw ?
;最后写入日期
WrtDate dw ?
;开始簇号
FstClus dw ?
;文件大小
FileSize dd ?
ends
mbr.asm
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:
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:
希望有人能帮我解决一下,谢谢。