第一个任务是启动。
计算机的启动,参考本篇:
http://www.cnblogs.com/rixiang/p/5075825.html
两个重要的概念:
1,boot:
软盘的第一个扇区区为启动区。(计算机读写软盘的时候,不是一个字节一个字节的读取的,而是512字节为一个单位来读写。因此,软盘的512字节为一个扇区。一张软盘的空间共有1440KB,也就是1474560字节,2880个扇区。)
2,IPL:
启动程序加载器。启动区只有区区512字节,实际的操作系统根本装不进去。所以几乎所有的操作系统,都是把加载操作系统本身的程序放在启动区里的。
前者boot这512字节是启动电脑的关键区域,而位于这一区域的IPL是一段程序,用于将操作系统从软盘,加载到磁盘里。
最初的IPL汇编代码,虽为IPL,但实际上此时并没有装载任何程序:
1 ; hello-os 2 ; TAB=4 3 4 ORG 0x7c00 ; このプログラムがどこに読み込まれるのか 5 6 ; 以下は標準的なFAT12フォーマットフロッピーディスクのための記述 7 8 JMP entry 9 DB 0x90 10 DB "HELLOIPL" ; ブートセクタの名前を自由に書いてよい(8バイト) 11 DW 512 ; 1セクタの大きさ(512にしなければいけない) 12 DB 1 ; クラスタの大きさ(1セクタにしなければいけない) 13 DW 1 ; FATがどこから始まるか(普通は1セクタ目からにする) 14 DB 2 ; FATの個数(2にしなければいけない) 15 DW 224 ; ルートディレクトリ領域の大きさ(普通は224エントリにする) 16 DW 2880 ; このドライブの大きさ(2880セクタにしなければいけない) 17 DB 0xf0 ; メディアのタイプ(0xf0にしなければいけない) 18 DW 9 ; FAT領域の長さ(9セクタにしなければいけない) 19 DW 18 ; 1トラックにいくつのセクタがあるか(18にしなければいけない) 20 DW 2 ; ヘッドの数(2にしなければいけない) 21 DD 0 ; パーティションを使ってないのでここは必ず0 22 DD 2880 ; このドライブ大きさをもう一度書く 23 DB 0,0,0x29 ; よくわからないけどこの値にしておくといいらしい 24 DD 0xffffffff ; たぶんボリュームシリアル番号 25 DB "HELLO-OS " ; ディスクの名前(11バイト) 26 DB "FAT12 " ; フォーマットの名前(8バイト) 27 RESB 18 ; とりあえず18バイトあけておく 28 29 ; プログラム本体 30 31 entry: 32 MOV AX,0 ; レジスタ初期化 33 MOV SS,AX 34 MOV SP,0x7c00 35 MOV DS,AX 36 MOV ES,AX 37 38 MOV SI,msg 39 putloop: 40 MOV AL,[SI] 41 ADD SI,1 ; SIに1を足す 42 CMP AL,0 43 JE fin 44 MOV AH,0x0e ; 一文字表示ファンクション 45 MOV BX,15 ; カラーコード 46 INT 0x10 ; ビデオBIOS呼び出し 47 JMP putloop 48 fin: 49 HLT ; 何かあるまでCPUを停止させる 50 JMP fin ; 無限ループ 51 52 msg: 53 DB 0x0a, 0x0a ; 改行を2つ 54 DB "hello, world" 55 DB 0x0a ; 改行 56 DB 0 57 58 RESB 0x7dfe-$ ; 0x7dfeまでを0x00で埋める命令 59 60 DB 0x55, 0xaa 61 62 ; 以下はブートセクタ以外の部分の記述 63 64 DB 0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00 65 RESB 4600 66 DB 0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00 67 RESB 1469432
接下来,就是要写真正的IPL程序。
上文已述,一张软盘的质量为1440KB。
含有IPL的启动区,位于C0-HO-S1(柱面0,磁头0,扇区1)。下一个扇区是C0-H0-S2。首先装载这一扇区。直至C0-H0-S18。
C0-H0-S18的下一个扇区是软盘反面的C0-H1-S1。按顺序读到C0-H1-S18。
然后下一个柱面,C1-H0-S1。最后直至C9-H1-S18。
1 ; haribote-ipl 2 ; TAB=4 3 4 CYLS EQU 10 ; どこまで読み込むか 5 6 ORG 0x7c00 ; このプログラムがどこに読み込まれるのか 7 8 ; 以下は標準的なFAT12フォーマットフロッピーディスクのための記述 9 10 JMP entry 11 DB 0x90 12 DB "HARIBOTE" ; ブートセクタの名前を自由に書いてよい(8バイト) 13 DW 512 ; 1セクタの大きさ(512にしなければいけない) 14 DB 1 ; クラスタの大きさ(1セクタにしなければいけない) 15 DW 1 ; FATがどこから始まるか(普通は1セクタ目からにする) 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トラックにいくつのセクタがあるか(18にしなければいけない) 22 DW 2 ; ヘッドの数(2にしなければいけない) 23 DD 0 ; パーティションを使ってないのでここは必ず0 24 DD 2880 ; このドライブ大きさをもう一度書く 25 DB 0,0,0x29 ; よくわからないけどこの値にしておくといいらしい 26 DD 0xffffffff ; たぶんボリュームシリアル番号 27 DB "HARIBOTEOS " ; ディスクの名前(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進める 64 ADD AX,0x0020 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 ; 読み終わったけどとりあえずやることないので寝る 79 80 fin: 81 HLT ; 何かあるまでCPUを停止させる 82 JMP fin ; 無限ループ 83 84 error: 85 MOV SI,msg 86 putloop: 87 MOV AL,[SI] 88 ADD SI,1 ; SIに1を足す 89 CMP AL,0 90 JE fin 91 MOV AH,0x0e ; 一文字表示ファンクション 92 MOV BX,15 ; カラーコード 93 INT 0x10 ; ビデオBIOS呼び出し 94 JMP putloop 95 msg: 96 DB 0x0a, 0x0a ; 改行を2つ 97 DB "load error" 98 DB 0x0a ; 改行 99 DB 0 100 101 RESB 0x7dfe-$ ; 0x7dfeまでを0x00で埋める命令 102 103 DB 0x55, 0xaa
此时已将软盘最初的10×2×18×512=184320byte=180KB内容装载到内存(具体内容就是汇编知识了)
内存0x08200到0x34ffff。
装载之后自然就是启动操作系统的过程。
比如在软盘0x004200地址有一个程序。那么启动它就要到内存0x8000+0x4200 = 0xc200地址。
此时,系统启动的工作其实已经告一段落,接下来作者做的工作就是导入C语言。
以及添入一个简单界面显示的程序。
这样一来就是从启动区开始加载操作系统到内存,然后运行图形界面程序。
理解上已经无碍了。
具体设计的就是画面显示方面的知识。