1 ポイント 投稿者 GN⁺ 2024-07-16 | 1件のコメント | WhatsAppで共有
  • 人は複雑なものと、単にややこしいだけのものを区別する。複雑さは興味深いと見なされるが、ややこしさは有害だと見なされる。x86_64 CPUのセットアップ過程は、その大半がややこしさに属する。
  • BIOSによって読み込まれたブートセクタから、CPUを16ビットのリアルモードから64ビットのロングモードへ設定する方法を解説する。この設定は基本的なものであり、さらに多くの作業が必要となる。
  • Intel 64 および IA-32 アーキテクチャ・ソフトウェア開発者マニュアル、アセンブラ(nasmを使用)、QEMUが必要。x86アセンブリと言語としてのnasm構文を理解している必要がある。

出発点: BIOS

  • リセット後、x86 CPUは"リアルモード"にある。このモードでは基本オペランドサイズが16ビットである。セグメンテーションを使って1MBのメモリをアドレス指定できる。
  • BIOS後に最初に実行されるコードはブートセクタにある。BIOSはシステム内で 0xaa55 で終わる最初のセクタを探し、そのブートセクタをメモリアドレス 0x7c00 に読み込む。
  • BIOSが提供するのは512バイトだけであり、これを使ってブートローダーの残りの部分をブートストラップしなければならない。

ブートセクタの設定

  • 簡単なブートセクタを用意し、BIOSルーチンを使って画面にメッセージを表示して停止させる。これにより、ツールが正しく動作するか確認できる。
  • アセンブリコードとMakefileを使ってブートセクタを設定する。

ステップ1 – ディスクから第2段階を読み込む

  • ブートローダーは2段階に分けられる。第1段階はブートセクタ内のコードで、BIOSが読み込むすべての部分である。第1段階の唯一の目的は、第2段階をメモリに読み込むことだ。
  • 第2段階では、16ビットのリアルモードから32ビットの保護モードへ切り替える。保護モードではBIOSルーチンを使えない。ディスクからセクタを読み込むのは、はるかに複雑になる。
  • BIOSを使ってディスクにアクセスする方法を説明する。

32ビット保護モード

  • CPUをリアルモード(16ビット)から保護モード(32ビット)へ切り替える。保護モードでは、セグメンテーションを使ってメモリ保護を実装する。
  • 保護モードへ切り替える前に、グローバルディスクリプタテーブル(GDT)を定義する必要がある。GDTはメモリ内に連続した構造として定義される。
  • GDTを定義し、保護モードへ切り替える方法を解説する。

64ビットロングモード

  • ロングモードへ切り替える前に、CPUは保護モードにあり、かつページングが有効化されていなければならない。保護モードはすでに設定されているが、ページングが必要となる。
  • ページングはセグメンテーションに代わって、仮想アドレス空間や権限などを管理する。ロングモード移行のためのページテーブルを作成する方法を解説する。
  • ロングモード移行用のGDTを定義し、保護モードからロングモードへ切り替える方法を説明する。

GN⁺のまとめ

  • この記事は、x86_64 CPUを16ビットのリアルモードから64ビットのロングモードへ設定する過程を詳しく説明している。これにより、ブートローダーやOSカーネル開発への理解を深められる。
  • BIOS、ブートセクタ、保護モード、ロングモードなど多様な概念を扱い、各段階で必要となるアセンブリコードと設定方法を提供している。
  • この記事はOS開発に関心のある人に有用で、特にx86アーキテクチャへの深い理解を与えてくれる。類似の機能を持つプロジェクトとしては「Writing a Simple Operating System – from Scratch」がある。

1件のコメント

 
GN⁺ 2024-07-16
Hacker Newsのコメント
  • 保護モードへ直接切り替えなくても、ロングモードへ移行する方法がある
    • ブートセクタに小さな64ビットカーネルを読み込むブートローダーを作成した
    • ディスクからカーネルを読み込み、VESAモードを設定する過程を含む
  • 80286は16ビットレジスタであるMSWを持ち、80386はこれを32ビットのCR0へ拡張した
    • 64ビットのロングモードではEFER MSRが追加され、CR0は64ビットへ拡張された
    • 現在はCR0の11ビットとEFERの8ビットだけが使われている
    • Intel/AMDが既存レジスタの空きビットを使わなかったのはなぜか気になる
  • この記事で最も不必要に複雑なのはMakefileとリンカスクリプトだ
    • NASMはフラットバイナリ出力を生成できるが、それを使うのはあまりに「ハック的」だと考えているようだ
  • CPUを正しいモードへ切り替えるために必要なすべての手順が不必要に複雑だ
    • どれも下位互換性のために必要な手順に見える
    • Intelは最初から正しいモードで起動できるフラグや命令を提供できたはずだ
    • あるいは下位互換性をすべて取り除くこともできたはずだ
    • ARM64にも似た問題があるのか調べた記憶がある
    • 最初から64ビットとして設計されたCPUがあるのか気になる
    • Itaniumの目標や設計はそういうものだったはずだ
  • なぜ新しいブートローダーのアプローチを作ったのか理解できないUEFI支持者もいるかもしれない
    • 筆者が言うように、「ここまで来たなら立派なものだ」
  • UEFIがどれほど古いのか気になる
    • ロングモードとともにBIOSを廃止しなかったのは惜しい
  • このブート手順がEFI/UEFIと互換性があるのか気になる
    • UEFIファームウェアが実機上でリアルモード/保護モード/ロングモードを実際にエミュレートしているのか気になる
  • ARMではこの過程がもっと簡単なのか気になる