2026-11-02

コンピューターシステムの理論と設計 ~第四章 機械語~

引き続き、『コンピュータシステムの理論と実装』(通称 nand2tetris)を読み進めています。 今回は第4章「機械語」で、Hackという nand2tetris 独自のコンピュータの機械語(CPUが直接理解できる命令)を書いてみて学んだことをまとめてみました。

Hackの登場人物

Hackの機械語を読むうえで、最初に押さえておきたいのが @・D・M の3つです。自分はロッカーに例えると理解しやすかったです。

  • @(A): 番号札。どのロッカーを見るかを決める
  • D: メモ用紙。計算途中の値を置いておく場所で、すぐに書き換わる
  • M: ロッカーの中の紙。@ が指している番地のメモリ(RAM[@])

JavaScriptで例えると、次のようなイメージです。

ポイントは、M は独立した入れ物ではなく 「今 @ が指している RAM[@]」を指す決まった書き方 だということです。@i と書いて @ を i の番地にすると、その後に出てくる M は全部 RAM[i] のことになります。

A命令とC命令

Hackの命令は1つあたり16ビットで、命令は次の2種類しかありません。

  • A命令(@値): @ に値をセットする
  • C命令(dest=comp;jump): 計算して、結果をどこかに保存したり、条件によってジャンプしたりする

たとえば RAM[2] = RAM[0] + RAM[1] は次のように書けます。

@ で番号札を切り替えてから M を読み書きする、という流れを繰り返しています。

@ を書き忘れると別のロッカーを見てしまう

自分が最初につまずいたのがここです。M は「今の @ が指しているロッカー」なので、@R1 を書かずに M を使うと、直前に @ で指定した番地のロッカー をそのまま見てしまいます。

たとえば合計を計算するプログラムで、直前に @sum を指定していた状態で @R1 を書き忘れると、M は RAM[R1] ではなく RAM[sum](中身は初期値の 0)になってしまいます。 M を使う前には、必ず「どのロッカーを見るか」を @ で指定し直す必要があります。

ジャンプと無限ループ

Hackのジャンプは、C命令の jump 部分で行います。

JMP は無条件ジャンプで、飛ぶ先は今の @ の値 になります。なので、ジャンプする前に @ で飛び先の行番号を指定しておきます。

プログラムの「終わり」は無限ループで表現する

Hackのプログラムの最後には、よく次のようなコードが置かれています。

(STOP) はラベルで、その位置の行番号に名前を付けるものです。アセンブル(機械語に変換)してROMに載せると、@STOP は実際の行番号に置き換わります。たとえば (STOP) が22行目なら、次のようになります。

22行目から22行目に飛び続けるだけで、何の処理もしない無限ループです。

CPUは電源がついている限り命令を実行し続けるので、「終わる」ということができません。そのため、何もしない処理を永久にループさせることでプログラムの終了を表現している んですね。JavaScriptのように処理が終わったら自然に止まる、という感覚とは違っていて面白いなと感じました。

定義済みシンボル

Hackには、最初から番地が決まっている 定義済みシンボル があります。

シンボル番地
R0 〜 R150 〜 15
SCREEN16384 ~ 24757
KBD24576

番地が固定されているので、別々に書かれたプログラムやハードウェア同士でも「この値はここに置く」という約束として使えます。 たとえば「入力は R0 と R1、結果は R2 に入れる」と決めておけば、テストする側とプログラムを書く側で値を受け渡せますし、KBD を見ればキーボードの入力が読める、という形で値を共有できるわけです。

まとめ

第4章では、Hackの機械語を通して @・D・M の役割や、ジャンプ・無限ループによる終了の表現などを学びました。 特に M が「今 @ が指しているメモリ」を指すという点は、@ を書き忘れて別の値を読んでしまうことで身をもって理解できた気がします。

次の第5章では、第1〜3章で作ってきたゲートやALU、メモリを組み合わせて、このHack機械語が動くCPUを自分で作ることになるので楽しみです。

参考資料

  • nand2tetris Web IDE
  • nand2tetris 公式サイト

Thanks for the visit Nozo Blog