「いちばんやさしい!OS自作超入門」第3章まででつまずいたこと | UNIX Cafe

* 当サイトでは、コンテンツの一部に広告を掲載しています。

System Note $ cat /proc/ai-disclosure

本記事の構成および論理分析にはAI(人工知能)を使用しています。情報の正確性は、システム管理者(UNIXユーザー)による手動検証済みです。

「いちばんやさしい!OS自作超入門」第3章まででつまずいたこと | UNIX Cafe

先日、自作LC-3 VMのコードをGitHubに公開し、仮想マシン制作の連載がひと区切りつきました。

この連載を通して、C言語のビット演算や配列を使いながら、「命令を読み込み、レジスタを更新し、メモリを読み書きする」というCPUの基本的な流れをかなり近くで見ることができたと思います。

ただ、LC-3VMで学んだのはあくまで「ハードウェア(CPU)に近い部分」です。
ここからさらに一歩進んで、マルチタスクやメモリ管理といった「OS(オペレーティングシステム)の仕組み」を学びたくなりました。

そこで、次なるステップとして選んだ教材が『いちばんやさしい!OS自作超入門』です。

この本の素晴らしいところは、複雑な本物のCPU仕様に迷わされないよう、あえて「仮想CPU」を使ってOSの本質だけを学べる点です。「シンプルなCPUを相手にする」というアプローチは、まさに私たちがLC-3VMでやってきたことと同じ。これなら知識がそのまま活かせそうだとワクワクしています。

この記事では、お目当ての「シングルタスクOSの開発」に入る前に、第三章までの準備段階で躓いたところを整理します。

一番ハードルが低いOS自作本。「OSってどう動くの?」の疑問がこれ1冊で解ける。
\最大5.5%ポイントアップ!/
Amazonで探す
\楽天ポイント4倍セール!/
楽天市場で探す
目次

第3章まででつまずいたことを整理する

「いちばんやさしい!OS自作超入門」を読みながら、GitHubで公開されているos_book_codeを使って第3章まで進めてみました。

第3章までは、まだ本格的なOS開発というより、アセンブラ、CPUエミュレータ、簡単なアセンブリプログラムを動かすための準備が中心です。

ただ、書籍本文の手順と現在のGitHub最新版では、いくつか前提が違って見えるところがありました。特にemu.pyの役割と、HALT / RETの違いで迷いやすいです。

この記事では、第3章まででつまずいた点と、その確認結果をまとめます。第4章から始まる「シングルタスクOSを開発」に入る前の準備メモです。

使用環境

この記事では、現在のGitHub最新版を手元に置いている前提で書きます。書籍本文とGitHub最新版のコードが、常に同じ段階を前提にしているとは限らない点に注意します。

本文中で確認している「現在のGitHub最新版」は著者公開のsueyasu/os_book_codeを指し、early.pyを使った単体実行の手順は、この記事用に用意した補助リポジトリk1117n-cmyk/os-book-code-practiceで試せるようにしています。

第3章までの位置づけ

第3章までの内容を大きく分けると、次のようになります。

  • 第1章: ソースコードを入手してサンプルを動かします
  • 第2章: CPUの仕組みと基本的な考え方を確認します
  • 第3章: アセンブリ言語で簡単なプログラムを書きます

ここでは、OS本体を作る前に、アセンブリコードをバイナリに変換し、それをCPUエミュレータで実行する流れを確認しています。

GitHubで公開されているasm.pyemu.pyと、書籍で前提としているemu.pyの役割を分けておくと、後の章に進みやすくなります。

第1章 開発環境を用意する

最初はPythonの環境設定です。この書籍はPythonで書かれた32bit 仮想CPUの上で動くOSを開発しますので、最初に前提となる仮想CPUを動かすための、Pythonの環境を構築します。

venvのドットで迷う

テキスト P.12

書籍の環境構築では、仮想環境を作るコマンドとして次のような形が出てきます。

python3 -m venv .
source bin/activate

ここで指定している.は「現在のディレクトリ」を意味します。

つまり、このコマンドは「現在のディレクトリそのものを仮想環境にする」という指定です。.venv/というディレクトリを作る指定ではありません。

実行すると、カレントディレクトリ直下に次のようなファイルやディレクトリが作られます。

bin/
include/
lib/
pyvenv.cfg

作業ディレクトリ直下に仮想環境の中身を置きたくない場合は、作成先のディレクトリ名を明示します。

python3.12 -m venv .venv
source .venv/bin/activate

python -m venv ..は、.venvの省略形ではありません。この点は最初に混乱しやすいところです。

1-4 ソースコードの入手とサンプルコードの実行

Wrote hello.binは正常なログ

テキスト P.14

書籍では、次のようなコマンドが出てきます。

python asm.py hello.asm
python emu.py hello.bin

1行目を実行すると、次のようなログが表示されます。

Wrote hello.bin (28 bytes)

これはエラーではありません。

python asm.py hello.asmは、hello.asmを機械語のバイナリに変換するコマンドです。この段階では、プログラムはまだ実行されていません。

Wrote hello.bin (28 bytes)は、hello.asmのアセンブルに成功し、hello.binという28バイトのバイナリを書き出した、という正常な中間ログです。

その次のエミュレータ実行で、初めてhello.binの中身がCPU上で実行されます。

emu.py hello.binでSimple OSが起動する

現在のGitHub最新版を使っていると、書籍どおりに次を実行しても、期待したHello, World!が表示されないことがあります。

python emu.py hello.bin

代わりに、次のような表示になります。

Welcome to Simple OS!
>

これはhello.binが実行された結果ではありません。

現在のリポジトリ直下にあるemu.pyは、引数で渡したhello.binを読む作りではなく、カレントディレクトリのos.binを読み込んでSimple OSを起動する作りになっています。

そのため、次のように引数を付けても、現在のemu.pyでは引数は使われません。

python emu.py hello.bin
python emu.py mul.bin
python emu.py pi.bin

どれも実際にはos.binのSimple OSが起動します。

hello.binを直接動かすにはearly.pyを使う

書籍序盤のhello.binを単体プログラムとして直接実行したい場合は、初期章用のemu.pyを使う必要があります。

ただ、現在の著者公開のリポジトリには、初期章用のemu.pyは残っていませんので、代わりに自作のearly.pyを用意しました。

python3 asm.py asm_code/hello.asm
python3 early.py asm_code/hello.bin

この場合は、書籍序盤の説明に近い形で、hello.binが直接CPUエミュレータ上で実行されます。

期待する出力は次のような形になります。

Hello, World!
CPU halted.
R0: 00000000
R1: 00000000
R2: 00000000
R3: 00000000
R4: 00000000
R5: 00000000
R6: 00000000
R7: 00000000
R8: 0000000C
R9: 00000000
TP: 00000000
SP: 000FFFFF
PC: 0000000C
PT: 00000000
VT: 00000000
CR: 00000000

一方、python emu.pyでSimple OSが起動している場合、CPU halted.とレジスタ一覧はhello.binの実行結果として出ているわけではありません。

Simple OSのプロンプトでexitを入力したときに、OSが終了してCPU halted.が表示されます。

Welcome to Simple OS!
> exit
bye.

CPU halted.
R0: 00000004
R1: 000C0004
R2: 00000000
R3: 00000000
R4: 00000000
R5: 00000000
R6: 00000000
R7: 00000000
R8: 0008064E
R9: 0008061C
TP: 00000016
SP: 000FF000
PC: 000802CC
PT: 000FFF00
VT: 000FF800
CR: C0000004

この時に出力されるレジスタ一覧は、os.binの実行結果になります。

つまり、この2つは別の実行経路として分けて考える必要があります。

early.pyはこのブログ記事のGitHubで公開していますので、気になる方は試してみてください。

3-3 アセンブリ言語でプログラムを作成してみよう

HALTとRETの違い

第3章までのサンプルを動かすうえで、HALTRETの違いも重要になります。

簡単に分けると、次のようになります。

  • HALT: CPUを停止します
  • RET: 呼び出し元へ戻ります

単体プログラムとして直接実行する場合、最後はHALTが自然です。そこでプログラム全体を終わらせ、CPUを停止します。

一方、Simple OSのexecコマンドから外部プログラムとして実行する場合、最後はRETが必要になります。RETで呼び出し元、つまりOS側のコマンドループへ戻るためです。

pi.asmの末尾が書籍とGitHubで違う

テキスト P.69

円周率を1000桁計算するpi.asmで、最後の命令が書籍とGitHub最新版で違っていました。

書籍側では、単体プログラムとして直接実行する流れに見えるため、最後がHALTになっています。

一方、GitHub最新版では最後がRETになっています。

Git履歴を見ると、次の変更が確認できました。

-        HALT
+        RET

コミットメッセージは次の内容でした。

execコマンドで起動できるように終了方法を変更

つまり、GitHub最新版のpi.asmは、Simple OSのexecコマンドから起動する前提に変更されています。

pi.binをSimple OSのexecから実行する

現在のGitHub最新版のpi.asmを使う場合、末尾はRETのままでOKです。

実行手順は次のようになります。

cd /path/os_book_code

python asm.py os.asm
python asm.py pi.asm

mkdir -p dir
cp pi.bin dir/pi.bin

python emu.py

Simple OSが起動したら、プロンプトで次を入力します。

> exec pi.bin

ここで注意が必要なのは、exec pi.binはリポジトリ直下のpi.binを直接読むわけではない、という点です。

emu.pyexec処理では、内部的にdir/<ファイル名>を開きます。そのため、pi.binは事前にdir/pi.binとして置いておく必要があります。

dir/pi.binが無い状態で実行すると、次のエラーになります。

File open error.

これはpi.asmの文法エラーではなく、execが読む場所にpi.binが無いという意味です。

第3章までで分かったこと

第3章までを現在のGitHub最新版で動かすときは、次の点を押さえておくと混乱しにくいです。

  • asm.py.asmから.binを作ります
  • Wrote ...はアセンブル成功のログです
  • 現在のemu.pyos.binを起動します
  • python emu.py hello.binとしても、現在のemu.pyhello.binを読みません
  • 書籍序盤の単体プログラムを直接実行するならearly.pyを使います
  • HALTはCPU停止です
  • RETは呼び出し元へ戻る命令です
  • pi.asmは単体実行ならHALT、Simple OSのexecから実行するならRETにします
  • exec pi.bindir/pi.binを読みます

書籍本文とGitHub最新版が、常に同じ段階のコードを前提にしているとは限りません。

迷ったときは、エミュレータが実際にどのファイルをopen()しているか、PCの初期値がどこになっているか、プログラムの最後がHALTRETかを見ると切り分けやすいです。

第4章へ進む前に

第4章からは「シングルタスクOSを開発」に入ります。

ここからは、emu.pyos.binを起動すること自体が本筋になります。第3章までで混乱しやすかった「単体プログラムを直接実行する世界」と「OSを起動して、その上でプログラムを動かす世界」が、ここから少しずつつながっていきます。

第4章へ進む前に、次の3つを区別できていればOKです。

  • asm.py: アセンブリをバイナリに変換します
  • early.py: 書籍序盤の単体プログラムを直接実行します
  • emu.py: 現在のGitHub最新版ではos.binを読み込んでSimple OSを起動します

ここまで整理できたので、次はシングルタスクOSの開発に進みます。

「いちばんやさしい!OS自作超入門」 第4章でつまずいたこと 

次回はシングルタスクOSの開発です。第4章を進める中で気づいたこと、つまずいた点と、手元で確認した対応を、書籍の進行順に整理していきます。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

のいのアバター のい UNIX Cafe マスター

Macintosh Color Classicから始まった旅は、長いWindows時代を経て、Windows10のサポート終了をきっかけにUNIXの世界へ戻ってきました。UNIX Cafeでは、UNIX・Linux・そしてMacな世界を、むずかしい言葉を使わず、物語のように書いています。プログラミングは、アイデアをコンピューターに伝えるための言葉です。簡単な単語と文法を覚えれば、誰でもコマンドを使えます。ぜひ一度、やさしいプログラミングの世界をのぞいてみてください。

目次