基于fat32的引导扇区 今年二月份的时候开始就打算自己动手写一个操作系统,也看了很多书,但是最近才真正有机会开始实践,以下是引导扇区代码,没啥好说的,做起来也很简单 首先是要用Winimage去建一个ima镜像(我不知道那个img为啥不行,每次读img然后软件就崩了),自定义大小,不要软盘不要软盘不要软盘,网上很多很多很多的资料都是用软盘,可恨呐!本来就是想要写一个真的能够用的东西放在U盘里面所以,用fat32吧,其实一开始我甚至都打算弄ntfs的,引导区代码都写了,但是后面的sys文件什么的搞不定甚至我对其结构的资料都找不到。。。没办法了,fat32就fat32吧,反正一般U盘都fat32。 好吧不废话了,代码部分的内容是首先fat32的bpb和ebpb,然后设置好段寄存器,然后检测是否有int13h的扩展功能,有的话,用扩展功能读磁盘5个扇区(DAP什么的自己查吧),没有就int13h正常的那点功能吧(但我不保证这部分代码对,因为我的测试是有扩展的),当然为了知道已经读完了,一些显示信息是必要的对吧。 然后说说我内存和磁盘的管理,在fat32里保留扇区里面有两个备份,一个备份通常有6个扇区——fat头里面LocaOfBackupSec(location of back up sector)的那个Word决定的,当然,貌似通常都是这样的(至于fat头文件里面的其他东西我接下来几篇博客会讲讲看hhh,或者也可以参考别的文档,一般能看到我这篇博客的都是想做这些事情的,这点总会知道的),第一个扇区(0扇区)是引导扇区,所以剩下我们有5个可以用来做些别的事情(所以要读5个),然后参考开机内存布局分布,大概500h-7c00h能用,然后7c00h开始的一个扇区是最开始装载的东西,然后之后到9Fc00h都是可用内存,但是考虑到500h之后几个字节貌似bios有用来做一些啥,我干脆从600h开始装5个扇区到1000h,之后放真正的kernel(应该一开始initialize吧,不管了再说吧) 所以这段代码就主要是读5个扇区到600h-1000h 然后跳到那个地方执行 代码就酱,实测能用,然后是用nasm生成bin文件,用010editor把二进制文件写进ima镜像就好 然后是bochs(当然这个镜像你们也可以用bochs带的那个img镜像工具生成,至于文件写不写的进去我就不管了反正我弄不开)bochs其实功能比较多,但是如果不懂得话,只要去官网上面找一个能用的镜像,然后把里面的bxrc文件改改,设置好内存,路径,以及ata0的参数就差不多了吧
;以下是引导扇区代码,版权归属浙江大学朱懿同学,3150101706 BITS 16 SECTION .TEXT org 7C00h jmp short BOOT_START nop OEMname db ‘ZJUZHUYI’ ;———————— ;BPB,refered to wikipedia ;———————— BytePerSec dw 0200h ;每个扇区的字节数 SectorsPerCluster db 01h ;每个簇的扇区数 ReservedSectors dw 26h ;保留扇区数,一般为0 NumofFATs db 2 ; RootDirEntries dw 0 ; TotalLogicalSec dw 0 ;未使用,00 MediaID db 0xF8 ;介质描述符,硬盘为0xF8 LogicalSecPerFAT dw 0 ;总是为零 ;————————- ;above is dos2.0BPB,total 13 bytes ;————————- SectorsPerTrack dw 0x20 ;每磁道扇区数 NumOfHeads dw 0x40 ;每个柱面磁头数 HidenSectors dd 0 ; LargeTotalLogicalSec dd 0x0FFF7 ; ;————————- ;above is dos3.31BPB,total 25 bytes(13+12) ;————————- LogSecPerFAT dd 0x01F8 ;每个fat的逻辑扇区 MirrorFlagETC dw 0 ; Version dw 0 ; RootDirectoryClu dd 2 ; LocaOfFSInfoSec dw 1 ; LocaOfBackupSec dw 6 ; times 12 db 0 ;reserved DriverNum db 0x80 ; FlagsETC db 0 ; ExtBootSign db 0x29 ; VolSerNum dd 0 ; times 11 db 0 ;Volum label FileSystemType db ‘FAT32 ’ ;貌似必须是这样 ;————————- ;above is FAT32 BPB,total 79 bytes(25+54) ;when you copy binary code using 010editor or other software ;please copy from 0x5A ;then is the boot start ;————————- BOOT_START: cli xor ax,ax mov ds,ax mov es,ax mov sp,0x0600 sti ;———–初始化 cmp word [RootDirEntries],0 jnz diskerr cmp word [LogicalSecPerFAT],0 jnz diskerr cmp dword [LogSecPerFAT],0 jz diskerr ;————- mov byte [DriverNum],dl ;dl表示启动的磁盘编号(驱动器号?)在扩展int13h中有用处 mov si,MsgBooting call ShowMassage mov ah,41h mov bx,055aah int 13h ;扩展int13h,可以用来读取硬盘 jc StartReadDisk mov al,01h mov byte [BiosExtendSup],al jmp StartReadDisk ;———————— ;———————— DAP: DAP_PacketSize db 10h DAP_Reserved db 0 DAP_BlockCount dw 0 DAP_BufferOffset dw 0 ;缓冲区段的段地址和偏移 DAP_BufferSeg dw 0 DAP_BlockNumLow dd 0 ;起始扇区的高地址和低地址 DAP_BlockNumHigh dd 0 Others1: BiosExtendSup db 0 ;————打印的一些信息 MsgBooting db ‘Booting’,0Dh,0Ah,00 BootSucc db ‘BootSuccess’,0Dh,0Ah,00 FailRead db ‘ReadFail’,0Dh,0Ah,00 JmpFail db ‘JmpFail’,0Dh,0Ah,00 Restart db ‘Press any key to restart’,0Dh,0Ah,00 Extend db ‘Extend’,0Dh,0Ah,00 NoExtend db ‘NoExtend’,0Dh,0Ah,00 DiskErr db ‘DiskError’,0Dh,0Ah,00 ;test1 db ‘1’,0Dh,0Ah,00 ;用于觉得有怀疑的地方的测试 ;test2 db ‘2’,0Dh,0Ah,00 ;test3 db ‘3’,0Dh,0Ah,00 ;————–以上是DAP(DiskAddressPacket)用于int13h扩展功能,每次读写要重新设定哦 StartReadDisk: pusha mov word [DAP_BlockCount],05h ;需要读5个扇区 mov word [DAP_BufferSeg],0000h mov word [DAP_BufferOffset],0600h mov dword [DAP_BlockNumLow],01h mov ax,word [BiosExtendSup] cmp ax,0 jz LoadNoExtend mov si,Extend call ShowMassage ;———–有扩展的时候 mov ah,42h mov dl,byte[DriverNum] mov si,DAP_PacketSize int 13h jc ReadFail jmp Finish_Boot ;———–没有扩展的时候 ;———–详细参考int13h的2号功能参数和LBA跟CHS的关系 LoadNoExtend: mov si,NoExtend call ShowMassage mov ax,0000h mov es,ax mov ax,word [DAP_BlockNumLow] mov dx,word [DAP_BlockNumLow+2] div word [SectorsPerTrack] mov cx,dx inc cx and cl,3Fh ;后六位为扇区号,所以要和3Fh(00111111b)and xor dx,dx div word [NumOfHeads] mov ch,al shl ah,6 ;柱面号高二位然后or运算得到cl or cl,ah mov dh,dl mov dl,byte [DriverNum] mov al,5 mov ah,02h mov bx,0600h int 13h jc ReadFail jmp Finish_Boot ;———— Finish_Boot: popa mov si,BootSucc call ShowMassage mov cl,byte [DriverNum] mov dl,byte [BiosExtendSup] db 0EAh dd 00000600h xor ax,ax mov ds,ax mov si,JmpFail call ShowMassage mov si,Restart call ShowMassage call restart ;————打印函数 ShowMassage: cld lodsb cmp al,00h jz Msgend mov ah,0Eh mov bl,07h ;白底黑字 int 10h jmp ShowMassage Msgend: ret ;————disk error diskerr: mov si,DiskErr call ShowMassage call restart ;————readfail ReadFail: mov si,FailRead call ShowMassage mov si,Restart call ShowMassage call restart ;———————— restart: mov ah,00h int 16h db 0EAh dd 0FFFF0000h ;———————— ;此处需要考虑字节数的,一开始用掉了79+8+3=90byte ;还剩下510-90=420byte,一条指令最少也要2字节,所以最多210条指令哦 ;考虑到有的长指令还有3byte什么的,还是不要超过150行最好 ;———————— times 510-( − <script type="math/tex" id="MathJax-Element-3">-</script>$) db 0 dw 0xaa55 ; 引导扇区结束