OS自作入門 onLinux 4日目
4日目がようやく終わりました。賞味3、4日間といったところでしょうか。
文化祭関連の準備でも忙しかったです。
ある場所につまづいていたため、大分時間がかかってしまいました…
とりあえずソースコードはこちら。
====
#include "func.h" #define COLORN 16 #define COL_000000 0 #define COL_FF0000 1 #define COL_00FF00 2 #define COL_FFFF00 3 #define COL_0000FF 4 #define COL_FF00FF 5 #define COL_00FFFF 6 #define COL_FFFFFF 7 #define COL_C6C6C6 8 #define COL_840000 9 #define COL_008400 10 #define COL_848400 11 #define COL_000084 12 #define COL_840084 13 #define COL_008484 14 #define COL_848484 15 void Main(); void init_palete(); void set_palete(int, int, unsigned char *); void boxfill(unsigned char *, int, unsigned char, int, int, int, int); void Main() { char *vram = (char *)0xa0000; const int x = 320, y = 200; init_palete(); boxfill(vram, x, COL_008484, 0, 0, x - 1, y - 29); boxfill(vram, x, COL_C6C6C6, 0, y - 28, x - 1, y - 28); boxfill(vram, x, COL_FFFFFF, 0, y - 27, x - 1, y - 27); boxfill(vram, x, COL_C6C6C6, 0, y - 26, x - 1, y - 1); boxfill(vram, x, COL_FFFFFF, 3, y - 24, 59, y - 24); boxfill(vram, x, COL_FFFFFF, 2, y - 24, 2, y - 4); boxfill(vram, x, COL_848484, 3, y - 4, 59, y - 4); boxfill(vram, x, COL_848484, 59, y - 23, 59, y - 5); boxfill(vram, x, COL_000000, 2, y - 3, 59, y - 3); boxfill(vram, x, COL_000000, 60, y - 24, 60, y - 3); boxfill(vram, x, COL_848484, x - 47, y - 24, x - 4, y - 24); boxfill(vram, x, COL_848484, x - 47, y - 23, x - 47, y - 4); boxfill(vram, x, COL_FFFFFF, x - 47, y - 3, x - 4, y - 3); boxfill(vram, x, COL_FFFFFF, x - 3, y - 24, x - 3, y - 3); while(1) { io_hlt(); } } void init_palete() { unsigned char table_rgb[COLORN * 3] = { 0x00, 0x00, 0x00, // 0: black 0xff, 0x00, 0x00, // 1: red 0x00, 0xff, 0x00, // 2: lime 0xff, 0xff, 0x00, // 3: yellow 0x00, 0x00, 0xff, // 4: blue 0xff, 0x00, 0xff, // 5: purple 0x00, 0xff, 0xff, // 6: cyan 0xff, 0xff, 0xff, // 7: white 0xc6, 0xc6, 0xc6, // 8: gray 0x84, 0x00, 0x00, // 9: dark red 0x00, 0x84, 0x00, // 10: green 0x84, 0x84, 0x00, // 11: dark yellow 0x00, 0x00, 0x84, // 12: dark blue 0x84, 0x00, 0x84, // 13: dark purple 0x00, 0x84, 0x84, // 14: dark cyan 0x84, 0x84, 0x84 // 15: dark gray }; set_palete(0, 15, table_rgb); } void set_palete(int start, int end, unsigned char *rgb) { int i, eflags; eflags = io_load_eflags(); io_cli(); io_out8(0x03c8, start); for( i = start; i <= end; i++ ) { io_out8(0x03c9, rgb[0] / 4); io_out8(0x03c9, rgb[1] / 4); io_out8(0x03c9, rgb[2] / 4); rgb += 3; } io_store_eflags(eflags); } void boxfill(unsigned char *vram, int width, unsigned char c, int x0, int y0, int x1, int y1) { int x, y; for( y = y0; y <= y1; y++ ) { for( x = x0; x <= x1; x++ ) vram[y * width + x] = c; } }
boot.cです。bootpack.cから名前を変更しました。
始めのdefineは、カラーコードをマクロ定義しています。
基本的にはやはりOS自作本通りなのですが、一か所大きな変更点があります。
init_palete関数中のtable_rgbがstaticではなくauto宣言になっています。
自作本では「staticをつけないと無駄な代入が大量に行われるので、
staticをつければDBになって節約できる」とありました。
多分その通りです。
ところが、僕の環境では、staticをつけると動作せず、staticを外すと動作しました。
以下、自分なりの考察です。
table_rgbは初期値付きの静的配列です。
.bssセクションに配置されます。
ここでは、仮にファイル先頭からの.bssの
オフセットを0x0140とします。
さて、boot.cはコンパイルしてboot.oというオブジェクトファイルになり、
func.sをアセンブルしたオブジェクトファイルfunc.oとldでリンクされてboot.binになります。
リンク時に、変数のオフセットが計算されて、静的変数の場合はバイナリ中に書き込まれます。
この後、boot.binはhead.binの後ろにくっつけられます。
table_rgbはあくまでファイル先頭からのオフセット0x0140ですから、
ポインタの指し示す先が変わってしまいます。
table_rgbは適当な実行コードをさもRGB値のデータであるかの
ように指示してしまいます。
table_rgbの配列中の値がすべて0x00になっていたみたいなので、
どうしてかと思って色々考えてみたところ、多分こうなのではないかと思います。
間違っている可能性大なのでご注意を!
というわけで、とりあえずstaticを外しておきました。
ただし、上の推論から行くと、どうして自作本でうまくいっているかが
説明がつかなくなります。
5日目で文字表示ができるようになるようですし、そのときにアドレスを表示して
デバッグしてみようかなと思いますので少々お待ちください。
それと、原因がお分かりの方がいらっしゃいましたら、是非ご教授お願いしますm(_ _)m
ちなみに、func.s中のio_load_eflags関数とio_store_eflags関数で、
pushf命令とpopf命令を使っています。
nasm系列ではpushfd、popfdのようなのですが、GASではどうやら
pushf、popfらしいです。