OS自作本 MacOS 4-6日目
やったこと
画面の色と画面上のテキストとキーボードとマウス
メモリ復習
アドレス | 内容 |
---|---|
0x07C00ー0x07DFF | IPL。フロッピーの先頭1セクタ(ブートセクタ) |
0x08200ー0x34FFF | フロッピーの内容(10シリンダ分。IPLを除く) |
アドレス | 内容 |
---|---|
0x00000000ー0x000FFFFF | 起動中にいろいろ使うけど、その後は空き(1MB) |
(0x000A0000ー0x000AFFFF) | VRAM(画面用メモリ) 64KB |
0x00100000ー0x00267FFF | FDの内容記憶用(1440KB) |
0x00268000ー0x0026F7FF | 空き(30KB) |
0x0026F800ー0x0026FFFF | IDT(2KB) |
0x00270000ー0x0027FFFF | GDT(64KB) |
0x00280000ー0x002FFFFF | bootpack.hrb(512KB) |
0x00300000ー0x003FFFFF | スタックなど(1MB) |
0x00400000ー | 空き |
画面上の色(P.84, 85)
1. 色の登録(init_palette関数)
8bit color modeなので256色使えるが、使いそうな16色を登録することにする。 まず16*3のテーブルを作り、そこにそれぞれの色のRGBの値を順番に入れていく。 例えば、1番目の色を#ffffffにしたいのなら、0xff, 0xff, 0xffと入れていく。 この時、static char tableとしてtableを作成することで、アセンブラに翻訳した時にRESBではなくDBでメモリに書かれるため早いらしい。
2. 登録した内容をデバイスに送信(set_palette関数)
CPU外のデバイスに送信するので、割り込みの作業が必要。デバイスに送信する際は、io_out8というnaskfunc.nasで実装されている関数を使う。
3. VRAMメモリをいじる
VRAM(画面用メモリ)の値を適切な色に変更する。これはポインタを用いればCで実装可能。
画面上のテキスト(P101,102)
1. 文字の登録
16*8のテーブルに文字の形を登録する。 マウスカーソルも同様。
2. 文字の利用(putfont8関数)
キーボードとマウス(P.115)
1. GDTとIDTの初期化&設定
GDT : Global (Segment) Descriptor Table = セグメントの情報が詰まったテーブル
IDT : Interrupt Descriptor Table = 割り込みの情報が詰まったテーブル
これらはどちらもCPUの設定だが、これをまず初期化&設定しなければならない。
セグメントとはプログラムごとに使っているメモリのこと。それらが競合しないためにGDTが存在している。 GDTには各セグメントの大きさ、開始番号、その特性が書かれている。 そのプログラムがどのセグメントに対応しているのかを表す、セグメントレジスタというレジスタが存在しており、MOV AL [DS:EBX]という命令をすれば、自動的にEBXにそのセグメントの開始番号DSを足したところのメモリを読んでALに代入してくれる。ちなみにセグメントレジスタは16bitであり、下3bitが使えないので、結局13bit=8000個のセグメントしか利用できない。そして一つのセグメント情報は8byte必要なので64KBのメモリが必要。そしてセグメント(CPU全メモリを表しているセグメントとbootpack.hrb用のセグメント)情報をGDTに入れた後、GDTR(Global (Segment) Descriptor Table Register)という48bitのレジスタに、先頭セグメントの番地と有効設定個数(大きさ)をLGDTという命令を使って入れる。MOV命令ではなく、LGDT命令を用いるのは、48bit=6byteという特殊なレジスタだから。ちなみに48bit中、上位32bitは番地、下位16bitはリミット(GDTの有効バイト数-1)が入っている。GDTの初期化以上。
IDTは、各割り込みとそれに対応する関数の表である。「X番が発生したらY関数を呼び出す」ということが表を見たらわかるようになっている。割り込みが発生した時にまずやらないといけない処理は、割り込みハンドラ処理。簡単にいうとレジスタをメモリに退避して、割り込み処理を呼び、レジスタを復帰させIRETD命令を実行するという流れ。キーボード割り込みによって発生するレジスタ退避&復帰処理は、naskfunc.nasのasm_inthandler21に書いてあり、実際の割り込み処理はint.cのinthandler21に書かれている。C言語でレジスタ退避&復帰を書かない理由は、最後のIRETD命令でのリターンがCでは書くことができないかららしい。IDTの設定の後に、PIC(Programmable Interuppt Controller)の初期化もしなければならない。これは、PICは8個の割り込み信号IRQ(Interrupt Request)を1つの割り込み信号にまとめる装置で、これを二つ使うことによって15個の割り込み信号を可能としている。
これらの最後にCPUの割り込み設定を許可する(io_sti関数)
以下がbootpack.cのHariMain内のソースコード
init_gdtidt(); GDT, IDTの初期化&設定
init_pic(); PICの初期化&設定
io_sti(); /* IDT/PICの初期化が終わったのでCPUの割り込み禁止を解除 */