5日までのまとめ
現在30日で作るosの本を読んでます。それで、今回は7日までで出来上がったソースコードを軽く説明して行きたいと思います。
正直、自分でも全部理解している自信がないので理解できる範囲で説明して行きたいと考えております。
qiitaの投稿も今回がはじめてなので、修正点やアドバイスなどありがたくお待ちしております
では、やっていきましょう!!!!
osの起動(記憶媒体からメモリにプログラムを書き込む処理)
まず、osをどのようにして、起動するかについて説明しています。
前提条件として、記憶媒体は、フロッピーディスクをこの本では扱っています。
また、アセンブラ?にはnasmと言うソフトを活用しています。
パソコンに、電源が入ってから何をするかを教える必要があります。
これを、Bootstrapといいます。
まず、はじめにパソコンに電源が入るとcpuはBIOS ROMのプログラムにアクセスします。そして、現在使用されているマザーボードにどのような周辺機器が接続されているか確認します。
BIOSのプログラムが最後行う処理は、現在ユーザが起動に使おうとしたディスクのはじめの512バイト(MBR領域とも言います)を読み込みます。
以下のプログラムはそのmbrで読み込まれるソースコードになっています。
CYLS EQU 10 ; どこまで読み込むか
ORG 0x7c00 ; このプログラムがどこに読み込まれるのか
entry:
MOV AX,0 ; レジスタ初期化
MOV SS,AX
MOV SP,0x7c00
MOV DS,AX
; ディスクを読む
MOV AX,0x0820
MOV ES,AX
MOV CH,0 ; シリンダ0
MOV DH,0 ; ヘッド0
MOV CL,2 ; セクタ2
readloop:
MOV SI,0 ; 失敗回数を数えるレジスタ
retry:
MOV AH,0x02 ; AH=0x02 : ディスク読み込み
MOV AL,1 ; 1セクタ
MOV BX,0
MOV DL,0x00 ; Aドライブ
INT 0x13 ; ディスクBIOS呼び出し
JNC next ; エラーがおきなければnextへ
ADD SI,1 ; SIに1を足す
CMP SI,5 ; SIと5を比較
JAE error ; SI >= 5 だったらerrorへ
MOV AH,0x00
MOV DL,0x00 ; Aドライブ
INT 0x13 ; ドライブのリセット
JMP retry
next:
MOV AX,ES ; アドレスを0x200進める
ADD AX,0x0020
MOV ES,AX ; ADD ES,0x020 という命令がないのでこうしている
ADD CL,1 ; CLに1を足す
CMP CL,18 ; CLと18を比較
JBE readloop ; CL <= 18 だったらreadloopへ
MOV CL,1
ADD DH,1
CMP DH,2
JB readloop ; DH < 2 だったらreadloopへ
MOV DH,0
ADD CH,1
CMP CH,CYLS
JB readloop ; CH < CYLS だったらreadloopへ
; 読み終わったのでharibote.sysを実行だ!
MOV [0x0ff0],CH ; IPLがどこまで読んだのかをメモ
JMP 0xc200
error:
MOV SI,msg
putloop:
MOV AL,[SI]
ADD SI,1 ; SIに1を足す
CMP AL,0
JE fin
MOV AH,0x0e ; 一文字表示ファンクション
MOV BX,15 ; カラーコード
INT 0x10 ; ビデオBIOS呼び出し
JMP putloop
fin:
HLT ; 何かあるまでCPUを停止させる
JMP fin ; 無限ループ
msg:
DB 0x0a, 0x0a ; 改行を2つ
DB "load error"
DB 0x0a ; 改行
DB 0
RESB 0x7dfe-$ ; 0x7dfeまでを0x00で埋める命令
DB 0x55, 0xaa
アセンブラ言語に慣れていない僕は軽く、吐き気がありますが笑
がんばって説明していきます。
ちなみに、なんですがこの本ではアセンブラ言語は大文字で書かれていましたが小文字でもいいそうです。
ORG 0x7c00
entry:
MOV AX,0
MOV SS,AX
MOV SP,0x7c00
MOV DS,AX
はじめに、この部分なんですが
ORG 0x7c00
でこのプログラムはメモリ上の0x7c00番地からスタートするという意味があります。
なぜ、もっとはじめのほうの番地を使うことができないかといいます。これより前の番地ではすでにbiosが占領しているため私たちが使うことができないため0x7c00番地からはじまっています。
また、レジスタに変な値が入力されているといけないので初期化を行っています。
tuzuki:
MOV AX,0x0820
MOV ES,AX
MOV CH,0 ; シリンダ0
MOV DH,0 ; ヘッド0
MOV CL,2 ; セクタ2
readloop:
MOV SI,0 ; 失敗回数を数えるレジスタ
retry:
MOV AH,0x02 ; AH=0x02 : ディスク読み込み
MOV AL,1 ; 1セクタ
MOV BX,0
MOV DL,0x00 ; Aドライブ
INT 0x13 ; ディスクBIOS呼び出し
JNC next ; エラーがおきなければnextへ
ADD SI,1 ; SIに1を足す
CMP SI,5 ; SIと5を比較
JAE error ; SI >= 5 だったらerrorへ
MOV AH,0x00
MOV DL,0x00 ; Aドライブ
INT 0x13 ; ドライブのリセット
JMP retry
はじめに、esレジスタに番地を入力しているのは、そこに今度プログラムを書き込みますよーという意味です。ですので、今からフロッピーディスクからデータを読み込んでメモリに記述するのですが、そのメモリの始まりの番地を記述しています。
ここでは、フロッピーディスクから次のプログラムをよみこんでいます。
プロッピーディスクからメモリにプログラムを読み込むには、割り込みを使ってフロッピーディスクからプログラムを読み込む必要があります。
inc 13h
と記述することでcpu割り込みを行いフロッピディスクを読み込むのですが。
そのほかにも、フロッピーディスクのどこから読み込みのか?どれだけ読み込むのかをデータとして送らなければいけないのですがそのときにレジスタを使って情報を受け渡しています。
具体には、
alが何セクタ読み込むか
chは何番目のシリンダか
clは何番目のセクタから読み込むか
dhはheadの何番目か
dlはdriveの何番目か
そして、これらの情報をレジスタに渡したあとに、
int 0x13
と割り込みをかけてフロッピーディスクに情報を読み込みにいく。
また、以下ではフロッピーディスクにデータを読みこんでできなかった場合同じことを繰り返すプログラムが実装されています。
readloop:
MOV SI,0 ; 失敗回数を数えるレジスタ
retry:
MOV AH,0x02 ; AH=0x02 : ディスク読み込み
MOV AL,1 ; 1セクタ
MOV BX,0
MOV DL,0x00 ; Aドライブ
INT 0x13 ; ディスクBIOS呼び出し
JNC next ; エラーがおきなければnextへ
ADD SI,1 ; SIに1を足す
CMP SI,5 ; SIと5を比較
JAE error ; SI >= 5 だったらerrorへ
MOV AH,0x00
MOV DL,0x00 ; Aドライブ
INT 0x13 ; ドライブのリセット
JMP retry
next:
MOV AX,ES ; アドレスを0x200進める
ADD AX,0x0020
MOV ES,AX ; ADD ES,0x020 という命令がないのでこうしている
ADD CL,1 ; CLに1を足す
CMP CL,18 ; CLと18を比較
JBE readloop ; CL <= 18 だったらreadloopへ
MOV CL,1
ADD DH,1
CMP DH,2
JB readloop ; DH < 2 だったらreadloopへ
MOV DH,0
ADD CH,1
CMP CH,CYLS
JB readloop ; CH < CYLS だったらreadloopへ
; 読み終わったのでharibote.sysを実行だ!
MOV [0x0ff0],CH ; IPLがどこまで読んだのかをメモ
JMP 0xc200
error:
MOV SI,msg
putloop:
MOV AL,[SI]
ADD SI,1 ; SIに1を足す
CMP AL,0
JE fin
MOV AH,0x0e ; 一文字表示ファンクション
MOV BX,15 ; カラーコード
INT 0x10 ; ビデオBIOS呼び出し
JMP putloop
fin:
HLT ; 何かあるまでCPUを停止させる
JMP fin ; 無限ループ
msg:
DB 0x0a, 0x0a ; 改行を2つ
DB "load error"
DB 0x0a ; 改行
DB 0
RESB 0x7dfe-$ ; 0x7dfeまでを0x00で埋める命令
DB 0x55, 0xaa
そして、最後に
MOV [0x0ff0],CH
JMP 0xc200
0xc200にとびます。
これは、いろいろとコンパイルを行った結果
メイン処理の部分がそのアドレスの場所になったからそこにとんだと書いてありました。
詳しいことが、ちょっとわからなかったです。
まあ、今日はこの辺で。