<<自己动手写操作系统>>学习笔记(一)---后记
2012-07-02 21:46
537 查看
比划着书,反汇编着NTLDR,大概写一个MBR出来了,但貌似进入了死循环???
我把编译出来的文件写入磁盘MBR中,重启,没反应,各种调试输出没错
很大可能是:MBR读取了MBR再次加载到0x7C00转移控制权?
我明明读取的是分区表的PBR呀?贴代码吧。
bios.inc
fs.inc
mbr.asm
希望有人能帮我解决一下,谢谢。
我把编译出来的文件写入磁盘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:
希望有人能帮我解决一下,谢谢。
相关文章推荐
- <<自己动手写操作系统>>学习笔记(一)---MBR,PBR,BPB,文件系统
- <自己动手写操作系统>第三章——pmtest3源码解析:使用LDT
- <自己动手写操作系统>第三章pmtest7源码解析——检测系统内存
- <自已动手写操作系统>学习扎记之保护模式
- <<orange‘s :一个操作系统的实现>>读书笔记(2) 保护模式
- <自己动手写操作系统>2011032901
- 自己动手写的Web服务器<一>
- 自己动手,实现一种类似List<T>的数据结构(二)
- <仅是自己做笔记。。。系列-13>输入两个整数 n 和 m,从数列1,2,3.......n 中 随意取几个数, 使其和等于 m ,要求将其中所有的可能组合列出来.
- <仅是自己做笔记。。。系列-9>在一个字符串中找到第一个只出现一次的字符。
- <转>看过小马哥的成就,你们谁敢说自己做过项目?
- <仅是自己做笔记。。。系列-14>输入两个整数序列。其中一个序列表示栈的push顺序, 判断另一个序列有没有可能是对应的pop顺序。
- <自己动手写操作系统>2011032201
- <自己动手写操作系统>2011042901
- 关于<自己动手写操作系统>开发环境的安装
- <自己动手写操作系统>2011033101
- <操作系统>进程与线程的有趣理解
- <自己动手写操作系统>2011033002
- MFC中的 Document / View 结构的使用 <转载+自己总结,MFC中的MVC>
- <仅是自己做笔记。。。系列-11>输入n,用最快的方法求Fibonacci数列的第n项。