「OS自作入門 四日目」の編集履歴(バックアップ)一覧はこちら
OS自作入門 四日目 - (2007/07/02 (月) 09:34:31) の最新版との変更点
追加された行は緑色になります。
削除された行は赤色になります。
*OS自作入門四日目のまとめ
自分のためのまとめなので、他の人には意味不かも。
**アセンブラ
[INSTRSET "i486p"] ; 486の命令まで使いたいという記述
**C言語
:&(AND) | かつ。and演算。それぞれの桁について比較して、両方が1だったら1、どちらかが0なら0。
0100 AND 1101 -> 0100
: (OR) | または。or演算。それぞれの桁について比較して、どちらかが1だったら1。
0100 OR 1101 -> 1101
:^(XOR) | xor演算。どちらかが0かつもう一方が1のとき1。0かつ0は0。1かつ1は0。ビット反転。
0100 XOR 1101 -> 1001
**C言語からメモリへの書き込み
C言語の関数上で与えられた引数は
1番目[ESP+ 4]
2番目[ESP+ 8]
3番目[ESP+12]
4番目[ESP+16]
...
に書いてある。
**ポインタ
----
*OS自作入門四日目のまとめ
自分のためのまとめなので、他の人には意味不かも。
**アセンブラ
: INSTRSET | どういう意味だろう。
[INSTRSET "i486p"] ; 486の命令まで使いたいという記述
こういう感じで使う。
:RESB num| numの数だけメモリを確保。Reserve Byteの略。他にもRESW,RESD,RESQ,REST が存在し、それぞれワード、ダブルワード、4倍ワード、10バイトワード。
char a[3];
とすると、アセンブラでは
a:
RESB 3
となる。
**C言語
:&(AND) | かつ。and演算。それぞれの桁について比較して、両方が1だったら1、どちらかが0なら0。
0100 AND 1101 -> 0100
: (OR) | または。or演算。それぞれの桁について比較して、どちらかが1だったら1。
0100 OR 1101 -> 1101
:^(XOR) | xor演算。どちらかが0かつもう一方が1のとき1。0かつ0は0。1かつ1は0。ビット反転。
0100 XOR 1101 -> 1001
**C言語からメモリへの書き込み
C言語の関数上で与えられた引数は
1番目[ESP+ 4]
2番目[ESP+ 8]
3番目[ESP+12]
4番目[ESP+16]
...
に書いてある。
**ポインタ
int i;
char *p;
p = (char *) i;
*p = i & 0x0f;
変数iを宣言。
ポインタ用の変数pを宣言。
ポインタ用の変数pにポインタ変数にキャストしたiを代入。
p番地にiを0x0fでandをとった値を代入。
番地は以下の様に指定することが可能。
*(p + i)
*(i + p)
p[i]
i[p]
これらは全て番地の足し算。
**色
8bitカラーモードでは0〜255の色番号の色の内16色を使うことができる。色番号は0x000000-0xffffffで、その設定にはまずパレットを設定する。パレットの設定には16進数2桁(=8bit)を3つ用いる。
このようにパレットを設定する。
void init_palette(void)
{
static unsigned char table_rgd[16*3] = {
0x00, 0x00, 0x00, /*0;:黒*/
...
}
これを16個指定する。
のだが、パレットを設定する関数で、
io_out(0x03c9,rgb[0]/4);
とやっているのが気になる。4で割っているということは、2ビット右にシフトするということなので、
もともと8ビットだったデータを6ビットにして送信しているということになる。
0xffという値があるのだが、結局輝度情報に8ビット全てを使っているのでシフトすると設定しようとした色によっては
色情報に誤差というか変な値が入る可能性があり得る。よくわからん。
**その他
:static宣言 | 変数宣言の前にstaticと付けると、RESBの代わりにDB命令でメモリを確保する。 ここでは3×16個も代入が存在するので、代入命令の数を抑えるために使われている。static宣言したことで、ここでは
table_rgb:
RESB 16*3
以下代入命令...
とならずに
table_rgb:
DB 0x00, 0x00, 0x00, 0xff, ...
となっている。(んじゃないのかなぁと思う。)
:unsigned宣言 | 変数宣言の前にunsignedを付けると符号のない数(=0か正)として扱う。
charにはunsigned,signed,その他があり、signedは正と負を両方扱う。その他はコンパイラ依存になる。
**パレット
パレットのアクセスの手順
-まず一連のアクセス中に割り込みなどが入らないようにする(たとえばCLI)。
-0x03c8に設定したいパレット番号を書き込み、続いて、R、G、Bの順に0x03c9に書き込む。もし次のパレットも続けて設定したいのなら、パレット番号の設定を省略して、さらにRGBの順に0x03c9に書き込んでよい。
-現在のパレット状態を読み出すときは、まず0x03c7にパレット番号を書き込んで、0x03c9を3回読み出す。これが順にR、G、Bになっている。これももし次のパレットも読み出したいときは、パレット番号の設定を省略してRGBの順に読み出してよい。
-最初にCLIした場合は、最後にSTIする。
:CLI| clear interupt flag.割り込みフラグを初期化。割り込み禁止にする。
:STI| set interupt flag.割り込みフラグをセット。割り込み可能にする。
これらはC言語では記述できないのでアセンブラで記述する。
**io_out8
8バイト書き出す関数。naskfunc.nasに書かれている。
_io_out8: ;void io_out8(int port, int data);
MOV EDX,[ESP+4]
MOV AL, [ESP+8]
OUT DL,AX
RET
となっており、port番号をDL(EDXの下位8ビット)に格納、dataをALに格納。最後にOUT命令で出力。OUT命令は入出力デバイスにコマンドを送る命令。
**EFLAGS
32ビットのレジスタ。割り込みフラグやキャリーフラグビットが存在する。EFLAGSのやりとりは1命令ではできず、スタックを使って行う。
_io_load_eflags ;int io_load_eflags(void)
PUSHFD ;PUSH EFLAGSということ
POP EAX ;これでEAXに保存
RET
_io_store_eflags ;void io_store_eflags(int eflags)
MOV EAX,[ESP+4]
PUSH EAX
POPFD ;POP EFLAGSということ。これでEAXの値をEFLAGSに保存。
RET
**VRAM
320×200の画面での各画素とアドレスの対応関係は、左上を(0,0)右下を(319,199)とすると
0xa0000 + x + y * 3220
として計算される。他の画面モードにおいてもyにかける値が変わるくらい。こうして計算した番地に色番号を記憶させることで画面を表示する。いちおうどんな線でもこれで描画することができる。
----