操作系统(一)引导程序

操作系统(一)引导程序

在自学操作系统的过程中,试图自己实现。参考了一些文献(《30天自制操作系统》、《现代操作系统》等),决定将零散的信息进行一下整理,梳理一下思路。并一点点的开始实现自己的操作系统。我将已经实现的部分上传到了我的GitHub,代码中不足之处还请路过的大神们指点。(希望我能写完)

原理

操作系统的启动过程

具体的信息在计算机是如何启动的——阮一峰博客的文章中记录的非常详细,在这里仅简单列举一下相关内容

  1. BIOS硬件自检
  2. 加载引导程序
    • BIOS首先读取存储设备的第一个扇区(引导扇区),如果这个扇区的最后两个字节是0x55和0xAA则视作可以启动。
    • 将引导扇区的引导程序加载至系统内存的0x7c00位置,执行。
    • 引导程序进行初始化等一系列处理。
  3. 载入系统内核,BIOS引退

FAT12文件系统

在《30天自制操作系统》中,作者使用了一个自制的软件以生成img镜像,实际上就是作者实现的一个简单的FAT12文件系统生成的程序。有关于FAT12文件系统的具体内容可以参考FAT12文件系统

在这里需要了解的包括:
《操作系统(一)引导程序》
由上图可知,在第一个扇区即引导扇区中存储着软盘的相关内容,根目录区(存放着文件名称、大小、修改日期等)开始于第19个扇区(0x2600)。根目录区每个条目的大小为32个字节,所以根目录区的长度为:BPB_RootEntCnt*32(字节)。这样就可以确定出数据区的开始扇区。按默认情况计算开始的地址为(0x8200)。
《操作系统(一)引导程序》
上图为引导扇区中的参数。

按照以上FAT12的原理,我也实现了一个“极简版的FAT12文件生成程序”,内有彩(bug)蛋,详见GitHub ExtUtils/createImg。

BIOS内存分布

在开机时,系统会进入实模式,这个时候系统只用1M空间可以使用。具体分配情况如下:

  • 0x00000—0x003ff中断向量表。
  • 0x00400—0x004ff BIOS数据区。
  • 0x00500—0x9ffff 自由内存区。
  • 0xA0000—0xbffff作为显存使用。
  • 0xc0000—0xc7fff 显卡BIOS。
  • 0xc8000—0xcbfff ide控制器BIOS使用。
  • 0xf0000—0xfffff 系统bios使用。

在开机时,会自动将引导程序加载至0x7c00处。

代码编译

按照常规使用汇编+C作为编写语言。采用nasm和gcc对代码进行编译。首先将代码编译为二进制文件,再写入“软盘”中。
编译指令为:

nasm -f bin filename.s -o filename.bin

BIOS中断

BIOS中断内容较多,可以查阅BIOS中断大全

代码分析

以下代码已上传至GitHub。

    CYLS EQU 10
    ORG     0x7C00          ;起始地址
    JMP     start           ;短转移
    DB      0x90            ;无意义
    DB      "MY OS   "      ; BS_OEMName
    DW      512             ; BPB_BytesPerSec
    DB      1               ; BPB_SecPerClus
    DW      1               ; BPB_ResvdSecCnt
    DB      2               ; BPB_NumFATs
    DW      224             ; BPB_RootEntCnt
    DW      2880            ; BPB_TotSec16
    DB      0xF0            ; BPB_Media
    DW      9               ; BPB_FATSz16
    DW      18              ; BPB_SecPerTrk
    DW      2               ; BPB_NumHeads
    DD      0               ; BPB_HiddSec
    DD      2880            ; BPB_TotSec32
    DB      0,0,0x29        ; BS_DrvNum
    DD      0xffffffff      ; BS_VolID
    DB      "HELLO-OS   "   ; BS_VolLab
    DB      "FAT12   "      ; BS_FileSysType
    RESB    18              ; 无意义

; 以上部分为引导扇区的描述,均按照默认设置。
; 下面开始引导程序

start:
    MOV AX, 0
    MOV SS, AX
    MOV SP, 0x7C00
    MOV DS, AX
   
    MOV AX, 0x0820
    MOV ES, AX
    ; 以上初始化堆栈、数据、附加段寄存器。
    MOV CH, 0   ; 柱面
    MOV DH, 0   ; 磁头
    MOV CL, 2   ; 扇区
; 开始将软盘中的启动程序读入系统内存中
read:
    MOV SI, 0
retry:
    MOV AL, 1
    MOV AH, 0x02
    MOV BX, 0
    MOV DL, 0x00
    INT 0x13
    ; 依次读入每个扇区的内容;若读入失败超过5次,则转至错误处理
    JNC next
    INC SI
    CMP SI, 5
    JAE error
    MOV AH, 0x00
    MOV DL, 0x00
    INT 0x13
    JMP retry
next:
    MOV AX, ES
    ADD AX, 0x0020
    MOV ES, AX
    INC CL
    CMP CL, 18
    JBE read
    MOV CL, 1
    INC DH
    CMP DH, 2
    JB read
    MOV DH, 0
    INC CH
    CMP CH, CYLS ; 共读取CYLS个扇区
    JB read
    
    ;JMP error ;用来判断是否跳出循环

    MOV [0x0FF0], CH
    JMP 0xC200
    ; 转至后续执行程序
    ; 0x7c00 + 0x8000 = 0xc200
    
final:
    HLT
    JMP final

; 显示错误信息
error:
    MOV SI, msg
; 逐字符打印错误信息
print:
    MOV AL, [SI]
    INC SI
    CMP AL, 0
    JE final
    MOV AH, 0x0E
    MOV BX, 15
    INT 0x10
    JMP print

msg:
    DB 0x0a, 0x0a
    DB "load error"
    DB 0x0a
    DB 0

    RESB 510 - ($ - $$) ; 空余补0
    DB 0x55, 0xaa

PS:不用debug调试汇编程序真累心。少写了一条指令检查了一整天。

    原文作者:xinjiyuan97
    原文地址: https://blog.csdn.net/xinjiyuan97/article/details/87832372
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞