おりょうの寺子屋、教師兼生徒を務めますわたくし、
おりょうが、本日は出張授業ですよ~ なんちゃって。
#はじめに
HTC Advent Calendar 2020の12日目を担当します。
ONEJAPAN HACKATHONに参加したチームHTCのメンバー、おりょうです。
今回は私が絶賛挑戦中のOS作成の一部分を切り取ってご紹介しようかなと思います。
OSってみんな知ってるけどいざ作るとなるとなんだかハードルが高く感じますよね?
でも実際ちょっと興味ありません?
少なくともここまでの前説を読んでくれているあなたは、
少なからずOSに興味があるから見に来てくれているのでしょう。
そんなあなただけに今回は!
めちゃくちゃ簡単な「なんちゃってOS(ブートセクタ編)」をご紹介いたします。
合計3回に分けて紹介する予定です。
早速見ていきましょう!
##概要
成果物:OS(フロッピーディスクで、フォーマットはFAT12)
アセンブラ:NASK
想定対象読者:OS自作をこれから始めようとしている人。
##シラバス
1時限目:アセンブリ言語でソースコードを書こう①(ORG命令~entryラベルまで)
2時限目:アセンブリ言語でソースコードを書こう②(putloopラベル)←今日はここ!
3時限目:アセンブリ言語でソースコードを書こう③(finラベル~msgラベルまで)
4時限目:出来たソースコードを機械語にアセンブルしてみよう。
5時限目:PC/ATエミュレータを使ってOSを起動させてみよう。
#2時限目:アセンブリ言語でソースコードを書こう②(putloopラベル)
まずは講義3回分のソースコードの全容を見てみましょう。
ORG 0x7c00
; 以下はFAT12フォーマットフロッピーディスクのための記述
JMP entry
DB 0x90
DB "HELLOIPL"
DW 512
DB 1
DW 1
DB 2
DW 224
DW 2880
DB 0xf0
DW 9
DW 18
DW 2
DD 0
DD 2880
DB 0,0,0x29
DD 0xffffffff
DB "HELLO-OS "
DB "FAT12 "
RESB 18
;ここからブートセクタについて書いていくで!
entry:
MOV AX,0
MOV SS,AX
MOV SP,0x7c00
MOV DS,AX
MOV ES,AX
MOV SI,msg
putloop:
MOV AL,[SI]
ADD SI,1
CMP AL,0
JE fin
MOV AH,0x0e
MOV BL,13
INT 0x10
JMP putloop
fin:
HLT
JMP fin
msg:
DB 0x0a, 0x0a
DB "hello, world"
DB 0x0a
DB 0
RESB 0x7dfe-$
DB 0x55, 0xaa
ざっと目を通しましたか?
それではさっそく説明開始!
[putloopラベル]
ここでは、文字の表示方法を指示したり、
文字表示のためのファンクション(BIOS)を呼び出します。
putloop:
MOV AL,[SI]
ADD SI,1
CMP AL,0
JE fin
MOV AH,0x0e
MOV BL,13
INT 0x10
JMP putloop
新たに命令が5種類出てきましたね。
順に説明します。
#####ADD命令
これはその名の通り、足し算する命令です。
#####CMP命令
これもその名の通り、比較する命令です。※Comparisonの略かと。
#####JE命令
これは、Jamp Equalの略で、
直前のCMP命令結果が等しければ、指定の場所へ飛ぶよう指示するための命令です。
場所の指定にはラベル名や、メモリ番地を割り当てることができます。
#####INT命令
これは簡単に言うと、関数(BIOS)呼び出し命令です。
BIOSというのは、OS開発に使える関数の集まりみたいなものでして、
PCメーカーが事前に用意しておいてくれる代物になります。
ありがたく使いましょ。
#####JMP命令
これはその名の通り、指定したラベル、番地へ飛ぶよう指示する命令です。
さて、命令の意味が分かったところでソースコードに戻ります。
上から順に行きましょう。まずはこれ↓
MOV AL,[SI]
ここで気になるのは[]だと思うんですが、
この記号は、メモリを表します。
例えとして比較例を出してみますね。
・MOV AL,SI
・MOV AL,[SI]
この2つの命令、実はALに代入される値が違います。
前者は、SIの値が入ります。
つまり、今回のソースコードで言うと、1時限目(前回記事)で登場した下記の命令。
MOV SI,msg
これによってSIには既にmsgの番地(0x7c50)が代入されいたのですが、
その値が、「MOV AL,SI」という命令によって、ALに代入されることとなります。
では後者はどうか。
後者は、SIに代入された番地の1バイトの内容をALに読み込ませるという意味になります。
つまり、0x7c50という値が代入されるのではなく、
そのメモリ番地に格納されているデータを代入されるわけです。
これが文字を表示させるうえで非常に大事なポイントでして、
[]を付けることによって、次回紹介するmsgラベルに記載のhello worldという文字を、
表示させることができるんです。
さて、「MOV AL,[SI]」の意味が、
「メモリのSI番地の1バイトの内容をALに読み込め」ということが分かったら次に行きましょう。
次はこれです。↓
ADD SI,1
これは変数SIに1を加算することで、「SIのメモリ番地を1つ先へずらす」こととなります。
勘が良い人はもうお気づきかもしれませんが、ラベル名の通り、
この個所は最終的にループさせるつもりです。
ループ処理と言えばどの言語でもよく登場する加算処理をここでもやってるんだと思ってください。
そんでもってお次はこちら↓
CMP AL,0
これによってALが0かどうかを判定し、
0ならば「JE fin」でfinラベルの処理へ飛び、
0以外ならば、そのまま先へ進むこととなります。
ALにはさっき”SIに代入されたメモリ番地にある内容”を格納したため、
現在はmsgラベル部分の内容が入ってることになるため、0ではないです。
よってそのままfinには飛ばずに処理を続けていきますよ~
次の3行はまとめて説明しちゃいましょう。
MOV AH,0x0e
MOV BL,13
INT 0x10
結論から申し上げると、この3行はビデオBIOSという
関数を利用するための要素となります。
BIOSは関数の集まりですので、そこからどれを選んで利用するかが、
OSを作るうえでは重要となります。
今回は文字を表示するということなので、
ビデオカード関係の関数である、
「INT 0x10]を選びました。
そしてこの関数を利用するにあたって必要な設定が下記です。
・AH = 0x0e;
・AL =キャラクターコード;
・BH = 0;
・BL = カラーコード;
いくつか省略可能なものがあるようですが、
これらを指定して、最後に「INT 0x10」で実行してあげることで、
めでたく文字が画面に表示されることとなります。
本日最後の命令はこちら↓
JMP putloop
この命令によって、
ALの値が0になってfinラベルに処理が移行しない限りは、
ここでまたputloopラベルの先頭に戻って、
処理を繰り返すこととなります。
いよいよ次回で「なんちゃってOS(ブートセクタ編)」のソースコード分析は終了です。
そのあとは2日かけて、「アセンブル」と「実際に起動」をやっていきますよ♪
楽しみにしていてくださいね~♬
今日の授業終わり!