6日目 分割コンパイルと割り込み処理
久しぶりにやる。
1. ソースファイル分割
2. Makefileの整理
3. ヘッダファイル整備
割愛
4. やり残した説明
load_gdtr関数
新たに追加したload_gdtr関数は、指定されたリミットとアドレスをGDTRという48ビットのレジスタに代入する関数。
代入の際は、LGDT命令を使用して、メモリのアドレスを指定するとそこから6 バイト読み込んでGDTRに代入してくれる。
GDTRの下位2バイトはリミットを表していて、残りの4バイトがGDTが置いてあるアドレスを表している。
IDTRも大体同じ。
set_segmdesc関数
これはセグメントの情報をCPUの仕様にそって8バイトにまとめて書き込む関数。
-
セグメントの大きさはどのくらいか?
-
セグメントがどの番地から始まるか?
-
セグメントの管理用属性(書き込み禁止・実行禁止・システム専用など)
これを8バイトにまとめて書き込む。
リミットの大きさは最大で4GB(4GBのメモリを好きなように分割するのがセグメントなので)。
その大きさを表す数値は32ビットの情報量がいるのだが、全部で8バイトにして書き込むため、その半分も使用するのは頂けない。
さて、ここでリミットは20ビットしか用意されていない。これでは1MBまでしか指定できない、と思うじゃん?
セグメントの属性にGビットフラグというものがあり、これを立てるとリミットの単位をバイト→ページに切り替えてくれる。
1ページは4KBのことなので、1Mx4KB = 4GBで、4GB無事に指定することができる。
limit_low とlimit_high にリミット情報を書き込む。
セグメントのアドレスは、ベースアドレスと呼ばれて32ビット分の情報をbase_low, base_mid, base_high に書き込む。
セグメントの属性は12ビット分で書き込み、読み書き可能か?システム専用か?アプリケーション専用か?などの属性を与える。
システム専用に指定されたセグメントはOSなど管理する側のプログラムが走るモードの時に動き、アプリケーション専用に指定されたセグメントは管理される側のプログラムが走るモードの時に動く。
5. PIC初期化
PICとは、Programmable Interrupt Controllerの略で、設定可能な割り込みコントローラということ。
CPUは単独では1つの割り込みしか扱えない設計になっており、それでは困るので基盤に付けられた補助チップがPIC。
PICは8個の割り込み信号(IRQ)を1つの割り込みにまとめる装置で、どれか一つでも割り込みが来たら一つだけ出ている出力が1になってCPUにお知らせしてくれる。
PICはCPUから見ると外部装置なのでCPUからはOUT命令を使って操作する。
IMR
IMRはInterrupt Mask Registerの略で、割り込み目隠しレジスタという。このビットが1になっているIQR信号は、無視される。
ICW
ICWはInitial Control Wordの略で、初期化制御データという。
ICWは4つあって、合計4バイトのデータになる。ICW1とICW4は決められた値を入れる。
ICW3も決められた値を入れる。
設定するのは、ICW2だけで、ここではIRQをどの割り込み番号としてCPUに通知するか決める。
6. 割り込みハンドラ作成
マウスはIRQ12、キーボードはIRQ1なのでINT 0x2cとINT 0x21 用の割り込み受付プログラムを作成。
アセンブラの新しい命令
PUSH:スタックに値を入れる
POP:スタックから値を取り出す
CALL:関数を呼び出す命令
あとは関数をIDTに登録すれば良い。
いえーい。マウスは赤色。