CPU が直接理解できる「機械語の一歩手前」
プログラムを書いたことがなくても大丈夫。このページを読めば、CPU シミュレーターの命令がすべて理解できるようになります。
CPU が分かる言語の、人間向け表現
↑ 抽象度(高いほど人間に近い) ← クリックで詳細
← 左のどこかの層をクリックしてください
人間が読み書きしやすい。でも CPU はそのまま実行できない。
CPU への「指示書き」。1行 = 1命令 = CPU が1回やること。
計算のたびにメモリに読み書きすると遅い→ CPU 内部の超高速な記憶領域
どんな計算にも使える「変数箱」。8ビット(0〜255 の整数)を格納できます。
例:LOAD A, 42 → A の箱に 42 を入れる
「次に実行する命令の番号」を常に指している特殊レジスタ。
通常は自動的に 0→1→2→… と増えますが、JMP 命令で強制的に変えられます。
直前の演算結果の「性質」を記録する 1 ビットのスイッチ。CMP の後で JEQ / JGT が参照します。
| フラグ | 立つ (=1) 条件 |
|---|---|
| Z | 結果が 0(= 同じ値を比較した時) |
| N | 結果が負(Rx < Ry の時) |
| C | 加算で 桁あふれ(255 を超えた) |
レジスタより遅いが、より多くのデータを保管できる
STORE A, 0x00 → アドレス 0x00 に A の値を保存
メモリの各マス目には住所番号(アドレス)がついています。0x00〜0x0F は 16進数 の表記で、10進数の 0〜15 のことです。
※ このシミュレーターでは LOAD B, [0x00] と書くとメモリから読み込みます
各レイヤーをクリックして速度・容量・用途を確認しよう
| 層 | 速度 | 容量 | 単価 |
|---|---|---|---|
| レジスタ | ~1 cy | ~512 B | 最高 |
| L1 | ~4 cy | 32–64 KB | 非常に高 |
| L2 | ~12 cy | 256 KB–2 MB | 高 |
| L3 | ~40 cy | 4–64 MB | 中 |
| RAM | ~100 ns | 4–128 GB | 低 |
| SSD | ~100 µs | 256 GB–8 TB | 非常に低 |
| HDD | ~8 ms | 1–20 TB | 最低 |
12 命令すべてを例付きで理解しよう
レジスタ Rx に即値(数字)を入れる。
メモリのアドレス addr から値を読み込む。
Rx の値をメモリアドレス addr に保存する。
Ry の値を Rx にコピーする。Ry は変わらない。
Rx = Rx + Ry
Rx = Rx − Ry
Rx = Rx × Ry(8ビット下位)
ADD A, B の後、A の値は変わりますが B は変わりません。
「もし〜なら」を実現するために使います。CMP で比較 → JEQ/JGT で分岐という流れが基本です。
Rx と Ry を比較してフラグを更新。値は変わらない。
無条件で label の行にジャンプ(ループに使う)。
Z=1(直前の比較が「等しい」)なら label へ。
N=0 かつ Z=0(直前の比較が「より大きい」)なら。
Rx の値を出力欄に表示。Python の print() に相当。
プログラム終了。必ず最後に書くこと。
シミュレーターの 3 つの例を 1 行ずつ読んでみよう
ADD A, B → A = 12 + 7 = 19。B は 7 のまま変わらない。sum=0; i=1; limit=5 に相当。sum += i — A に B を足す。CMP B, C で B と 5 を比較。B > 5 なら JGT done で出口へ。JMP loop で先頭に戻る。CMP A, B → 15 − 20 = −5 → N フラグが立つ(負)、Z は 0。JGT a_win — N=1 なので ジャンプしない(A は B より大きくない)。OUT B を実行 → 20 を出力。コピー&改造して使えるテンプレート
for i in range(1, N+1) に相当
大きい方を使う分岐
レジスタが足りない時のテクニック
等しいかどうかの分岐(JEQ を使う)
最後に HALT がないと、命令リストの外を読み続けて予期しない動作になります。必ず最後の行に HALT を入れましょう。
ADD A, B は「A を更新する」命令です。B には何も書き込まれません。「B に A を足した結果を入れたい」なら ADD B, A と書きます。
loop: と定義して JMP lop と書くと「ラベルが見つからない」エラーになります。定義と参照のスペルを一致させましょう。
フラグは直前の演算の結果です。JEQ/JGT の直前には必ず CMP を置きましょう。
; 以降はコメントとして無視されます。各行に「何をしているか」を書いておくと、後で見直したときに理解しやすくなります。
シミュレーターの「1ステップ」ボタンを使えば、1命令ずつ実行してレジスタの変化を確認できます。バグを見つけるのに最適です。
実際に命令を入力して、CPU がどう動くか体感してみよう。
パイプラインのアニメーションで Fetch→Decode→Execute が見えます。