x86アーキテクチャにおけるリアルモードからプロテクトモードへの移行について
現在、「作りながら学ぶOSカーネル 保護モードプログラミングの基本と実践」という本でOSについて学んでいます。
そこで、x86について、リアルモードから保護モードへ移行する際にCR0の最下位ビット(PEビット)を1にすることでCPUが保護モードとして動作するようになるという記載がありました。
しかし、その後の32ビットコード部分へのfarジャンプ命令では、prefix(0x66, 0x67)をつけているようです。
CPUはすでに保護モード(32ビット)として動いているはずなので、オペランドを32ビットと解釈させるためのprefixは不要と思えるのですが、なぜ必要となるのでしょうか?
確かに、prefixを外して実行するとうまくいきませんでした。
実際に本で説明されていた移行部分のコードは下記となります。
mov eax, cr0
or eax, 0x00000001
mov cr0, eax
jmp $+2
nop
nop
db 0x66 # <- ここ
db 0x67 # <- ここ
db 0xEA
dd PM_Start
dw SysCodeSelector
また、PEビットを1にした時点で保護モードとしてCPUが動作するのであれば、
その直後の命令ポインタが指すアドレスがくるってしまう気がするのですが、そんなことはないのでしょうか。
というのも、保護モードではCSレジスタの値からGDTを参照して対象のセグメントを探し出し、
EIPレジスタに入っているオフセットを足して次の命令をフェッチしていると思うのですが、
PEビットを1にした直後はCSレジスタにはリアルモードで使用していたセグメント情報が入っており、
それを元にGDTを参照しようとするとわけのわからないところを参照してしまいそうな気がしました。