5日目 構造体と文字表示とGDT/IDT初期化
5日目。
1. 起動情報の受け取り
bootpack.cでVRAMの場所とかサイズを生の数字で打ち込んだが、本来はこれらはasmhead.nasでメモした値を取得して使うべきである。
2. 構造体を使ってみる
起動情報のパラメタはまとめて構造体にしてしまう
3. 矢印表記を使ってみる
(*a).b は a->b と書ける。ただのC言語の話。
4. とにかく文字を出したい
文字(半角)は8x16の長方形の画素の集まりで書ける。アスキーアートみたいな感じ。頑張ってAを作成。!も簡単だったので作成。
結局は、文字の形になるように画素の色を変更するだけ。
void putfont8(char *vram, int xsize, int x, int y, char c, char *font)
fontに作成した画素マップ。x, y にどの場所に文字を出力するか、cに色をいれる。
5. フォントを増やしたい
A!と同じように全てのアルファベットを…は大変。面倒なのでOSASKで使われているフォントデータを流用。
Aのフォントデータはhankaku + ‘A’ * 16 からの16 バイトに収められている。
6. 文字列を描きたい
1文字1文字書くのは大変。なので表示したい文字列を引数に渡して、それを出力する関数を作成。
C言語では文字列の最後は0x00で終わる。
7. 変数の値の表示
sprintfを使う。printfは処理がOS依存(?) なのに対して、sprintfはメモリを操作するだけなのでOSに依らずに使える。
sprintfで変数を埋め込んだ文字列を作成して表示。
8. マウスカーソルも描いてみよう
マウスカーソルもかけます。
9. GDTとIDTを初期化しよう
マウスを動かしたい。そのためにちょっと難しい話。
セグメンテーション
アセンブラにあったORG命令は、このプログラムがメモリのどこに読み込まれるかを宣言する命令であった。
複数のプログラムが同時に動いた時、メモリの利用範囲が重なるといけないので、セグメンテーションによる解決をしている。
セグメンテーションとは、メモリを好きなように切り分けてそれぞれのブロックの最初の番地を0として扱えるという機能。
セグメント
セグメントの1つを表すには次の情報が必要。
-
セグメントの大きさはどのくらいか?
-
セグメントがどの番地から始まるか?
-
セグメントの管理用属性(書き込み禁止・実行禁止・システム専用など)
CPUではこれらの情報を8バイトで表しているが、セグメントを指定するためのレジスタは16ビットしかないので、パレットと同じようなシステムを使う。
このセグメント情報をメモリに書き込んだものをGDT(global descriptor table)という。メモリのどこかにセグメントの設定を書き込んで、その先頭の番地と有効設定個数をCPUのGDTRという特別なレジスタに設定すれば完了。
IDTはinterrupt descriptor tableの略で、割り込み記述子表。CPUには外部の状況や滅多に起きない内部のトラブルが起こると、臨時で処理を切り替えさせる機能がある。これが割り込み機能。
外部の装置に変化があったときに割り込みが発生し、CPUは現在実行中の処理を一時中断して後で再開可能になるように準備したのち予め設定しておいた関数を呼び出してくれる。
マウスを使うには、割り込みを使えるようにしないといけない。IDTを設定する必要がある。
IDTは割り込み番号0~255に対して割り込み番号123が発生したらxx関数を呼び出してね〜みたいな設定の表。