bluespearの「OS自作入門」勉強日記

2006-07-28

四日目 C言語と画面表示 12:33

4.1 C言語からメモリに書き込みたい(harib01a)

VRAMに直接書き込んで画面に何か表示しましょう、という話。

C言語には直接書き込む命令が無いから、アセンブラ関数作っていますが、C言語にはポインタがあるので、それで書き込むことも出来ますね。

アセンブラ部分で重要なのは、引数の保存場所と使えるレジスタ

といった形で保存されるようです。32ビットモードだからintは32ビット幅の整数値。アドレスが4つ進むってことは、4バイト分=32ビット分ですね。

C言語と連携する場合に使えるレジスタはEAX,ECX,EDXの3つだけ。

新しく出てきたINSTRSET命令はnaskに対象CPUを教える命令で、EAXなどの単語に対応させるだけのようです。

C言語部分はforを使って0xa0000から0xaffffまでの範囲を15で埋めてます。15というと0xfですね。RGB値で言えば全てfで埋まると白くなります。

さあmake run。見事真っ白な画面になりました。VRAMに直接書くとか、なんかかっこいいです。

4.2 しましま模様(harib01b)

今度は画面をしましま模様で埋めてみましょうとのこと。

これはbootpack.cを変更するだけです。VRAMを埋めるforループを15では無く,i & 0x0fで埋めています。

&はそのまんまアンド演算子で、ビットマスク取るのに使ってますね。0x0f = 00001111なので上位4ビット分を0にして、下位4ビットだけ残すことになります。iは0xa0000から0xaffffまで変化するので、VRAMには0x00から0x0fまでの数値が場所に応じて入ることになります。

meke runで見事にしましま模様が表示されます。

f:id:bluespear:20060728122900p:image

何か気持ち悪い色。ちょっと脱線して白黒の帯にしてみましょうか。いじるのは書き込む数値だけですから簡単簡単。write_mem8(i, i % 2)に変更してmake run。

f:id:bluespear:20060728122955p:image

あれ?青と黒の帯になっちゃいました。

えっと、各画素に対応するVRAMは8ビットカラーモードだから1バイト分。witemem8は1バイト分。あ、i % 2がいけないんですね。0とfで埋めるのに0と1で埋めちゃってます。

上手い解決法が思いつかないのでwrite_mem8(i, (i % 2) * 0xf)としちゃいましょう。make run。

f:id:bluespear:20060728123020p:image

今度は成功。ふー。

4.3 ポインタに挑戦(harib01c)

メモリに直接書き込むのにポインタ使いましょう、と言う話。

ここで、変数宣言が必要な理由が説明されます。要するにメモリサイズがわからないと代入のしようが無いよ、ということ。それとC言語の型の厳密性の話で、キャストしないでポインタに直接数値入れるなって警告に対して「どっちだって同じ数値じゃないか」と書いてあります。それ言ったら何もかも、同じ0と1の組み合わせじゃないか、になっちゃいますね。実際そうなんですけど、C言語みたいに高級言語は、プログラマのミスを減らすための仕組みが色々あるから、こうなるってことでしょうかね。

Column-2

*p = i & 0x0f;

*((* char) i) = i & 0x0f;

が同じ、と書いてありますが、下の例は私には簡単には解読できません。括弧多すぎ。

Column-3

C言語の壁と言われるポインタの話。書いてある範囲では、私のポインタについての理解は間違ってないようです。よかった。

ただ、ポインタを分かりやすくしてほしい、とは思ってないなぁ。何処をどうすればわかりやすくなるんでしょうね。ポインタアドレスでいいじゃないですか。*をつけると、そのアドレスの指し示す場所を表すだけの話です。

4.4 ポインタの応用(1) (harib01d)

ポインタ使ってこうもかけますって例。疑問なし。

4.5 ポインタの応用(2) (harib01e)

*(p + i)とp[i]は同じだよ、って話。ここら辺の話はポインタ完全制覇で知ってました。

Column-4

p[i]は*(p + i)のシンタックシュガーに過ぎない、と言う話。ここら辺もポインタ完全制覇を参照。

p[i]をi[p]と書いても動くってのは、なるほどなと思いました。実際そんな書き方されたらぶちぎれますけどね。

4.6 色番号設定(harib01f)

カラーパレットの設定です。なにやら色々増えてます。

まずはbootpack.c。

init_palette()内で重要なのは、static宣言するとDB命令を使うようになる点かな。

set_palette()ではio_系の関数を使ってパレットの設定をしています。

io_out8()は指定した装置にデータを送る関数。こいつで0x03c8と0x03c9にデータを送っています。この数値が何を意味するかは http://community.osdev.info/index.php?VGA を参照。

なので、最初にパレットを書き込みモードにしてからRGB値をそれぞれ書き込んでいることになります。

書き込む方法は

パレットのアクセスの手順

* まず一連のアクセス中に割り込みなどが入らないようにする(たとえばCLI)。

* 0x03c8に設定したいパレット番号を書き込み、続いて、R、G、Bの順に0x03c9に書き込む。もし次のパレットも続けて設定したいのなら、パレット番号の設定を省略して、さらにRGBの順に0x03c9に書き込んでよい。

* 現在のパレット状態を読み出すときは、まず0x03c7にパレット番号を書き込んで、0x03c9を3回読み出す。これが順にR、G、Bになっている。これももし次のパレットも読み出したいときは、パレット番号の設定を省略してRGBの順に読み出してよい。

* 最初にCLIした場合は、最後にSTIする。

ですので、この通り処理しているということですね。

割り込み処理への対応はio_cli()で割り込みフラグを0にして、処理が終わったらio_store_eflags()で元の値に戻しています。割り込みフラグはEFLAGSという特殊なレジスタの第9ビットに割り当てられています。EFLAGSとはFLAGSを拡張して32ビットにした、フラグが詰まったレジスタです。

次はnaskfunc.nasです。

io_in*やio_out*はそのまま*の数値の大きさで、I/O命令を扱ってます。io_load_eflagsとio_store_eflagsではスタックを使ってデータのやり取りをしています。PUSHFD命令、POPFD命令でフラグダブルワードで出し入れしています。MOV EAX,EFLAGSみたいに出来ないので、このような形になっているそうです。

アセンブラで書かれた関数戻り値はRETした時点でEAXに入っている値となります。

説明されていないほかの関数も、名前そのまんまの内容です。

さあ、make run。色が違うしま模様が出来ました。

f:id:bluespear:20060728143957p:image

4.7 四角形を描く(harib01g)

しま模様から四角形に描くものを変えます。

VRAMのメモリ番地と画素の座標の対応は 0xa0000 + x + y * 320 となります。左上から始まって、右にいって端まで行ったら一つ下に、というイメージですね。これは320*200*8bitの画面モードの話ですが、他の画面モードでも、先頭アドレスとyの係数が変わるだけだそうです。

ここでは四角形を描くboxfill8()関数を作って、それを利用しています。

void boxfill8(unsigned char *vram, int xsize, unsigned char c, int x0, int y0, int x1, int y1)

第2引数のxsizeが必要なのは画面モードによってyの係数が変化するからですね。ということは、この関数は別の画面モードでも問題なく使えます。

そしてmake run。おー。赤、緑、青の四角形が描かれました。

4.8 今日の仕上げ(harib01h)

OSぽい、というかWindowsぽい画面を表示するように、HariMain()関数内でboxfill8()関数を呼んでいるだけですね。

単純に数値を指定するのではなく、xsize, ysizeを使って下から1ピクセルずらして描く、みたいな工夫がされています。xsize-1は一番右の画素で、ずらす工夫はxsize-4の左に3ピクセルずらす、とかですね。試しにharib01gでboxfill8(p, 320, COL8_FF0000, 0, 0, 320, 100);としたところ、一つ下の列に1ドット余計な赤がかかれました。左上の座標が(0,0)、右下が(xsize-1,ysize-1)ということです。

make run。

f:id:bluespear:20060728150656p:image

おお。Wnidowsだw

4日目終了

VRAMに直接描いて、自力で画面に出力できるところまできました。見た目の変化がないと、達成感が少ないので、画面描写から入るこの本の構成はいい感じです。

明日は、もっといろんなものを描けるようにするみたいです。楽しみ

LakatosLakatos2012/02/22 02:14Gee whiz, and I tohught this would be hard to find out.

bebnriybebnriy2012/02/23 18:50o0FMhr <a href="http://nkqzuqwncftg.com/">nkqzuqwncftg</a>

zwzlxmzwzlxm2012/02/24 00:21krP1WV , [url=http://wlgsyuujwvtv.com/]wlgsyuujwvtv[/url], [link=http://lrkuqklxduhy.com/]lrkuqklxduhy[/link], http://qepbujygxxuu.com/