おりょうの寺子屋、教師兼生徒を務めますわたくし、
おりょうが、本日は出張授業ですよ~ なんちゃって。
#はじめに
HTC Advent Calendar 2020の7日目を担当します。
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を起動させてみよう。
#1時限目:アセンブリ言語でソースコードを書こう①
(ORG命令~entryラベルまで)
まずは講義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
ざっと目を通しましたか?
それではさっそく説明開始!
##ORG命令
上から順に行きますと、
まずORG命令が出てきますね。
意味は「メモリの○○番地から読み込んでいくよ~」です。
メモリの番地は16進数で指定してあげてくださいね。
むむ、「なぜ0x7c00なんですか?」って質問が飛んできそうですね。
理由はズバリ、ブートセクタが読み込まれるアドレスが
0x7c00 ~ 0x7dff
と決まっているからなんです。
なぜそう決まったのかを私に問うのは禁止です。
##FAT12
では次に、FAT12フォーマットフロッピーディスクのための記述部分ですが、
ここもほとんどが決まり文句と言いますか、このように記載するルールとなっています。
なのでここはあまり気にせずこの通真似して書いてください。
まあ気軽にいじれるところとしたら下記くらいですかね。
DB "HELLOIPL" ;任意のブートセクタ名
DB "HELLO-OS " ;ディスクの名前
バイト数は固定なので、そこだけ注意してくださいね。
##entryラベル
ここからが本題のブートセクタ部分です。
ラベルごとに説明していきますね。
今日紹介するのは[entryラベル]。
ここでは、レジスタの初期化を行います。
ここについても順に説明していきますよ。
entry:
MOV AX,0
MOV SS,AX
MOV SP,0x7c00
MOV DS,AX
MOV ES,AX
MOV SI,msg
###MOV命令とレジスタ
アセンブリ言語にはMOV命令というものがあって、
「MOV A,B」で「AにBを代入する」といった意味になります。
そしてAX,SS,SP等が何者かと申しますと、レジスタです。
レジスタというのは、CPUにある記憶回路のことで、
ここでは変数のようなものだと思っていただいて結構です。
今の説明を踏まえて上記ソースコードを人間様にわかりやすいように解読すると下記のようになります。
SS=0
SP=0x7c00
DS=0
ES=0
これだと数学みたいで分かりやすいでしょ?
あとは最終行の「MOV SI,msg」だけですね。
これもMOV命令ですので、結局は上記と同じです。
違いとしては、代入する値がラベル名となっている点ですね。
一見ラベル名を変数に代入なんておかしな話に聞こえますが、
代入される値は結局のところただの数値です。
実は、ここにラベル名を指定することで代入されるのは、
そのラベルが読み込まれるメモリの番地なのです。
つまり、msgラベルが読み込まれる番地(0x7c74)ということです。
そのため、「MOV SI,msg」を書き換えると、
「MOV SI,0x7c74」と書くことができます。
あらためてentryラベル部分を人間様の理解しやすいよう書き換えてみるとこうなります。
SS=0
SP=0x7c00
DS=0
ES=0
SI=0x7c74
ここまでで、ブートセクタの下準備は完了です!
次回からは実際に「hello world」と表記させるためのコードを書いていきますよ。
1時限目は以上!休み時間!
##参考
oswiki.osask.jp