学操作系统是枯燥的,所以需要一些成果来调剂一下,今天就来写一个引导区吧。由于书上是用软盘启动(或虚拟硬盘),所以先准备一个空的虚拟软盘映像吧,这个网上教程很多就不细说了。注:软盘用FAT12格式1.44M的。

    要写一个从软盘引导的程序就首先要知道软盘的组织结构,

;引导扇区格式
;-----------------------------------------------------------------------------------
;start length 内容         
;0 3 一个短跳转指令          jmp LABEL_START nop
;3 8 厂商名         '********'(任意8字节)
;11 2 每扇区字节数         0x200
;13 1 每簇扇区数         0x01
;14 2 Boot记录占用多少扇区          0x0001                     -------BPB_TecSec16
;16 1 共有多少FAT表          0x02
;17 2 根目录文件数最大值         0xe0
;19 2 扇区总数         0xB40
;21 1 介质描述符         0xf0
;22 2 每FAT扇区数          0x09
;24 2 每磁道扇区数          0x12
;26 2 磁头数(面数)          0x02
;28 4 隐藏扇区数 0
;32 4 若BPB_TecSec16=0,记录扇区数 0
;36 1 中断13的驱动器号          0
;37 1 表使用 0
;38 1 扩展引导标记(29h) 0x29
;39 4 卷序列号          0
;43 11 卷标          '***********'(任意11字节)
;54 8 文件系统类型          'FAT12   '(8字节)
;62 448 引导代码          引导代码
;510 2 510:0x55  511:0xaa          0xaa55

;----------------------------------------------------------------------------------

注:最后两字节的结束标志必不可少(少了它计算机将不能将它识别为引导区),事实上FAT12磁盘头可以没有,但这样系统将无法正常访问软盘映像。

    那么接下来就开始写引导代码吧

        ORG 0x7c00

        jmp short LABEL_START ; Start to boot.

nop                 ; 这个 nop 不可少

; 下面是 FAT12 磁盘的头
BS_OEMName         DB 'aby-tec '             ; OEM String, 必须 8 个字节
BPB_BytsPerSec DW 512     ; 每扇区字节数
BPB_SecPerClus DB 1     ; 每簇多少扇区
BPB_RsvdSecCnt DW 1     ; Boot 记录占用多少扇区
BPB_NumFATs DB 2             ; 共有多少 FAT 表
BPB_RootEntCnt DW 224     ; 根目录文件数最大值
BPB_TotSec16         DW 2880     ; 逻辑扇区总数
BPB_Media         DB 0xF0     ; 媒体描述符
BPB_FATSz16     DW 9     ; 每FAT扇区数
BPB_SecPerTrk DW 18     ; 每磁道扇区数
BPB_NumHeads DW 2     ; 磁头数(面数)
BPB_HiddSec     DD 0     ; 隐藏扇区数
BPB_TotSec32         DD 0             ; 如果 wTotalSectorCount 是 0 由这个值记录扇区数
BS_DrvNum         DB 0          ; 中断 13 的驱动器号
BS_Reserved1     DB 0     ; 未使用
BS_BootSig         DB 29h     ; 扩展引导标记 (29h)
BS_VolID             DD 0     ; 卷序列号
BS_VolLab         DB 'aby-tec    '    ; 卷标, 必须 11 个字节
BS_FileSysType DB 'FAT12   '     ; 文件系统类型, 必须 8个字节  


LABEL_START:
    mov ax, cs
    mov ds, ax
    mov es, ax
    Call DispStr                                ; 调用显示字符串例程
    jmp $                                       ; 无限循环
DispStr:
    mov ax, bootMessage
    mov bp, ax                               ; ES:BP = 串地址
    mov cx, bootMassageEnd-bootMassage     ; CX = 串长度
    mov ax, 01301h                               ; AH = 13,  AL = 01h,准备后面的10号中断调用
    mov bx, 000ch                                       ; 页号为0(BH = 0) 黑底红字(BL = 0Ch,高亮)

    mov dl, 0

    int 10h                                       ; 调用10号中断

            ret                                                                                  

bootMessage:

            db "Hello, aby-tec!"                                    ;显示内容

bootMassageEnd:

            db        0x0a                                                      ;换行,bootMassage的结束标志

            times  510-($-$$) db 0                       ; 填充剩下的空间,使生成的二进制代码恰好为512字节
            dw  0xaa55                               ; 结束标志


                                                                                      ;10中断ah=13 显示字符串

                                                                                  ;ES:BP = 串地址 
                                                                                  ;CX = 串长度 
                                                                                  ;DH, DL = 起始行列 
                                                                                  ;BH = 页号
                                                                                  ;AL = 0,BL = 属性 -光标返回起始位置  串:Char,char,……,char
                                                                                  ;AL = 1,BL = 属性 -光标跟随移动         串:Char,char,……,char
                                                                                  ;AL = 2  -------------光标返回起始位置  串:Char,attr,……,char,attr 
                                                                                  ;AL = 3  -------------光标跟随串移动     串:Char,attr,……,char,attr


    一般在引导区都会将加载器读到内存之中,并将cpu控制权交给加载器,不过现在只是测试就不管那么多了。

接下来就来测试一下吧。

写好代码保存为boot.asm;打开cmd转到工作目录下;使用nasm编译boot.asm:nasm boot.asm -o boot.bin;

用winimage制作一个空的软盘映像abytec.img(用winimage制作的软盘映像后缀为.ima改为.img即可);

用FloppyWriter将boot.bin写入abytec.img;在vBox新建一个虚拟机,并在虚拟机上添加软盘控制器,然后添加虚拟软盘abytec.img;

实验一之引导_第1张图片

实验一之引导_第2张图片

可以看到它成功显示了"Hello, aby-tec!"。软盘启动就到这里,之后再讲虚拟硬盘启动。

转载自:

https://blog.csdn.net/lingxufire/article/details/79934856