《30天自制操作系统》笔记(02)——导入C语言

上一篇,记录了计算机开机时加载IPL程序(initial program loader,一个nas汇编程序)的情况,包括IPL代码(helloos.nas)、编译生成helloos.img文件、用虚拟机QEMU加载helloos.img、制作U盘启动盘和用物理机加载helloos.img。

计算机启动时会自动加载和执行IPL程序,但IPL程序只能占用512字节。若直接用IPL写OS,空间不够用。所以IPL程序一般用于将真正的OS程序加载到内存某处(记作A),然后跳转到A。这样计算机就可以执行OS的程序了。

在上一篇中的IPL程序只是个hello world式的试验品,本篇通过修改上一篇的IPL,让它真正实现加载OS程序的功能。同时,将IPL程序代码和OS代码放到不同的源代码文件中;用C语言来编写以后的OS代码;用Makefile来编译源代码。

有了本篇的基础,就算是正式开始编写OS源代码了

OS开发设计方案

关于软盘的预备知识

一张软盘有80个柱面、2个磁头、18个扇区(Cylinder:0~79;Header:0~2;Sector:1~18),1个扇区有512个字节,所以软盘的容量是80*2*18*512=1440KB。

向一个软盘保存文件时,文件名会从0x2600开始往后存,文件的内容会从0x4200开始往后存。

我们的OS开发设计方案如下

1. 把IPL程序作为一个独立的源文件(ipl10.nas)开发,编译后生成二进制文件(ipl10.bin)。

2. 把OS程序作为若干独立的源文件开发,编译后生成二进制文件(haribote.sys)。haribote.sys就是我们的OS程序。

3. 用二进制的方式把ipl10.bin写入haribote.img(磁盘映像文件,看作一个软盘即可)的第一个扇区(这样,计算机启动时就会自动加载ipl10.bin程序)。

4. 把haribote.sys作为一个文件复制到haribote.img。根据上文的预备知识可知,这个文件的内容会从软盘的0x4200位置开始往后存。

实现一个开发结构完整的OS

完备的IPL程序

下面的代码是完备的IPL程序,它读了10个柱面上的代码到内存,所以文件名从helloos.nas改成了ipl10.nas。

  1 ; haribote-ipl
  2 ; TAB=4
  3 
  4 CYLS    EQU        10                ; どこまで読み込むか
  5 
  6         ORG        0x7c00            ; 指明程序的装载地址
  7 
  8 ; 以下这段是标准FAT32格式软盘专用的代码
  9 
 10         JMP        entry
 11         DB        0x90
 12         DB        "HARIBOTE"        ; freeparam 启动区的名称可以是任意的字符串(8字节)
 13         DW        512                ; 每个扇区(sector)的大小(必须为512字节)
 14         DB        1                ; 簇(cluster)的大小(必须为1个扇区)
 15         DW        1                ; FAT的起始位置(一般从第一个扇区开始)
 16         DB        2                ; FAT的个数(必须为2)
 17         DW        224                ; 根目录的大小(一般设成224项)
 18         DW        2880            ; 该磁盘的大小(必须是2880扇区)
 19         DB        0xf0            ; 磁盘的种类(必须是0xf0)
 20         DW        9                ; FAT的长度(必须是9扇区)
 21         DW        18                ; 1个磁道(track)有几个扇区(必须是18)
 22         DW        2                ; 磁头数(必须是2)
 23         DD        0                ; 不使用分区,必须是0
 24         DD        2880            ; 重写一次磁盘大小
 25         DB        0,0,0x29        ; 意义不明,固定
 26         DD        0xffffffff        ; (可能是)卷标号码
 27         DB        "HARIBOTEOS "    ; freeparam 磁盘的名称(11字节)
 28         DB        "FAT12   "        ; 磁盘格式名称(8字节)
 29         RESB    18                ; 先空出18字节
 30 
 31 ; 程序核心
 32 
 33 entry:
 34         MOV        AX,0            ; 初始化寄存器
 35         MOV        SS,AX
 36         MOV        SP,0x7c00
 37         MOV        DS,AX
 38 
 39 ; 读磁盘
 40 
 41         MOV        AX,0x0820
 42         MOV        ES,AX
 43         MOV        CH,0            ; 柱面0
 44         MOV        DH,0            ; 磁头0
 45         MOV        CL,2            ; 扇区2
 46 readloop:
 47         MOV        SI,0            ; 记录失败次数的寄存器
 48 retry:
 49         MOV        AH,0x02            ; AH=0x02 : 读入磁盘
 50         MOV        AL,1            ; 1个扇区
 51         MOV        BX,0
 52         MOV        DL,0x00            ; A驱动器
 53         INT        0x13            ; 调用磁盘BIOS
 54         JNC        next            ; 没出错时跳转到next
 55         ADD        SI,1            ; SI加1
 56         CMP        SI,5            ; 比较SI与5
 57         JAE        error            ; SI >= 5时,跳转到 error
 58         MOV        AH,0x00
 59         MOV        DL,0x00            ; A驱动器
 60         INT        0x13            ; 重置驱动器
 61         JMP        retry
 62 next:
 63         MOV        AX,ES            ; 把内存地址后移0x200(0x200 = 512)
 64         ADD        AX,0x0020        ; ADD    AX, 512 / 16
 65         MOV        ES,AX            ; 因为没有ADD ES,0x020 指令,所以这里稍微绕个弯
 66         ADD        CL,1            ; CL加1
 67         CMP        CL,18            ; 比较CL与18
 68         JBE        readloop        ; 如果CL <= 18,则跳转到readloop
 69         MOV        CL,1
 70         ADD        DH,1
 71         CMP        DH,2
 72         JB        readloop        ; 如果DH < 2,则跳转到readloop
 73         MOV        DH,0
 74         ADD        CH,1
 75         CMP        CH,CYLS
 76         JB        readloop        ; 如果CH < CYLS,则跳转到readloop
 77 
 78 ; 读完所有数据后,调到0x8200位置,即haribote.sys中的指令
 79 
 80         MOV        [0x0ff0],CH        ; 将CYLS的值写到内存地址0x0ff0中。
 81         JMP        0xc200
 82 
 83 error:
 84         MOV        SI,msg
 85 putloop:
 86         MOV        AL,[SI]
 87         ADD        SI,1            ; 给SI加1
 88         CMP        AL,0
 89         JE        fin
 90         MOV        AH,0x0e            ; 显示一个文字
 91         MOV        BX,15            ; 指定字符颜色
 92         INT        0x10            ; 调用显卡BIOS
 93         JMP        putloop
 94 fin:
 95         HLT                        ; 让CPU停止;等待指令
 96         JMP        fin                ; 无限循环
 97 msg:
 98         DB        0x0a, 0x0a        ; 换行2次
 99         DB        "load error"    ; freeparam
100         DB        0x0a            ; 换行
101         DB        0
102 
103         RESB    0x7dfe-$        ; 填写0x00,直到0x001fe
104 
105         DB        0x55, 0xaa
ipl10.nas

 

相关文章:

  • 2021-10-11
  • 2021-08-16
  • 2021-09-22
  • 2021-05-21
  • 2021-05-28
  • 2021-04-14
  • 2022-03-05
猜你喜欢
  • 2022-12-23
  • 2022-12-23
  • 2021-06-24
  • 2021-08-03
  • 2021-11-15
  • 2021-04-16
  • 2021-04-20
相关资源
相似解决方案