OS自作入門 onLinux 4日目

1d715984.png

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を外すと動作しました。
以下、自分なりの考察です。



mem01.png
table_rgbは初期値付きの静的配列です。
.bssセクションに配置されます。
ここでは、仮にファイル先頭からの.bss
オフセットを0x0140とします。


さて、boot.cはコンパイルしてboot.oというオブジェクトファイルになり、
func.sをアセンブルしたオブジェクトファイルfunc.oとldでリンクされてboot.binになります。
リンク時に、変数のオフセットが計算されて、静的変数の場合はバイナリ中に書き込まれます。

この後、boot.binはhead.binの後ろにくっつけられます。

mem02.png
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らしいです。