2009年5月20日 (水)

OS自作のための勉強について

長い間ブログを書いていませんでしたが、その間、

いろいろ脱線していました。

というのも、OS自作入門を読んでいてハードウェアの内容を知りたくなり、

以下の本を読みました。

CPUの創り方とゼロから学ぶ電子回路です。

CPUの創り方はとても面白かったです。

この本を読めば、CPUがどのようにプログラムを

実行していくかが、良く分かります。

CPUやマイコンを理解する基本となるプログラムカウンタやレジスタ、

ROM、加算器、命令デコーダの役割や、それらを簡単な電子部品で

どういうふうに作れば良いか丁寧に書いてあります。

また簡単なアセンブリ言語やハンドアセンブルを学ぶことも出来ます。

その他には発振回路やリセット回路の作り方も書いてあります。

また、ゼロから学ぶ電子回路では、

トランジスタ、アンプに関する知識やMOSFETに関する知識が

分かり、NOTやNAND等の論理回路をMOSFETで構成する

方法が簡単に書いてありました。

これらの本を読んでから、OS自作入門を

読み直していますが、今まで自分がまだ

分かっていなかった部分があったことが

良く分かりました。

ちなみに、CPUの創り方では、実際に自分でCPU(TD4という名前)を

作る事が出来るのですが、自分はまだ作っていません。

実際に作ると、更にいろいろなこと(自作の大変さ)が分かるようですが、

とりあえずOS自作の方に戻ろうかな。

2008年8月31日 (日)

OS自作入門の復習

3日目の第一章のプログラムharib00aを基に
自分なりに改造しています。ただし、基本的には
本書の内容にそって、各種のファイル等を自分で
打ち込んでいるだけですが・・・
今日は、その内容をまとめたので書いてみたいと思います。

改造内容

その1
ipl.nasを改造し、フロッピーディスク(FP)のデータの読み込みが
終わったら、終わったことが分かるように、DOS画面にメッセージを
出すようにしました。
INT0x10という一文字表示関数を使っています。

その2
FPの18セクタ読み込み出来るように改造。

ただし、第二章のエラー5回までという内容は
入っていない。したがってキャリーフラグがエラーの
時だけ、エラー表示が出る。つまりフロッピーディスクが
粗悪品で読み込みがうまくいかない場合、止まってしまう。

その3
haribote.nasという新しいファイルを追加。
これがOSの本体になる。今のところhlt命令のみ書いてある。

Makefileの内容も上に合わせて変更。
haribote.imgをiplmas.nasとharibote.nasを合わせて作るようにする。

その4
画面モードをVGAグラフィックス、320×200、8bitカラーモードに
変更した為、OS本体であるharibote.nasの方に、このカラー画面で
文字を表示させるプログラムを追加した。(DOS画面上ではなくて・・・)
文字表示は、INT0x10関数を使用しており、ここまでは16ビットモードである。

その5
P61の32ビットモードになると、BIOSが使えない為、
プログラムは大幅変更になる。なので、改造はここで終了する。

つもりだったが、今後の勉強のため自力で32ビットモードに移行する。

まず、カラー画面での文字表示は、32ビットモードだと使えない為、
やめた。
というのは、INT0x10はBIOSの関数であり、16ビットモード用の機械語で
ある為です。
haribote.nasをasmheadmas.nasとbootpack.cに分け、
bootpack.cは新規で作成した。bootpack.cには、まだ、hlt命令しかなく、
しかもそのhlt命令はC言語では書けない為、
アセンブリ言語で別ファイルに書いています。

Makefileをharib00i(P63)を参考に変更した。具体的にはharibote.nasが
二つのファイルに分かれる為、各種の生成規則を追加した。
ここで注意すべきは、iplとasmheadはそれぞれiplmasとasmheadmasという
名前に変えてある。

また、harib00jを参考に、naskfunc.nasを新規に作成した。
nasukfun.nasは、C言語では書けない命令をアセンブリ言語で
書く為です。hlt命令を書いてあります。

その6
真っ黒な画面を白あるいはしましま模様に変える為、
bootpack.cにVRAM a0000に数字を書き込む
関数write-mem8を追加した。
当然naskfunk.nasにMOV命令を使った
write-mem8の中身を書いた。

その7
上の内容は、ポインタを使えばVRAMに数値を書き込むことが
出来るので、ポインタを使って、bootpack.cを変更した。(P77)

とりあえず今回はここまでです。

2008年8月10日 (日)

ひさしぶりのOS自作入門

最近は、いろいろ忙しくてOS自作入門を

進めることが出来ませんでした。

しかし、いまは夏休みなので、また再開です。

すっかり内容を忘れているので、一から

やり直していますが、いま3日目です。

8bitカラーモード画面で、文字表示をさせる

改造をしました。

Chapter3 おもしろいなー。

2008年4月 5日 (土)

OS自作入門の3日目再読み返し

今日は、3日目の読み直しをしたときに
ひっかかった所について、書きます。

以前に読んでいた時は、問題なく理解出来ていたと
思うのですが、久しぶりに読んだせいか、
INT 0x13の所でひっかかりました。
なので、ここに覚え書きしたいと思います。

①INT 0x13は1セクタ毎に読み込む。
②ES(エクストラセグメント)を0x20だけ増やしているのは、
 1セクタが512バイトであり、ESは16倍されて
 読み書きする位置を指定する為、512/16=0x20である為。

これで忘れないぞー。

2008年3月15日 (土)

OS自作入門読み返し(再)

一時、他の勉強で時間があいてしまい、

すっかりOS自作入門の内容を忘れてしまったので、

もういちど最初からおさらいをしています。

1日目
hello,worldという文字を表示させるプログラムを
アセンブラで作成し、それをイメージファイルとして、
フロッピーディスクに書き込み、それを実際に
起動させる。

フロッピーディスクの1セクタ目、すなわちブートセクタに
上のプログラムを書き込むことによって、文字を
表示させる。

2日目
プログラムを更にコマンドを使って、
人間が読みやすくします。

1日目で数字の並びだったプログラム本体の内容を
コマンドで書き直していきます。

ここで、レジスタ、メモリの意味や条件分岐、割り込み命令など、
今後の基本となる部分が多く出てきます。

3日目
ブートセクタ以降のディスクのデータの読み込みを行います。
ディスク読み込み命令を使います。

ここで、簡単にフロッピーディスクの構造についても
知ることが出来ます。

また、ついにOS本体を作り始めます。
ブートセクタの最後に、OS本体にジャンプする命令を
入れることで、OS本体を起動させます。

ここでOSがやっているのは、画面を黒く表示させることです。

また、最後に32ビットモードへの移行と、C言語を使用可能に
する基礎を作ります。

ちょっとずつ思い出してきたなー。

2008年1月 9日 (水)

OS自作入門の13日目

OS自作入門を久しぶりに見たら、

かなり内容を忘れていました。

また、一度初めから読み返さないとな~。

お正月に進めるつもりでしたが、他の

勉強で終わってしまいました。

今、仕事の関係で、材料力学やら

何やらいろいろ勉強しています。

2007年12月 2日 (日)

OS自作入門の13日目その1

OS自作入門の13日目その1です。

初版第六刷のP250から252までです。

やっと13日目のその1です。

でもなんだか内容を忘れてきてしまってたりして。。

それでは、勉強を始めます。

①文字を書く部分を一つの関数にまとめる。
下記のような部分が4箇所出てくるので、
それを一つの関数にまとめ、プログラム数を減らします。

  boxfill8(buf_win, 160, COL8_C6C6C6, 40, 28, 119, 43);
putfonts8_asc(buf_win, 160, 40, 28, COL8_000000, s);
sheet_refresh(sht_win, 40, 28, 120, 44);

              ↓

void putfont8_asc_sht(struct SHEET *sht,int x,int y,int c,int b,char *s,int l)
{
boxfill8(sht->buf,sht->bxsize,b,x,y,x+l*8-1,y+15);
putfont8_asc(sht->buf,sht->bxsize,x,y,c,s);
sheet_refresh(sht,x,y,x+l*8,y+16);
return;
}

結果的に2行減ります。

②長ーいif分を省略
HariMainの中に、キーボード、マウス、タイマバッファへの書き込みが
あるかないかを判断する条件式がありますが、タイマを増やした時に
面倒くさい事になります。(下記)

if (fifo8_status(&keyfifo) + fifo8_status(&mousefifo) + fifo8_status(&timerfifo)
    + fifo8_status(&timerfifo2) + fifo8_status(&timerfifo3) == 0)

そこで、タイマ用のバッファを一つにまとめます。
すると上の式が、

if (fifo8_status(&keyfifo) + fifo8_status(&mousefifo) +
   fifo8_status(&timerfifo) == 0)

にまとまります。
この時に、どのタイマが終わったかどうかは、
HariMainの中で、

i=fifo8_get(&timerfifo)

で、各タイマのdataを受け取って、その情報を元に
どのタイマが終わったかを判断し、例えば"10[sec]"というふうに
表示します。

今日はここまでです。
次は、性能の測定です!

2007年10月14日 (日)

OS自作入門の12日目その4

OS自作入門の12日目その4です。

P244から249までです。(初版第6刷)

やっと12日目も終わりそうです。
ここ最近は、進み具合がちょっと
遅くなっていますが、少しずつでも
進めて行きたいと思います。

①高速化(P244~245)
割り込みハンドラinthandler20の中のif文を
高速化しました。

タイマーがいくつかセットされても、
タイムアウトに一番近い物のみ監視する事に
しました。

変更点
1.構造体TIMERCTLにtimerctrl.next変数を追加しました。

2.timer.cファイルにあるtimer_settimeにif文を追加しました。
 ここでタイマー時間をセットする時に
 timerctrl.next > timer->timeoutであれば、
 つまりこの時セットした時間timeoutが、
 今nextとして設定されている時間より小さければ
 timerctrl.nextを入れ替えます。

3.inthandler20の最初の方にif文を追加しました。
 if (timerctrl.next > timerctrl.count) {
      return;
  }
  で、時刻がnextを超えない時は、return文で
 戻るようにしています。

②高速化2(P246~249)
下敷きを設定した時のように、タイマもタイムアウト時間の
小さい順に並べます。

実際には、timer_settime関数の中でタイマアウト時間が
小さい順に並べています。

if (timerctl.timers[i]->timeout >= timer->timeout)
で新しく登録しようとしているタイマのタイムアウト時間
timer->timeoutが、すでに登録されているタイマの
タイムアウト時間timerctl.timers[i]->timeoutより
小さい場合に、それ以降のタイムアウト時間を後ろに
ずらして、間に入れます。
(文章にすると分かりにくいですね。きっと)

そして、inthandler20割り込みハンドラの中では、
if (timerctl.timers[i]->timeout > timerctl.count)
という条件文を使って、timerctl.count時間より
小さいタイマを全て、fifo8_put関数で、fifoバッファに
書き出しています。(下記参照)

void inthandler20(int *esp)
{
  中略
for (i = 0; i < timerctl.using; i++) {
  /* timersのタイマは全て動作中のものなので、flagsを確認しない */
  if (timerctl.timers[i]->timeout > timerctl.count) {
   break;
  }
  /* タイムアウト */
  timerctl.timers[i]->flags = TIMER_FLAGS_ALLOC;
  fifo8_put(timerctl.timers[i]->fifo, timerctl.timers[i]->data);
}
  後略
}

その後、上記でタイムアウトしたタイマの分を、
timerctl.timers[]の中で前にずらしています。

12日目も結構難しかったです。何度も本文とプログラムを
読んで何とか分かるようになりました。

さあ、次は13日目だー。どんな内容かなー?

2007年9月22日 (土)

OS自作入門の12日目その3

OS自作入門の12日目その3です。

P239から244までです。

前回、バックグラウンド上に、10secを表示させましたが、
今回は、それを複数表示させるように改造しました。

具体的には、timerfifo2、3やtimerbuf2、3、timer2、3を追加しました。

ここでちょっとtimer.cの関数を整理します。

init_pit :PITの初期化つまり割り込み周期を設定する。

timer_alloc :タイマ変数を確保状態にします。
       つまりその変数をこれから使うってことですね。

timer_free :タイマ変数を未使用にします。つまり、この変数を
       また使える状態になったということです。

timer_init :タイマ変数に初期値を入れます。

timer_settime :タイムアウト時間を設定します。

inthandler20 :タイムアウト時間になったら、fifoバッファに
        timer_initで設定したデータを送ります。

また、割り込み処理での無駄があるので、それも省いています。
これまでtimeoutという変数を使って、カウントダウン式に
タイムアウト時間を見ていましたが、timerctl.countという変数を
絶対時間のようにして、カウントダウン式を止めました。

それにより引き算をという無駄を省いています。

なかなか12日目も終わらないけど、がんばるぞー。

2007年9月15日 (土)

OS自作入門の12日目その1

OS自作入門の12日目その1です。

P231からです。やっと3分の1を超えてきたなー。

・割り込み頻度の設定

8254というタイマの初期値を設定して、
割り込み頻度を決めます。

初期値の設定には、CPU外部への命令になるので、
io_out命令を使います。

実際に設定する初期値は、カウント値です。というのも、

割り込み頻度=クロック数/カウント値

で割り込み頻度を決められるからです。

ちなみに、

AT互換機でのクロック数 :1.19318MHz

なので、カウント値を11932とした場合、
1.19318×1000000/11932=100回/秒となります。

このタイマは、IRQの0番につながっているので、
IRQ0の割り込み頻度を設定しています。

あとは、11目にウィンドウを出したように、

カウンタを画面に表示させます。

カウンタが動いたぞー。

Ws000009

より以前の記事一覧