一、内存分布图
二、启动区汇编代码
这段代码是启动区代码,启动区的代码会保存到0x7c00至0x7dff(ORG 0x7c00),0x7c00之前的区域存放着BIOS程序或让BIOS程序用来实现各种功能,0x7e00到0x7fff为止的区域保留,并将启动区代码拷贝到0x8000到0x81ff(没从代码上看到,怎么做到的?)。
以下这段启动区代码将从0柱面、0磁头、2扇区开始的10个柱面、2个磁头、18个扇区的内容读入到内存的0x8200之后的位置(MOV AX,0x0820)
1 00000000 ; haribote-ipl
2 00000000 ; TAB=4
3 00000000
4 = 0000000A CYLS EQU 10 ; 声明常量
5 00000000
6 ORG 0x7c00 ; 指明程序的装载地址
7 00007C00
8 00007C00 ; 以下这段是标准FAT12格式软盘专用的代码
9 00007C00
10 00007C00 EB 4E JMP entry ; 跳转到entry
11 00007C02 90 DB 0x90
12 00007C03 48 41 52 49 42 4F 54 45 DB "HARIBOTE" ; 启动区的名称可以是任意的字符串(8字节)
13 00007C0B 0200 DW 512 ; 每个扇区的大小
14 00007C0D 01 DB 1 ; 簇的大小
15 00007C0E 0001 DW 1 ; FAT的起始位置
16 00007C10 02 DB 2 ; FAT的个数
17 00007C11 00E0 DW 224 ; 根目录的大小
18 00007C13 0B40 DW 2880 ; 该磁盘的大小
19 00007C15 F0 DB 0xf0 ; 磁盘的种类
20 00007C16 0009 DW 9 ; FAT的长度
21 00007C18 0012 DW 18 ; 一个磁道有几个扇区
22 00007C1A 0002 DW 2 ; 磁头数
23 00007C1C 00000000 DD 0 ; 不使用分区
24 00007C20 00000B40 DD 2880 ; 重写一次磁盘大小
25 00007C24 00 00 29 DB 0,0,0x29 ; 意义不明
26 00007C27 FFFFFFFF DD 0xffffffff ; 可能是卷标号码
27 00007C2B 48 41 52 49 42 4F 54 45 4F 53 DB "HARIBOTEOS " ; 磁盘的名称(11字节)
00007C35 20
28 00007C36 46 41 54 31 32 20 20 20 DB "FAT12 " ; 磁盘格式名称(8字节)
29 00007C3E 00 00 00 00 00 00 00 00 00 00 RESB 18 ; 先空出18字节
00007C48 00 00 00 00 00 00 00 00
30 00007C50
31 00007C50 ; 程序主体
32 00007C50
33 00007C50 entry:
34 00007C50 B8 0000 MOV AX,0 ; 寄存器初始化
35 00007C53 8E D0 MOV SS,AX
36 00007C55 BC 7C00 MOV SP,0x7c00
37 00007C58 8E D8 MOV DS,AX
38 00007C5A
39 00007C5A ; 读磁盘
40 00007C5A
41 00007C5A B8 0820 MOV AX,0x0820 ; AX=0x0820
42 00007C5D 8E C0 MOV ES,AX ; ES=AX
43 00007C5F B5 00 MOV CH,0 ; 柱面0
44 00007C61 B6 00 MOV DH,0 ; 磁头0
45 00007C63 B1 02 MOV CL,2 ; 扇区2
46 00007C65 readloop:
47 00007C65 BE 0000 MOV SI,0 ; 记录失败次数的寄存器
48 00007C68 retry:
49 00007C68 B4 02 MOV AH,0x02 ; AH=0x02 : 读入磁盘
50 00007C6A B0 01 MOV AL,1 ; 1个扇区
51 00007C6C BB 0000 MOV BX,0 ; BX=0
52 00007C6F B2 00 MOV DL,0x00 ; A驱动器
53 00007C71 CD 13 INT 0x13 ; 调用磁盘BIOS
54 00007C73 73 10 JNC next ; 没出错时跳转到next
55 00007C75 83 C6 01 ADD SI,1 ; SI加1
56 00007C78 83 FE 05 CMP SI,5 ; 比较SI与5
57 00007C7B 73 2E JAE error ; SI >= 5时,跳转到error
58 00007C7D B4 00 MOV AH,0x00 ; 复位磁盘驱动器
59 00007C7F B2 00 MOV DL,0x00 ; A驱动器
60 00007C81 CD 13 INT 0x13 ; 重置驱动器
61 00007C83 EB E3 JMP retry
62 00007C85 next:
63 00007C85 8C C0 MOV AX,ES
64 00007C87 05 0020 ADD AX,0x0020
65 00007C8A 8E C0 MOV ES,AX ; ADD ES,0x020
66 00007C8C 80 C1 01 ADD CL,1 ; CL加1
67 00007C8F 80 F9 12 CMP CL,18 ; 比较CL和18
68 00007C92 76 D1 JBE readloop ; 如果CL <= 18,则跳转至readloop
69 00007C94 B1 01 MOV CL,1 ; CL赋值为1
70 00007C96 80 C6 01 ADD DH,1 ; DH加1
71 00007C99 80 FE 02 CMP DH,2 ; 比较DH和2
72 00007C9C 72 C7 JB readloop ; 如果DH < 2,则跳转到readloop
73 00007C9E B6 00 MOV DH,0 ; DH赋值为0
74 00007CA0 80 C5 01 ADD CH,1 ; CH加1
75 00007CA3 80 FD 0A CMP CH,CYLS ; 比较CH和CYLS
76 00007CA6 72 BD JB readloop ; 如果CH < CYLS,则跳转到readloop
77 00007CA8
78 00007CA8 ; 已经读完,让CPU进入待机状态
79 00007CA8
80 00007CA8 fin:
81 00007CA8 F4 HLT ; 让CPU停止,等待指令
82 00007CA9 EB FD JMP fin ; 无限循环
83 00007CAB
84 00007CAB error:
85 00007CAB BE 7CC0 MOV SI,msg ; 将msg标签地址0x7CCD赋值给SI
86 00007CAE putloop:
87 00007CAE 8A 04 MOV AL,[SI] ; 将内存地址[SI]赋值给AL
88 00007CB0 83 C6 01 ADD SI,1 ; SI加1
89 00007CB3 3C 00 CMP AL,0 ; 比较AL和0
90 00007CB5 74 F1 JE fin ; 如果AL = 0,已经输出完毕,则跳转到fin
91 00007CB7 B4 0E MOV AH,0x0e ; 显示一个文字
92 00007CB9 BB 000F MOV BX,15 ; 指定字符颜色
93 00007CBC CD 10 INT 0x10 ; 调用显卡BIOS
94 00007CBE EB EE JMP putloop ; 跳转到putloop
95 00007CC0 msg:
96 00007CC0 0A 0A DB 0x0a, 0x0a ; 换行2次
97 00007CC2 6C 6F 61 64 20 65 72 72 6F 72 DB "load error" ; 加载错误
98 00007CCC 0A DB 0x0a ; 换行
99 00007CCD 00 DB 0
100 00007CCE
101 00007CCE 00 00 00 00 00 00 00 00 00 00 RESB 0x7dfe-$ ; 以0x00填充到0x7dfe为止
00007CD8 00 00 00 00 00 00 00 00 00 00
00007CE2 00 00 00 00 00 00 00 00 00 00
00007CEC 00 00 00 00 00 00 00 00 00 00
00007CF6 00 00 00 00 00 00 00 00 00 00
00007D00 00 00 00 00 00 00 00 00 00 00
00007D0A 00 00 00 00 00 00 00 00 00 00
00007D14 00 00 00 00 00 00 00 00 00 00
00007D1E 00 00 00 00 00 00 00 00 00 00
00007D28 00 00 00 00 00 00 00 00 00 00
00007D32 00 00 00 00 00 00 00 00 00 00
00007D3C 00 00 00 00 00 00 00 00 00 00
00007D46 00 00 00 00 00 00 00 00 00 00
00007D50 00 00 00 00 00 00 00 00 00 00
00007D5A 00 00 00 00 00 00 00 00 00 00
00007D64 00 00 00 00 00 00 00 00 00 00
00007D6E 00 00 00 00 00 00 00 00 00 00
00007D78 00 00 00 00 00 00 00 00 00 00
00007D82 00 00 00 00 00 00 00 00 00 00
00007D8C 00 00 00 00 00 00 00 00 00 00
00007D96 00 00 00 00 00 00 00 00 00 00
00007DA0 00 00 00 00 00 00 00 00 00 00
00007DAA 00 00 00 00 00 00 00 00 00 00
00007DB4 00 00 00 00 00 00 00 00 00 00
00007DBE 00 00 00 00 00 00 00 00 00 00
00007DC8 00 00 00 00 00 00 00 00 00 00
00007DD2 00 00 00 00 00 00 00 00 00 00
00007DDC 00 00 00 00 00 00 00 00 00 00
00007DE6 00 00 00 00 00 00 00 00 00 00
00007DF0 00 00 00 00 00 00 00 00 00 00
00007DFA 00 00 00 00
102 00007DFE
103 00007DFE 55 AA DB 0x55, 0xaa ; 启动区标志
三、汇编语言指令
JC(jump if carry)如果进位标志(carry flag)是1的话就跳转,进位标志用来表示有没有进位,但在CPU的标志中,它是最简单易用的,所以在其他地方也经常用到,可以用来报告BIOS函数调用是否有错
JNC(jump if not carry)如果进位标志是0的话就跳转
JAE(jump if above or equal)大于或等于时跳转
JBE(jump if below or equal)小于或等于时跳转
JB(jumo if below)小于时跳转
四、BIOS中断
电脑里有个名为BIOS(basic input output system)的程序,出厂时就组装在电脑主板上的ROM(read only memory)单元里,电脑厂家在BIOS中预先写入了操作系统开发人员会用到的一些程序。INT指令调用BIOS中断,INT后面不同的数字可以调用不同的中断,进行中断时会从一些寄存器中读取信息以处理中断,具体的信息可以查询BIOS_interrupt_call
五、显卡模式
VRAM(video RAM)显卡内存,用来显示画面的内存,不同的画面模式的像素数不一样,使用的VRAM也不一样,在VGA图形模式,320×200×8位彩色模式(调色板模式)下,VRAM是0xa0000~0xaffff的64KB
六、导入C语言之后的文件结构
bootpack.c
|cc1.exe将C语言程序编译成汇编语言源程序
bootpack.gas
|gas2nask.exe把gas变换成nask能翻译的语法
bootpack.nas naskfunc.nas
|nask.exe翻译成机器语言 |nask.exe翻译成机器语言
bootpack.obj naskfunc.obj
|obi2bim.exe为了做成完整的机器语言文件,必须将必要的目标文件全部链接上
bootpack.bim
|bim2hrb.exe为了能实际使用,针对每一种操作系统的要求进行必要的加工
bootpack.hrb
|使用copy指令将asmhead.bin(导入C语言之前的汇编语言文件)和bootpack.hrb简单的结合起来
haribote.sys