0から作るソフトウェア開発
日々勉強中。。。 |
Follow @Nina_Petipa |
0から作るOS開発 カーネルローダその3 プロテクティッドモードへの移行とA20 |
CR0レジスタ | ||
---|---|---|
ビット | ビット名称 | 説明 |
0 | PE | Protection Enableビット。このビットをONにするとプロテクティッドモードへ移行します |
1 | MP |
Monitor Co-Processorビット。モニタ・コプロセッサビット WAIT命令を実行したときの動作を変更することができます 0:TSビットが0でも1でも関係なく無視する 1:TSビットが1であればコプロセッサ使用不可能例外を発生させる |
2 | EM |
Emulationビット。エミュレーションビット 浮動小数点演算(x87 FPU)命令を実行したときの動作を変更することができます 0:x87 FPUを持っているので命令実行可能 1:命令実行時x87 FPUを持っていないのでコプロセッサ使用不可例外が発生する ソフトウェアによってエミュレーションを行う ※細かい条件はIntelのCPU仕様書をご確認ください |
3 | TS |
Task Switchビット。タスクスイッチビット CPUはタスクスイッチする時にこのビットを1にします ※EM、MPビットの設定によっては影響があります |
4 | ET |
Extended Typeビット。拡張タイプビット 0:80287以前のCPU 1:80387以後のCPU |
5 | NE |
数値演算エラービット 0:x87 FPUエラーレポート無効 1:x87 FPUエラーレポート有効 |
16 | WP |
Write Protectビット。書き込み保護ビット 0:リング0のプログラムが読み取り専用のユーザ空間に書き込むことができる 1:リング0のプログラムが読み取り専用のユーザ空間に書き込むことを禁止 |
18 | AM |
Alignment Maskビット。アライメントマスクビット 0:自動アライメントチェック無効 1:自動アライメントチェック有効 |
29 | NW |
Not Write throughビット。ノットライトスルービット 0:CDビットが0の場合キャッシュをライトバックまたはライトスルーが有効 1:CDビットとNWビットの組み合わせはCPUのマニュアル10-17ページを参照ください |
30 | CD |
Cache Disableビット。キャッシュ無効ビット 0:NWビットが0の場合キャッシュ操作が有効 1:CDビットとNWビットの組み合わせはCPUのマニュアル10-17ページを参照ください |
31 | PG |
PaGingビット。ページングビット 0:ページング無効 1:ページング有効 ページングについては仮想メモリ管理にて後述します |
MOV EAX, CR0 ; CR0レジスタの値を読み出します
OR EAX, 0x00000001 ; PEビットをOR命令でONします
MOV CR0, EAX ; そのままCR0に書き込みます
MOV CS, 0x08 ; Nullディスクリプタを選択している状態なのでN.G.
MOV DS, 0x10 ; Nullディスクリプタを選択している状態なのでN.G.
MOV EAX, CR0 ; CR0レジスタの値を読み出します
OR EAX, 0x00000001 ; PEビットをOR命令でONします
MOV CR0, EAX ; そのままCR0に書き込みます
JMP CODE_DESC:Pmode_start ; CODE_DESCは0x08が入っています
;/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ ; ; Starting Protected Mode ; ;/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
[BITS 32] Pmode_start: MOV AX, DATA_DESC ; DATA_DESCには0x10が入っています MOV SS, AX ; 以下データセグメントセレクタを入れています MOV ES, AX MOV FS, AX MOV GS, AX MOV DS, AX MOV ESP, 90000h ; スタックポインタも初期化します
[BITS 32]
MOV AX, DATA_DESC ; DATA_DESCには0x10が入っています
MOV SS, AX ; 以下データセグメントセレクタを入れています
MOV ES, AX
MOV FS, AX
MOV GS, AX
MOV DS, AX
MOV ESP, 90000h ; スタックポインタも初期化します
I/Oデバイスのポートアドレスマップ | |||||
---|---|---|---|---|---|
アドレス範囲 |
下位4バイト 0x0-0x3 |
中下位4バイト 0x4-0x7 |
中上位4バイト 0x8-0xB |
上位4バイト 0xC-0xF |
|
0x0000-0x000F | DMAコントローラ チャンネル0-3 | ||||
0x010-0x00F | - | ||||
0x020-0x02F | PICマスタ | - | |||
0x030-0x03F | - | ||||
0x040-0x04F | PIT | - | |||
0x050-0x05F | - | ||||
0x060-0x06F |
キーボード・マウス(0x60) スピーカ(0x61) |
キーボード・マウス(0x64) | - | ||
0x070-0x07F |
RTC(0x70:ビット0-6) NMI(0x70:ビット7) RTC(0x71) |
- | |||
0x080-0x08F | DMAページレジスタ0-2(0x81-0x83) | DMAページレジスタ3(0x87) | DMAページレジスタ4-6(0x89-0x8B) | DMAページレジスタ7(0x8F) | |
0x090-0x09F | - | ||||
0x0A0-0x0AF | PICスレーブ(0xA0-0xA1) | - | |||
0x0B0-0x0BF | - | ||||
0x0C0-0x0CF | DMAコントローラ チャンネル4-7(0xC0-0xDF)、1-16バイト | ||||
0x0D0-0x0DF | DMAコントローラ チャンネル4-7(0xC0-0xDF)、16-32バイト | ||||
0x0E0-0x0EF | - | ||||
0x0F0-0x0FF | フローティングポイントユニット(FPU/NPU/Math Coprocessor) | ||||
0x100-0x10F | - | ||||
0x110-0x11F | - | ||||
0x120-0x12F | - | ||||
0x130-0x13F | SCSIホストアダプタ(0x130-0x14F)、バイト1-16 | ||||
0x140-0x14F |
SCSIホストアダプタ(0x130-0x14F) バイト17-32 |
SCSIホストアダプタ(0x140-0x15F) バイト1-16 |
|||
0x150-0x15F | SCSIホストアダプタ(0x140-0x15F)、バイト17-32 | ||||
0x160-0x16F | - |
クワンタネリ(4番目の)IDEコントローラ マスタドライブ |
|||
0x170-0x17F |
セカンダリ(2番目の)IDEコントローラ マスタドライブ |
- | |||
0x180-0x18F | - | ||||
0x190-0x19F | - | ||||
0x1A0-0x1AF | - | ||||
0x1B0-0x1BF | - | ||||
0x1C0-0x1CF | - | ||||
0x1D0-0x1DF | - | ||||
0x1E0-0x1EF | - |
ターシェリ(3番目の)IDEコントローラ マスタドライブ |
|||
0x1F0-0x1FF |
プライマリ(1番目の)IDEコントローラ マスタドライブ |
- | |||
0x200-0x20F | ジョイスティックポート | - | |||
0x210-0x21F | - | ||||
0x220-0x22F | サウンドカード | ||||
SCSIホストアダプタ(0x220-0x23F)、バイト1-16 | |||||
0x230-0x23F | SCSIホストアダプタ(0x220-0x23F)、バイト17-32 | ||||
0x240-0x24F | サウンドカード | ||||
ネットワークカード(NE2000以外) | - | ||||
NE2000ネットワークカード(0x240-0x25F)、バイト1-16 | |||||
0x250-0x25F | NE2000ネットワークカード(0x240-0x25F)、バイト1-16 | ||||
0x260-0x26F | サウンドカード | ||||
ネットワークカード(NE2000以外) | - | ||||
NE2000ネットワークカード(0x260-0x27F)、バイト1-16 | |||||
0x270-0x27F | - | プラグ・アンド・プレイシステムデバイス | LPT2(パラレルポート2) | ||
- | LPT3(パラレルポート3) | ||||
NE2000ネットワークカード(0x260-0x27F)、バイト17-32 | |||||
0x280-0x28F | サウンドカード | ||||
ネットワークカード(NE2000以外) | - | ||||
NE2000ネットワークカード(0x280-0x29F)、バイト1-16 | |||||
0x290-0x29F | NE2000ネットワークカード(0x280-0x29F)、バイト17-32 | ||||
0x2A0-0x2AF | ネットワークカード(NE2000以外) | - | |||
NE2000ネットワークカード(0x2A0-0x2BF)、バイト1-16 | |||||
0x2B0-0x2BF | NE2000ネットワークカード(0x2A0-0x2BF)、バイト17-32 | ||||
0x2C0-0x2CF | - | ||||
0x2D0-0x2DF | - | ||||
0x2E0-0x2EF | - | COM4(シリアルポート4) | |||
0x2F0-0x2FF | - | COM2(シリアルポート2) | |||
0x300-0x30F |
サウンドカード/ MIDIポート(0x300-0x301) |
- | |||
ネットワークカード(NE2000以外) | - | ||||
NE2000ネットワークカード(0x300-0x31F)、バイト1-16 | |||||
0x310-0x31F | NE2000ネットワークカード(0x300-0x31F)、バイト17-32 | ||||
0x320-0x32F |
サウンドカード/ MIDIポート(0x320-0x321) |
- | |||
NE2000ネットワークカード(0x320-0x33F)、バイト1-16 | |||||
PC/XTハードディスクコントローラ | - | ||||
0x330-0x33F |
サウンドカード/ MIDIポート(0x330-0x331) |
- | |||
NE2000ネットワークカード(0x320-0x33F)、バイト17-32 | |||||
SCSIホストアダプタ(0x330-0x34F)、バイト1-16 | |||||
0x340-0x34F | SCSIホストアダプタ(0x330-0x34F)、バイト17-32 | ||||
SCSIホストアダプタ(0x340-0x35F)、バイト1-16 | |||||
ネットワークカード(NE2000以外) | - | ||||
NE2000ネットワークカード(0x340-0x35F)、バイト1-16 | |||||
0x350-0x35F | SCSIホストアダプタ(0x340-0x35F)、バイト17-32 | ||||
NE2000ネットワークカード(0x340-0x35F)、バイト17-32 | |||||
0x360-0x36F | テープアクセラレータカード(0x360) | - |
クワンタネリ(4番目の)IDEコントローラ スレイブドライブ |
||
ネットワークカード(NE2000以外) | |||||
NE2000ネットワークカード(0x360-0x37F)、バイト1-16 | |||||
0x370-0x37F | テープアクセラレータカード(0x370) |
セカンダリ(2番目の)IDEコントローラ スレイブドライブ |
LPT1(パラレルポート1) (カラーシステム) |
||
- |
LPT2(パラレルポート2) (モノクロシステム) |
||||
NE2000ネットワークカード(0x360-0x37F)、バイト17-32 | |||||
0x380-0x38F | - |
サウンドカード (FMシンセサイザー) |
- | ||
0x390-0x39F | - | ||||
0x3A0-0x3AF | - | ||||
0x3B0-0x3BF | VGA/モノクロビデオ | ||||
0x3C0-0x3CF | VGA/EGAビデオ | ||||
0x3D0-0x3DF | VGA/CGAビデオ | ||||
0x3E0-0x3EF | テープアクセラレータカード(0x3E0) | - | COM3(シリアルポート3) | ||
- |
ターシェリ(3番目の)IDEコントローラ スレイブドライブ(0x3EE-0x3EF) |
||||
0x3F0-0x3FF | フロッピードライブコントローラ | COM1(シリアルポート1) | |||
テープアクセラレータカード(0x3F0) |
プライマリ(1番目の)IDEコントローラ スレイブドライブ(0x3F6-0x3F7) |
- | |||
0x0400-0x0537 | - | ||||
0x0537-0x0CEF | - | ||||
0x0CF0-0x0CFF | - |
PCI アドレスレジスタ |
PCI データレジスタ |
A20wait:
IN AL, 0x64 ; 0x64のデバイスから読み込み、ALに格納
TEST AL, 0x2 ; ビット1をテスト
JNZ A20wait ; ビット1が0でなければループ
この例では0x64のアドレスを指定して、0x64のデバイス(キーボードコントローラ)から値を読み込みます
MOV AL, 0xAD ; ALレジスタに0xADを格納
OUT 0x64, AL ; ALレジスタの値を0x64のデバイスに書き込み
この例では0x64のアドレスを指定して、0x64のデバイスにALレジスタの値を書き込みますキーボードコントローラのポートアドレス | |||
---|---|---|---|
ポートアドレス | リード/ライト | 名前 | 説明 |
0x060 | リード | リードバッファレジスタ | キーボードコントローラからデータを読み込むレジスタです |
0x060 | ライト | ライトバッファレジスタ | キーボードコントローラにデータを書き込むレジスタです |
0x064 | リード | ステータスレジスタ | キーボードコントローラのステータスを読み込むレジスタです |
0x064 | ライト | 制御コマンドレジスタ | キーボードコントローラに制御するコマンドを書き込むレジスタです |
キーボードコントローラのステータスレジスタ | ||
---|---|---|
ビット | 名前 | 説明 |
ビット0 | アウトプットバッファフル |
0:キーボードコントローラのアウトプットバッファにデータが無いことを意味しています 1:アウトプットバッファにデータが存在していて、まだリードされていない状態です。リードバッファレジスタから値を読み込みとこのビットが0になります |
ビット1 | インプットバッファフル |
0:キーボードコントローラのインプットバッファ(0x060または0x064)が空の状態 1:キーボードコントローラのインプットバッファにデータが書き込まれた状態であるが、まだコントローラが値を読み取っていない状態。コントローラが書き込まれた値を読み取るとこのビットは0になります |
ビット2 | システムフラグ |
制御コマンドを書き込み、コマンドが成功すると、制御コマンドに応じて0または1にセットされます 例えばコントローラの中にはセルフテストが成功したときに1をセットします また、パワーONリセットしたときにはこのビットが0にセットされます |
ビット3 | コマンド/データフラグ |
0:最後に書き込みしたのがデータ(0x060に書き込みをした) 1:最後に書き込みしたのがコマンド(0x064に書き込みをした) |
ビット4 | 禁止(ロック)フラグ |
キーボードコントローラのデータアウトプットバッファにデータが書き込まれるたびに、このビットが更新されます このフラグはキーボードのインヒビット(禁止)キーが押されている状態に1になります インヒビットキーが押されている状態ではキーボードコントローラはキーが押されても何も反応しません 0:インヒビットキーが押されている状態です 1:インヒビットキーが離されている状態です |
ビット5 | 送信(書き込み)タイムアウトフラグ |
0:キーボードコントローラからの送信(書き込み)が完了した状態 1:キーボードコントローラからの送信(書き込み)が完了していない状態。または送信エラーが起こった状態。 ソフトウェアで一定時間タイムアウトを監視します |
ビット6 | 受信(読み込み)タイムアウトフラグ |
0:キーボードコントローラが受信(読み込み)を完了した状態 1:キーボードコントローラが受信(読み込み)を完了していない状態。または受信エラーが起こった状態。 ソフトウェアで一定時間タイムアウトを監視します |
ビット7 | パリティエラー |
0:キーボードコントローラから受信(読み込み)した最後のバイトは奇数パリティ 1:キーボードコントローラから受信(読み込み)した最後のバイトは偶数パリティ キーボードコントローラは通常奇数パリティで送信してきます |
キーボードコントローラの制御コマンド | ||
---|---|---|
コマンド | 名前 | 説明 |
0x20 | キーボードコントローラコマンド読み込み | キーボードコントローラから制御コマンドを読み込みます |
0x60 | キーボードコントローラコマンド書き込み | 制御コマンドをキーボードコントローラに書き込みます。次に0x60にコマンドのデータを書き込みます |
0xAA | セルフテスト | セルフテストを行います |
0xAB | インターフェイステスト | インターフェイステストを行います |
0xAC | 診断情報出力 | 診断情報を出力します |
0xAD | キーボード無効 | キーボードを無効にします |
0xAE | キーボード有効 | キーボードを有効にします |
0xC0 | リードインプットポート | コントローラはインプットポートを読み取った値をアウトプットバッファに書き込みます |
0xD0 | リードアウトプットポート | コントローラはアウトプットポートを読み取った値をアウトプットバッファに書き込みます |
0xD1 | ライトアウトプットポート | コントローラは次に0x60に受信したデータをアウトプットポートに書き込みます |
0xDD | A20アドレスライン有効 |
A20以上のアドレスラインを有効にします ※標準コマンドではないので対応していないコントローラがあります |
0xDF | A20アドレスライン無効 |
A20以上のアドレスラインを無効にします ※標準コマンドではないので対応していないコントローラがあります |
0xE0 | リードテストインプット | TEST0、TEST1ピンの状態を読み取り、アウトプットバッファにデータを書き込みます |
0xFE | システムリセット | キーボードをリセットします |
キーボードコントローラのアウトプットポート | ||
---|---|---|
ビット | 名前 | 説明 |
ビット0 | システムリセット |
0:システムをリセットします 1:システムは通常動作状態 |
ビット1 | A20 |
0:A20以上のアドレスラインを無効 1:A20以上のアドレスラインを有効 |
ビット2-3 | 未使用 | - |
ビット4 | インプットバッファフル |
0:キーボードコントローラのインプットバッファ(0x060または0x064)が空の状態 1:キーボードコントローラのインプットバッファにデータが書き込まれた状態であるが、まだコントローラが値を読み取っていない状態。コントローラが書き込まれた値を読み取るとこのビットは0になります |
ビット5 | アウトプットバッファエンプティ |
0:アウトプットバッファにデータが存在していて、まだリードされていない状態です。リードバッファレジスタから値を読み込みとこのビットが0になります 1:キーボードコントローラのアウトプットバッファにデータが無いことを意味しています |
ビット6 | キーボードクロックライン |
0:キーボードのクロックラインはハイインピーダンス 1:キーボードのクロックラインをLow固定 |
ビット7 | キーボードデータライン |
0:キーボードのデータラインはハイインピーダンス 1:キーボードのデータラインはLow固定 |
MOV AL, 0xD1 ; ライトアウトプットポートコマンドをALレジスタに格納
OUT 0x64, AL ; アドレス0x64にALのデータを送信
MOV AL, 0x02 ; A20を有効にするデータ
OUT 0x60, AL ; 0x60にアウトプットポートに出力したい値を書き込む
MOV AL, 0xD0 ; リードアウトプットポートコマンドをALレジスタに格納
OUT 0x64, AL ; アドレス0x64にALのデータを送信
IN AL, 0x60 ; リードバッファレジスタにアウトプットポートの値が
; 書き込まれるので、読み込む
;/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ ; ; Enable A20 ; ;/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
[BITS 16] Enable_A20: CLI ; 割り込み禁止 CALL A20wait ; ウェイト処理 MOV AL, 0xAD ; キーボード無効化 OUT 0x64, AL CALL A20wait ; ウェイト処理 MOV AL, 0xD0 ; リードアウトプットポートコマンド送信 OUT 0x64, AL CALL A20wait2 ; アウトプットポートの値が書き込まれるまでウェイト IN AL, 0x60 ; リードバッファレジスタ読み込み PUSH EAX ; 読み込んだデータをスタックに保存 CALL A20wait ; ウェイト処理 MOV AL, 0xD1 ; ライトアウトプットポートコマンド送信 OUT 0x64, AL CALL A20wait ; ウェイト処理 POP EAX ; 読み込んだアウトプットポートの値を元に戻す OR AL, 0x2 ; A20有効ビットを1にする OUT 0x60, AL ; A20有効にする出力データを送信 CALL A20wait ; ウェイト処理 MOV AL, 0xAE ; キーボード有効 OUT 0x64, AL CALL A20wait ; ウェイト処理 STI ; 割り込み有効 RET A20wait: ; ウェイト処理関数 IN AL, 0x64 ; ステータスレジスタ読み込み TEST AL, 0x2 ; 送信したコマンド処理が完了したかを ; システムフラグでチェック JNZ A20wait ; 完了していない場合はループ RET A20wait2: ; アウトプットポートの値が書き込まれるまでウェイト処理関数 IN AL, 0x64 ; ステータスレジスタ読み込み TEST AL, 0x1 ; 値が書き込まれたかインプットバッファフルをチェック JZ A20wait2 ; 書き込まれていない場合はループ RET