質問: プロテクトモード移行するには思いつく限り(以下間違えて認識しているところがありましたら教えてください。) ``` ・セグメントディスクリプタ(とりあえず1個でも作ればアクセスできるはず) ・IDT (これがないとソフトウエア割り込みを呼び出せない) ・IR0レジスタのPEビットを1にセットする。 ・レジスタの値をセグメントベースからセレクタへ書き換える。(ここで先読みの問題が出てくる。) ``` この中の4つ目に関して不明点があるので教えてください。 今回の内容と非常に似た質問 ・・・ほぼ同じ IR0のビットを1にセットした時点でメモリ空間へのアクセス方法 リアルモードでのセグメント方式のアクセス方法 ``` セグメントベース × 10 + オフセット ``` ではなく ``` セグメントセレクタ(ディスクリプタからベースアドレス参照) + オフセット ``` このアクセス方法に変化する。 つまり、CR0レジスタのPEビットを1にしたあとも リアルモードで使っていたCS,DSの値をそのまま使っていると おそらく対応セグメントディスクリプタが見つからずエラーになる。 なので、・・・ プロテクトモード用にCS,DSを再セットする。 ``` MOV CS, 0xXX MOV DS, 0xXX ``` このようにしてDS,CDともに再セットしたかったところだがCPUは命令を先読するため、 CR0レジスタのPEビットをONにした時点で CPUはリアルモード値がセットされたCS,DSが使われた命令群をすでに読み込んでしまっていることになる。 **ここから本題 どうやってそれを解消するのか** ``` jmp $+2 ``` この命令を使う。 このjmp命令を使うとCPUが先読みしていた命令群をクリアできる。 ``` ;/_/_/_/_/_/_/_/ ;CR0レジスタPEオン ;/_/_/_/_/_/_/_/ mov eax, cr0 or eax, 0x00000001 mov cr0, eax ;/_/_/_/_/_/_/_/ ;先読みクリア ;/_/_/_/_/_/_/_/ jmp $+2 ``` **!ここから勘違いが発生してる可能性があります!** 間違えてたらお願いします。 CR0レジスタのPEビットを1にした時点で プロテクトモード用のアクセスに切り替わるが その時点ですでにCPUに先に読み込まれていた命令群は プロテクトモードではなくリアルモードで動くのですよね? 似た質問 なので ``` ;/_/_/_/_/_/_/_/ ;CR0レジスタPEオン ;/_/_/_/_/_/_/_/ mov eax, cr0 or eax, 0x00000001 mov cr0, eax ;/_/_/_/_/_/_/_/ ;先読みクリア ;/_/_/_/_/_/_/_/ jmp $+2 nop nop jmp [セレクタ:32bitオフセット] ;← ``` リンク先の質問者さんは明示的に32bitで指定するための専用の命令が必要だといっておりますが jmp $ + 2 で先読みをクリアしたあとならその命令というのは必要ありませんよね? 仮に、32bitオフセットができないとしても mov cs,0xXX でセレクタを指定することはできますよね?(命令が増えるけど) 0から作るOS こちらでは ・先読みのクリア ・レジスタ再セット をいっぺんにやっているように見えますが ``` MOV EAX, CR0 ; CR0レジスタの値を読み出します OR EAX, 0x00000001 ; PEビットをOR命令でONします MOV CR0, EAX ; そのままCR0に書き込みます JMP CODE_DESC:Pmode_start ; CODE_DESCは0x08が入っています ``` このさいに32bitと認識されるための(?)専用命令を使っていますが これはさきほどのように CR0レジスタのPEビットを1にセットしたあとでも その時点で先読みしていた命令群はリアルモード前提で実行され、16ビットレジスタを使えないから という解釈であっていますか? 気になったのでお願いします。
回答: 過去の質問の回答にもありますが、最後の ``` JMP CODE_DESC:Pmode_start ``` FAR JUMP が、 * CS レジスタのロード(これによりプロテクトモード用のセグメントディスクリプタがロードされる) * 命令プリフェッチキューのクリア を同時に行います。 同じ CS 内でのジャンプが NEAR JUMP、セグメントを異なる場所にするジャンプが FAR JUMP です。つまり FAR JUMP は CS レジスタのロードを伴います。 また、ジャンプすることで命令プリフェッチキューはクリアされる(それまで読んだのとは別の場所から処理が継続されるのですから、プリフェッチは全部捨てねば意味がありません)ので、上手くいくのです。 ※32bit プレフィックスは不要です。必要なのは FAR JUMP です