『30日でできる!OS自作入門』 の覚書です。

本書を読んでいて気になったこと、整理したいことをメモしていこうと思います。ちゃんとした説明は、本書を読むほうが良いと思います。

プログラミングの基礎からはじめて、30日後にはウィンドウシステムを有する32bitマルチタスクOSをフルスクラッチで作り上げるという入門書。ビギナーでも無理なく作成できるようPCの仕組み・アセンブラ・Cの解説から始まり、試行錯誤を繰り返しながらアルゴリズムを学びつつ、たのしく自由な雰囲気でOSをゼロから構築していくという、他に類を見ない手法による、趣味と実用と学習を兼ね備えたOS作成の入門書です。

「Amazon 出版社コメント」

[参考]

おぼえがき

セグメンテーション おぼえがき

セグメンテーションとは

セグメンテーションとは、メモリの物理アドレスをセグメントアドレスとオフセットの 2 段階で指定する方法です。8086系のインテル CPU はメモリの物理アドレスを直接指定することができないのでこの方法をつかいます。

セグメントアドレスの指定には、セグメントレジスタを使います。セグメントレジスタは 4 個用意されていて、それぞれに名前と役割が与えられています。

CS

「コードセグメント」 と呼びます。このレジスタには、実行中のプログラムのアドレスが格納されます。このレジスタと命令ポインタ(EIPレジスタやIPレジスタ)を組み合わせて、命令の置かれている物理アドレスを計算します。

DS

「データセグメント」 と呼びます。このレジスタは、データをメモリから読み出すときに使われます。

SS

「スタックセグメント」 と呼びます。スタック操作に使われるセグメントです。P.133 のスタック操作の説明で使われているのが確認できます。

ES

「エクストラセグメント」 と呼びます。データセグメントの拡張として使用します。DS だけで足りない場合に使います。

[参考]

セグメントとオフセット

GDT (Global Descriptor Table) とは

P.112 の GDT に関する説明のメモです。

セグメントアドレスの指定にはセグメントレジスタを使います。このセグメントレジスタですが、じつはセグメントの物理アドレスがそのまま格納されているわけではなく、セグメント情報の ID が格納されています。セグメント情報のことをセグメントディスクリプタ (Segument Descriptor) と呼び、セグメント ID のことをセグメントセレクタ (Segment Selector) と呼びます。

セグメント情報は次の4つの情報で構成されています。

  1. セグメントがどこから始まるのか (セグメントベース) : 32bit
  2. セグメントの大きさはどれくらいか (セグメントリミット) : 20bit
  3. セグメント属性 : 12bit

一つのセグメントに関する情報は、この 8byte の情報によって構成されています。これらセグメント情報を管理するのが GDT (Global Descriptor Table) と呼ばれるテーブルです。そして、GDT がメモリのどのアドレスに用意されているかを知らせるためのレジスタが、GDTR になります。

GDT

セグメントセレクタは 13bit になっています。セグメントレジスタは 16bit ですが、下位 3bit が使えません。なので、セグメントセレクタであらわせる ID の数は 2 ^ 13 = 8,192 個です。ただし、セグメント ID が 0 、つまり最初のセグメント情報はヌルセレクタと呼ばれ、使うことができません。実際はセグメント情報は全部で 8,191 個 です。

アセンブラからセグメントを指定する

セグメントを指定するには、セグメントレジスタにセグメント情報のアドレスをセットします。セグメント情報のアドレスは、GDT 内の相対アドレスで指定します。つまり、セグメント情報は 8byte なので、「8 * (セグメントID)」 をセグメントレジスタにセットしてやればよいことになります。これで、GDTR のアドレスとセグメントセレクタのアドレスを計算して、セグメントが指定できます。

[参考]

Linux メモリー・モデルの探求

マルチタスクのメモ

ここから、P.295 のマルチタスクのメモです。

CPU はいつでもセグメント番号を扱う命令を実行するたびに GDT の設定を確認しにいくので、今回も JMP 命令を実行するときに普通の far-JMP なのか タスクスイッチなのかを判断しています。

本書 P.294 より

つまり、GDT に設定しておくセグメントの情報には 2種類あって、実行可能なセグメント(プログラムのこと?) と タスク状態セグメントがあるということらしいです。タスク状態セグメントは、全部で 104byte からなる情報の塊で、これが見つかるとタスクスイッチされます。

割り込み と PIC (Programmable Interrupt Controller)

P.127 の割り込みに関する説明のメモです。

CPU は、割り込み信号 (IRQ: Interrupt Request) を一つしか処理することができません。そこで、複数の割り込みを処理できるように CPU の外部に PIC (Programmable Interrupt Controller) という装置が用意されています。

1つの PIC は同時に 8つの割り込みを監視することができます。Intel 製の CPU には、PIC が 2つ付いています。

┌―――┐   ┌――――――――┐
│CPU│―――│PIC(マスタ)│
└―――┘   └――――――――┘
├IRQ0
├IRQ1   ┌―――――――――┐
├IRQ2 ―― │PIC(スレーブ)│
├IRQ3   └―――――――――┘
├IRQ4       ├IRQ8
├IRQ5       ├IRQ9
├IRQ6       ├IRQ10
└IRQ7       ├IRQ11
├IRQ12
├IRQ13
├IRQ14
└IRQ15

PIC の割り込み信号を命令と受け取る

CPU は、PIC の割り込み信号を、INT 命令として実行するように作られています。PIC は、IRQ それぞれに割り込み信号を設定し、割り込みが発生すると、割り込み信号を INT 命令一緒に CPU に送信します。

CPU は、IDT (Interrupt Descriptor Table) を見て割り込み信号に対応する関数の呼び出しを行います。これが割り込み処理です。IDT は、割り込み信号と割り込み処理関数を対応付けたテーブルです。

PICの割り込み処理

PIT (Programmable Interval Timer) とは

P.232 のタイマーに関する説明のメモです。

PC でタイマーを利用するときには、PIT (Programmable Interval Timer) を設定します。これは、一定期間ごとに割り込みを発生させる装置です。

PC では、PIT は IRQ0 につながっています。設定方法は、キーボードやマウスの割り込みを設定するのと同じ方法です。

[参考]