<<自己动手写操作系统>>学习笔记(一)---后记

比划着书,反汇编着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:


希望有人能帮我解决一下,谢谢。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值