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の割り込み禁止を解除 */
めっちゃ疲れたけど頭に内容が入ったので楽しい。
OS自作本 MacOS 1-3日目
めちゃめちゃ重要なこと
HexからBinary変換
- Hexの各桁がBinaryの4桁になる
- 0xffff -> 1111 1111 1111 1111
- 2の16乗 - 1 ≒ 2の16乗 = 64 * 1024 = 64KB
BinaryからHex変換
- Binaryの4桁分をHexの1桁にする(逆の作業)
この計算を一瞬でできるように!
全体像
細かいところの説明が多く、OS開発の全体像が見えず嫌になっているので、先人たちのまとめをみながらじっくり整理して理解していく。
このサイトに書かれていることがとてもわかりやすい。
はりぼてOS起動までの流れ
https://wa3.i-3-i.info/word15562.html http://www.cqpub.co.jp/interface/sample/200511/if0511_chap1.pdf
OS 30日本に書かれていることは、これらのWebsiteに書かれていること(PCの電源を入れてからOSが起動するまでの流れ)と合致している。
その他
以下は『30日でできる!OS自作入門』のメモから勝手に使用させていただいています。
各ソースコードの役割
番号 | 対応するソースコード |
---|---|
4 | ipl10.nas |
5,6 | asmhead.nas |
7 | 上記以外のbootpack.cやsheet.cなど |
asmhead.nasについて
asmhead.nasの処理については最初から理解する必要はないです。 本の中で徐々に解説されていきます。 asmhead.nasですでにメモリにロードされているFDの内容をまた別のところにコピーしているのは、 用意してあるセグメントに移すためと、P171のメモリマップに合わせるためという意図があるようです。
とりあえず、上記の
- OS本体の起動準備(画面モード設定・1MB以上のメモリにアクセスできるようにする・32ビットモードに移行など)
- bootpackを用意してあるセグメントにコピーして実行
がasmhead.nasの役割。bootpack.cにいろいろ書くことで、C言語を用いて開発できるようになっているのは、asmhead.nasにbootpack.cとのつなぎの部分が書かれているから。
フロッピーディスク
メモリマップ
アドレス | 内容 |
---|---|
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.63に書いてあるが、BIOSのページ (AT)BIOS - os-wiki
によれば
おまけ:一番簡単な画面モード0x13の使い方
このモードは解像度が荒いですが、パックドピクセルなのでとても簡単に扱えます。まず画面モードを切り替えて、そんでもってパレットを設定してしまいましょう。 VRAMは0xa0000~0xaffffの64KBです。厳密に言うと、320x200=64000なので、62.5KBですが。1ドット==1バイトですので、がしがしライトしてください。リードもOKです。たるいBIOSで1点ずつ描いていく必要はありません。以上!
と書いているので
上の
アドレス | 内容 |
---|---|
0x00000000ー0x000FFFFF | 起動中にいろいろ使うけど、その後は空き(1MB) |
(0x000A0000ー0x000AFFFF) | VRAM(画面用メモリ) 64KB |
となる
これからの開発の流れ
疑問
p.40 「BIOSはPC基板上のRead Only Memoryにあらかじめ組み込まれている、基本的な入出力に関する関数の集まり」とあるが、PC基板上とはどこなのか。ハードウェアでどうやってそんな設計が可能なのか。
p.42 「0x00007c00-0x00007dffがブートセクタが読み込まれるアドレス」と書かれているが、これは全てのOSで共通していることなのか?qemuでOSを立ち上げているが、qemuにもこのようなメモリマップの設定がされてあるのか?またブートセクタでやらないといけないことは何なのか。
p.44 「Makefileを動かすようにするには、make.exeを呼び出す必要があります。」と書かれているが、macで実行する場合、make.exeは呼び出せない。macの場合のMakefileはどのように起動されているのか?またmake.batには以下のように書かれているが、%1 %2 %3 %4 %5 %6 %7 %8 %9パートは何の役割を果たしているのか?
..¥z_tools¥make.exe %1 %2 %3 %4 %5 %6 %7 %8 %9
- p.52 バッファアドレスを決めるときに、「MOV AL [ES:BX]と書き、ES*16+BXのアドレスを指定することで、114095バイトまでメモリ番地を指定できるようになる」と書いてあるが、結局使うのが16マシンだったらES:BXの計算結果を使えないのではないのか?(結果を使うためにはどこかのレジスタかなんかに保存する必要がありそうなので)
30日OS本 macOS Mojave 環境構築
環境構築手順
このWebsiteを参考にして、環境構築してみると、make runで失敗してしまう。
cp helloos.img ../../z_tools/qemu/fdimage0.bin make -C ../../z_tools/qemu qemu-system-i386 -L . -m 32 -localtime -vga std -fda fdimage0.bin qemu-system-i386: -localtime: invalid option make[1]: *** [default] Error 1 make: *** [run] Error 2
のようなエラーが出てしまった。
解決法
上のWebsiteを最後までやったのち、
から、z_tools_osxをダウンロードする。
z_tools_osxをz_toolsに名前を変更して、
HariboteOSディレクトリに置き、z_toolsを上書きする。
追記
3日目の最後の方でバグが生じるので、以下も変更しておいてください。
HariboteOS/z_tools/haribote/ の中にある、haribote.rulの中身の
../z_tools/haribote/harilibc.lib; ../z_tools/haribote/golibc.lib;
を以下のように変更する。
../../z_tools/haribote/harilibc.lib; ../../z_tools/haribote/golibc.lib;
完成!試してみる。
cd ~/HariboteOS/01_day/helloos0 make run