30日でできる!OS自作入門5日目
何をやるか
- 構造体入門(省略)
- 文字やマウスカーソルの表示
- マウスカーソルを動かすためのセグメンテーションと割り込みの入門
構造体入門
- 構造体は複数の変数をまとめて宣言するものであり、構造体を使うメリットは関数にデータを引き渡すときに引数を減らすことなどが考えられる。
- 以下の構造体BOOTINFOは、OSのインターフェースの描画に関する設定情報(描画システムの横や縦の解像度)をまとめたものである。
struct BOOTINFO { char cyls, leds, vmode, reserve; short scrnx, scrny; char *vram; };
- cyls,leds,vmode,reserve,...*vramの情報をOS本の3日目(p.62)で、メモリーのアドレス0x00ff0から順に保存されている。
- メモリーに保存されているインターフェースの横のサイズの情報を構造体のポインタで参照するために、構造体の中にある先頭の変数のアドレス
struct BOOTINFO *binfo = (struct BOOTINFO *) 0xf00f0;
を代入し、(*binfo).scrnx
またはbinfo->scrnx
と書く。
文字表示
4日目に描いたインターフェースに文字を書く。文字は8*16の長方形の集まりで0,1で表現できる、以下の写真は0,1で’A’を表現したものである。- プログラムではAを0,1で表現したものを配列データとして16進数で保存する。これをフォントデータとよぶ。
static char font_A[16] = { 0x00, 0x18, 0x18, 0x18, 0x18, 0x24, 0x24, 0x24, 0x24, 0x7e, 0x42, 0x42, 0x42, 0xe7, 0x00, 0x00 };
- 下記にはインターフェースに文字を表示させるための関数が書かれている。引数vramは4日目で用いたビデオラムのアドレス、xsizeはインターフェースの横のサイズ、xやyは文字を表示させたい位置、cは文字の色、fontにはAを表現した配列データのアドレスのことである。変数pにはインターフェースに文字表示させる場所に対応するビデオラムのアドレスが書かていて、 変数dにはフォントデータの一つの要素が書かれている。
- フォントデータの1を白色,0を背景色にすることで文字を表示する。
if ((d & 0x80) != 0) { p[0] = c; }
はフォントデータの一つの要素を2進数で表現した時に左から一番目の桁が1である場合に、それに対応するビデオラムを白色に塗る。他のif文の処理もある桁が1である場合に同様の処理をしている。このような処理を繰り返して文字を表示する。
void putfont8(char *vram, int xsize, int x, int y, char c, char *font) { int i; char *p, d /* data */; for (i = 0; i < 16; i++) { p = vram + (y + i) * xsize + x; d = font[i]; if ((d & 0x80) != 0) { p[0] = c; } if ((d & 0x40) != 0) { p[1] = c; } if ((d & 0x20) != 0) { p[2] = c; } if ((d & 0x10) != 0) { p[3] = c; } if ((d & 0x08) != 0) { p[4] = c; } if ((d & 0x04) != 0) { p[5] = c; } if ((d & 0x02) != 0) { p[6] = c; } if ((d & 0x01) != 0) { p[7] = c; } } return; }
この関数を用いて文字”A”を表示させた。
この後A以外のフォント、値、マウスカーソルを表示する。
セグメンテーション,割り込みの入門
描いたマウスカーソルを動かすためにセグメンテーションや割り込みの話が関わってくる。セグメンテーション
- プログラムをメモリーに読み込ませるために、アセンブラ言語ではORG命令で
ORG 0x1234
という風に番地を指定する必要があった。しかしアプリケーションを複数読み込ませる時に、ORG命令を用いるとメモリーの利用範囲が重なることがありエラーがおきてしまうことがある。これを解消するためにセグメンテーションが必要である。 - セグメンテーションはメモリーをブロックごとに好きに切り分けて、最初の番地を0として扱える機能である。どのプログラムも
ORG 0
と書いても問題がなくなる。 - セグメンテーションは一つのセグメント(ブロック)を表すために以下の設定情報が必要である。
- セグメントの大きさ
- セグメントはどの番地から始まるのか
- セグメントの管理用属性(書き込み禁止・実行禁止・システム専用)
- CPUでは3つの設定情報を8バイトであらわされている。複数のセグメントの情報を並べたものをGDTとよぶ。
- グラフィック色番号(4日目)と同じようにセグメント番号があり、セグメントレジスタを用いてどのセグメントがどのセグメント番号に対応させるかの設定が必要である。
割り込み
- 外部からの入力が起きたときに臨時で処理を切り替えさせる機能で、マウスカーソルを動かすためには必要である。
- 割り込みが起きたときに処理を切り替えて後で再開可能できるようにし、設定した処理を行う。
- IDTはGDTと同様に複数の割り込みの設定情報を並べたものである。