30日でできる!OS自作入門3日目
何をやるか
新しく出たアセンブラ言語の命令など
- JC キャリーフラグが1なら指定先にジャンプする。キャリーフラグは読み込みエラーが起こったときに1が出力される。
- JNC キャリーフラグが0なら指定先にジャンプする。つまり読み込みエラーがなければ指定先にジャンプするということである。
- JBE CMP命令で比較して値が小さいかもしくは等しければジャンプする。
- EQU 命令じゃないだけどC言語の#defineみたいなもの。CYLS EQU 10はCYLSは10ですよという意味である。
フロッピーディスクについて
- フロッピーは0~79の円形のシリンダーで構成されている。シリンダーはヘッダーを切り替えることによって表と裏の読みこみできる
- シリンダーは1~18のセクター(512KB)で構成されている。シリンダーとセクターは0-indexで統一しない理由はなんでなのか少し気になるな。
- シリンダーの読み込み方が一つのシリンダーの表と裏を読んだら、次のシリンダーを読むようになっている。
プログラムを読んで
- MOV [678] 123みたいなメモリーに値を代入する命令はないが、恐らくretryの処理のところのINT 0x13命令で読み込んだ値がメモリーに格納されている。メモリーに読み込んだ値を格納する番地(バッファアドレス)の指定方法はESレジスタやBXレジスタに値を導入することによって計算される。
- 多分、INT命令の所でmov [ES:BX] 読み込んだ値 が命令されているのだろう。 ES:BXはES×16+BXで計算され、ESやBXはそれぞれ16ビットのため最大表現でできる数は0xffffであるため、ES:BXで最大表現できる数は1,113,095バイト(1MB)である。
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へ
C言語導入
C言語のプログラムでHLT命令を扱えるようにするために以下のことをする。(かなりはしょっている気がするが。。。)- アセンブラのプログラムで32ビットの機械語を扱うモードを設定し、HLTを扱う関数をGLOBALで定義する。そしてオブジェクトファイルに変換する
- C言語のプログラムは、アセンブラ言語で定義したHLTを扱う関数を用いる。そしてオブジェクトファイルに変換する。
- 最後に生成された二つのオブジェクトファイルをくっつける。
感想
C言語を導入するための、アセンブラの方での設定や変換についてはあまり理解できていないと思う。書くのが億劫で3日目をまとめるのに少し時間がかかった。プログラムを読んだり実行するだけしかしていないので、せめてまとめることは続けたい。4日目からはC言語を扱うということなので少し楽しみだ。