当 x86 CPU の電源がオンになると、その EIP(命令ポインタ)はアドレス0xFFFFFFF0
にハードコードされます。つまり、メモリの最後の 16 ビットです。この時点で CPU はリアルモードにあり、0xFFFFFFF0
から命令を実行できます。
** リアルモード(Real Mode)とプロテクトモード(Protected Mode)** は CPU の 2 つの動作モードです。リアルモードは初期の CPU の動作モードであり、プロテクトモードは現代の CPU の動作モードです。リアルモードは 8086 CPU の時代に登場し、16 ビットの命令を実行します。しかし、16 ビット CPU は最大で 1MB のアドレス指定(20 本のアドレスライン)をサポートするため、後にメモリが大きくなるにつれてレジスタのビット数が 32 ビットになりました。そのため、プロテクトモードが導入され、より大きな領域の、より柔軟なメモリアクセスを実現するために使用されます。
リアルモードの
segment << 4 + offset
とは異なり、プロテクトモードのアドレッシング方式は論理アドレス(Logical Address)のsegment:offset
のsegment
をselector
として使用してGDT/LDT
のエントリにインデックスし、flags
を使用して現在のプログラムがこのメモリセグメントにアクセスできるかどうかを判断し、アクセスできる場合はbase
とoffset
を抽出してリニアアドレス(Linear Address)を得ます。最後に、リニアアドレスをページングテーブルを介して物理アドレス(Physical Address)に変換します。
ブートローダーを実行する際に、現代の CPU はまだリアルモードに入る必要があります。これはソフトウェアの後方互換性を実現するためです。
0xFFFFFFF0
から始まるこの 16 ビットのアドレスは ** リセットベクタ(Reset Vector)** と呼ばれます。この時、BIOS は自身を RAM に移動し、後続の実行でより高速なアクセス速度を持つことができます。また、マザーボードメーカーは0xFFFFFFF0
が BIOS のアドレスを指すことを保証します(通常、0xFFFFFFF0
にはjmp
命令があります)。そのため、BIOS が実行されます。
BIOS は異なるデバイス(ハードディスク、CD-ROM、フラッシュドライブなど)をスキャンし、デバイスがブート可能かどうかを判断します。この判断方法は通常、デバイスの最初のセクタの最後の 2 バイト(つまり、511 番目と 512 番目のバイト)が0xAA55
であるかどうかを確認することです(リトルエンディアンまたはビッグエンディアンに注意してください)。もしそうであれば、そのデバイスはブート可能です。
BIOS がブート可能なデバイスを見つけると、そのブート可能なデバイスの最初のセクタを RAM の0x7c00
にコピーします(512 バイトの0x7c00
から始まる部分)。そして、コピーされたプログラムを実行するために0x7c00
にジャンプします。このプログラムの部分は通常、ブートローダーと呼ばれます。
その後、ブートローダーは RAM の0x100000
からシステムカーネルをロードします。ほとんどの x86 オペレーティングシステムのカーネルは0x100000
にあります。このプロセス中に、ブートローダーまたはオペレーティングシステム自体が CPU の実行モードをリアルモードからプロテクトモードに切り替えます。そして、私たちのオペレーティングシステムが起動されます。