Personal tools
You are here: Home ブログ 学習経過 カーネル(その1)
« December 2010 »
Su Mo Tu We Th Fr Sa
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31  
Recent entries
sysfs tips 02 ohyama 2010-09-09
sysfs tips ohyama 2010-09-02
Haskell で周波数スペクトルを得る ohyama 2010-07-29
Haskell で線形識別関数の学習を行う ohyama 2010-07-19
Haskell で逆行列を求める ohyama 2010-07-16
Recent comments
Re:vim に lisp 機能をつける t.mimori 2010-12-16
Re:Haskell で周波数スペクトルを得る H.OHYAMA 2010-08-01
Re:lkml でお勉強 (その1-1) Hiroyasu OHYAMA 2009-08-21
Re:lkml でお勉強 (その1-1) kosaki 2009-08-20
Re:vim に lisp 機能をつける ohyama 2008-05-08
Categories
学習経過
GNU/Linux
 
Document Actions

カーネル(その1)

前回まででプロテクトモードに移るまでの話をした。
今回からはここからブートされるプログラム、つまりカーネルについての話を始める。今回話をする主な項目は次の 3 つ。

・カーネルの呼び出しの話
・画面出力の話
・IDT の設定とキー割り込みの話

尚、ソースはこちら


・カーネルの呼び出しの話
リアルモードのセットアップルーチン (second.bin) から、32-bit プロテクトモードで動作するプログラム (stage3.bin) を呼び出す。
具体的には、ブートプログラム (boot.bin) 内部において、stage3.bin のプログラムを second.bin の直後に配置するようにする。これを実現させるために、Makefile 内部でセットアッププログラムのサイズを固定的に扱う事になるのだが、セットアップルーチンのサイズがコロコロ変わる事は早々無いと思うので、この方針で話を進める。

まずは、stage3.S で書かれたプログラムへ飛為、ljmp を実行する。指定するアドレスは、second.bin の次のセクタから始まる stage3.bin の先頭アドレスである。

しかし stage3.bin をリンクする際、リンカスクリプトで .text セクションの開始位置をリニアアドレスに展開される位置に修正しないと、カーネルで指定したラベルはリンカによって全て 0 をベースとしたオフセットに変換される。これにより、文字列の操作はおろか、プログラムのコールすら出来なくなる(又、それを行う為には、いちいちアドレス変換をプログラム側で行わなければならなくなる)。
なので、stage3 の .text セクションの開始アドレスを、次のようにリンカスクリプトでセットアッププログラムが終わる次のセクタのアドレス (0x90600) に指定している。

SECTIONS{
. = 0x90600;
.text : {*(.text)}
.rodata : {*(.rodata)}
.data : {*(.data)}
.bss : {*(.bss)}
}


・画面出力の話
プロテクトモードにおいては、BIOSコールを使った画面出力が行えないので、以前(ブートローダー(その7))に詳しく話をした VRAM を使った画面出力を行う。
VRAM による画面出力は、0x000b8000 から始まる 4000 byte の予約領域への書き込みによって実現可能なのだが、改行やら、カーソルが画面の端に存在した時の事を考慮すると結構めんどくさい(このアルゴリズムについては、sodex の画面出力機構の一部を拝借した)。
最もプリミティブな処理は、stage3.S の _poscolor_printc で行っている。

・IDT の設定とキー割り込みの話
割り込みベクタのベースアドレスを 0x20 に設定したので、IRQ N の割り込みは、ベクタ 0x20+n に登録されたサービスルーチンが実行される。
ここでは、以前と同様にタイマ割り込みとキーボード割り込みを登録する。ここでは、サービスルーチンにおいてページフォルトの一般例外を許可する為に、トラップゲートのディスクリプタに登録する。又サービスルーチンを実行するセグメント領域は、カーネルのコードセグメントを指定。
サービスルーチンの実行順序は、irr レジスタに割り込み要求が入り、isr レジスタに実行中の irq 番号が登録される。次の割り込みを許可する為に、プログラム側で、pic に対して割り込み終了を通告し、対象 irq における isr レジスタの修正(クリア)を行う。
又、割り込みが ps/2 キーボードからの割り込み (key_service_routine [stage3.S]) の場合、割り込みが発生すると 8042 キーコントローラのモードレジスタからキー情報を取得しないと、次の割り込みが発生しない。
モードレジスタは 8bit のレジスタで、下位 7 bit に押されたキーの情報が入っており、最上位ビットでキーが押された (make された) かキーが離された (break された) かを判定している。シフトやメタキーなどの制御の実装ができるまで、break 情報を無視する事にする。
更に厄介な事が、モードレジスタの下位7bit に入っている入力キーの情報は、qwerty 配列のキーボードの左上(Esc) から順に通し番号が振られているので、これを効率的に扱う為に、ASCII コードへの変換を行っている(__convert_keynum() [vga.c])。

Category(s)
学習経過
The URL to Trackback this entry is:
http://dev.ariel-networks.com/Members/ohyama/30ab30fc30cd30eb-305d306e1/tbping
Add comment

You can add a comment by filling out the form below. Plain text formatting.

(Required)
(Required)
(Required)
(Required)
(Required)
This helps us prevent automated spamming.
Captcha Image


Copyright(C) 2001 - 2006 Ariel Networks, Inc. All rights reserved.