ソフトウェアのしくみシミュレーター
コンピュータは、精製した岩(シリコン)に刻んだスイッチのON/OFFだけで、計算し、記憶し、画面を描き、ネットワーク越しに会話しています。 このページでは、その積み上げを25個のインタラクティブシミュレーターで下から順に体験できます。 どれも数クリックで動くので、気になったものから触ってみてください。
大半のシミュレーターは、書籍『CODE コードから見たコンピュータのからくり』(Charles Petzold 著、永山操 訳)を教材化した コンピュータのしくみ講座を作る過程で生まれたものです。 発想のもとになっているのは Faza「Software, from First Principles」(fazamhd.com) のインタラクティブ図解で、アナログ→デジタル変換とネットワークの3点は、そちらを本サイト用にVueコンポーネントとして再実装したものです。
2つの状態でコードを作る
オン/オフの2状態しか送れなくても、並べる個数を増やせば文字は表せる。すべての出発点。
懐中電灯の符号
送れるのは「短い点滅」か「長い点滅」の2種類だけ。それでも並べる個数を増やせば、1個で2文字、2個で4文字と表せる文字が倍々に増えていく。ドットとダッシュを組み立てて「送る」を押すと、符号表と照合して文字が判定される。
関連する講: 第1講「コードで世界を伝える」
点滅の並びを作って「送る」を押すと、符号表と照合して文字を判定します。
懐中電灯で送れるのは「短い点滅」か「長い点滅」の2種類だけです。それでも並べる個数を増やすと、 1個で2文字、2個で4文字と、表せる文字は倍々に増えていきます。よく使うEとTに最短の符号が 割り当てられているのも符号表から読み取れます。たった2つの状態の組み合わせで文字が届く—— この構造が、このあとの点字にも電気回路にも、そのまま顔を出し続けます。
リレー中継(弱った信号を作り直す)
距離を伸ばすと信号は右へ行くほど弱まり、ある距離を超えると受信側のサウンダが動かなくなる。そこにリレーを置くと1本だった線路が短い区間に分かれ、切れ目ごとに信号が濃い色へ戻る。届く距離が伸びたのは信号が強くなったからではなく、1区間が短くなったからだという点を確かめられる。
関連する講: 第2講「遠くまで、確実に届ける」
送=送信キー / リ=リレー / 受=サウンダ(受信側)
区間 1本 / 1区間あたり 150マイル
リレーなし(送信側から受信側まで1本の区間)
縦線=サウンダを動かせる最低の強さ(20%)
届く — 受信側のサウンダが鳴る
1区間150マイル。まだ読み取れる強さが残っているので、リレーなしでも届きます。
距離を伸ばすと、線の色が右へ行くほど薄くなります。導線が長くなるほど信号は弱まり、ある距離を超えると 受信側では読み取れなくなります。ここでリレーを置くと、1本だった線路が同じ長さの区間に分かれ、 区間の切れ目ごとに信号が濃い色に戻ります。リレーが弱った信号を受け取り、その動きで 新しい電池につながった次の区間のスイッチを入れ直しているからです。届く距離が伸びたのは、信号そのものが 強くなったからではなく、1区間の長さが短くなったからだ、という点を確かめてみてください。 人間が電文を書き取って送信し直していた中継作業を、この仕組みがそのまま肩代わりしています。
歯車で数える
電気より前の計算機。物理的な仕掛けだけで「数を数えて桁を繰り上げる」を実現していた。
機械式カウンター
車の走行距離計と同じ、桁ごとの数字ホイールと繰り上げピン。ホイールが9から0へ戻る瞬間だけ、ピンが隣の桁を1目盛り押し出す。+1を押し続けて、099→100で2桁が連鎖して動く瞬間を見てみてほしい。パスカル以来の機械式計算機を悩ませた「キャリーの自動処理」そのもの。
関連する講: 第11講「そろばんからマイクロプロセッサへ」
一の位が9→0になる瞬間だけ、繰り上げピンが隣の桁を1つ押し出します。 それ以外のとき、桁同士は独立していて干渉しません。パスカル以来の機械式計算機の設計者たちを 悩ませた「キャリーの自動処理」とは、まさにこの連動機構のことです。後の加算回路のキャリー伝播も、 歯車が電気仕掛けに変わっただけで、原理はこれと同じです。
スイッチで論理を作る
電圧で自動開閉するスイッチを配線でつなぐと、「判断」する回路が生まれる。
スイッチ回路(AND・OR・NOT)
2つのスイッチを直列につなぐと「両方ONのときだけ点灯」(AND)、並列に並べると「どちらかONで点灯」(OR)になる。タブを切り替えて、配線の形がそのまま論理になっていることを確かめられる。手押しのスイッチをリレーの接点に置き換えれば、同じ論理が自動で動き出す。
関連する講: 第6講「論理ゲートを作る」
スイッチA・Bの両方を閉じた(ON)ときだけ電流が流れる直列回路
| A | B | 出力 |
|---|---|---|
| 0 | 0 | 0 |
| 0 | 1 | 0 |
| 1 | 0 | 0 |
| 1 | 1 | 1 |
ANDは直列つなぎで、両方のスイッチが閉じないと電流が流れません。 ORは並列つなぎで、どちらか一方が閉じれば電流が流れます。 NOTはスイッチが開いている(0)ときに通電し、閉じる(1)と遮断する「反転」の回路で、 双投式リレーの"逆側"の接点で作るインバータと同じ働きです。手で押すスイッチをリレーの接点に 置き換えれば、同じ論理がそのまま自動で動きます。
ブール式の表
論理は紙の上では「式」として書ける。A×B(AND)・A+B(OR)・A×(1−B) の3つをタブで切り替え、AとBの0/1を動かすと、式へ代入した結果と真理値表の「いまの入力に当たる行」が連動して光る。回路を組む前に、論理が機械的に計算できることを確かめる。
関連する講: 第5講「論理とブール代数」
×は交わり(AND)。AとBの両方が1のときだけ、式の値が1になる
| A | B | A×B |
|---|---|---|
| 0 | 0 | 0 |
| 0 | 1 | 0 |
| 1 | 0 | 0 |
| 1 | 1 | 1 |
タブで式を選ぶと、A・Bの4通りの組み合わせすべてについて式の値を埋めた表ができあがります。 AとBを切り替えると、いまの入力に当たる行がハイライトされ、上の代入結果と表の行が 常に一致していることを確かめられます。A+Bでは両方を1にしても値は2ではなく1—— ORの表だけの特別ルールです。A×(1−B)のような組み合わせの式も、内側のカッコから順に 当てはめていくだけで機械的に値が決まります。
XOR を組み立てる
「入力が異なるときだけON」になるXORは、単体の部品ではない。同じ入力をORとNANDの両方に入れ、2つの出力をANDでまとめると得られる。ORが「両方0」を、NANDが「両方1」をはじき、残った2通りだけが通る——1マスずつ外れた2つのゲートが互いの穴を塞ぐ様子が見える。
関連する講: 第7講「たし算とひき算の回路」
| A | B | OR | NAND | 出力 | |
|---|---|---|---|---|---|
| 0 | 0 | 0 | 1 | 0 | ← 現在 |
| 0 | 1 | 1 | 1 | 1 | |
| 1 | 0 | 1 | 1 | 1 | |
| 1 | 1 | 1 | 0 | 0 |
XOR は単体の部品ではなく、同じ入力をORゲートとNANDゲートの両方に入れ、 2つの出力をANDゲートでまとめた回路です。ORが「両方0」を、NANDが「両方1」をはじき、 残った「どちらか一方だけ1」の2通りだけで出力が1になります。入力を切り替えて、 どのゲートが反応し、真理値表のどの行にいるかを確かめてみましょう。
二進法で数えて、足す
スイッチは2状態しかないので、0と1だけで数える。それでも足し算はできる。
基数変換ラボ
同じ1つの数が、10進・8進・4進・2進の4つの表記で同時に切り替わる。桁をタップすると、その桁の重み(基数の累乗)と「桁の値×重み」が展開表示される。基数が変わっても位取りの原理は変わらないこと、基数が小さいほど桁数が長くなることを確かめられる。
関連する講: 第3講「10進法は絶対じゃない」
桁をタップすると、その桁の重み(基数の累乗)と「桁の値 × 重み」が表示されます。
スライダーや「+1 / −1」で数を動かすと、4つの基数の表記が同時に切り替わります。 どの基数でも、桁の値にその位の重み(基数の累乗)を掛けて全部足すと、必ず元の10進数に戻ります。 基数が小さいほど1桁で表せる量が少ないぶん桁数は長くなりますが、表記が違っても指している量は同じです。 位取りの原理そのものは、基数が変わっても変わりません。
二進カウンター
0と1だけの世界では、1+1で即座に桁が繰り上がる。「+1」を押すと一の位から繰り上げが左隣へ順に伝わり、1111の次には0000へ戻る「桁あふれ」も観察できる。機械式カウンターの繰り上げピンとまったく同じ原理が、2状態でも成立している。
関連する講: 第3講「10進法は絶対じゃない」
「+1」を押すと一の位(Bit0)から繰り上げが始まります。1だったビットは0に戻りつつ隣のビットへ繰り上げを渡し、0だったビットが1になったところで伝播は止まります。 4bitでは0〜15の16通りしか表せないため、1111の次は0000に戻ります(オーバーフロー)。コンピュータの整数演算が特定の値で「桁あふれ」するのはこの仕組みのためです。
ビット数と組み合わせの数(2ⁿ)
スライダーでビット数を1〜8の間で動かすと、区別できるコードの数が升目の増減としてそのまま見える。1ビット増やすたびに升目はちょうど2倍——1ビットで2通りだったものが、8ビットでは256通りになる。升目をタップすれば、そのマスに対応する2進表記も確かめられる。
関連する講: 第4講「ビットの正体」
3ビット → 2³ = 8通り
マスをタップすると、そのマスの2進表記がここに出ます
升目の1つひとつが、nビットで区別できるコード1個に対応しています。スライダーを右へ1つ動かすたびに、 升目の数はちょうど2倍——グリッドの縦か横のどちらかが2倍に伸びます。1ビットではたった2通りだった組み合わせが、 8ビットでは256通り。ビット数nを決めると、区別できる可能性の数2ⁿが決まるという関係を、 升目の増減として目で確かめてみてください。
半加算器
1ビットの足し算の「和(S)」はXOR、「繰り上がり(CO)」はANDの振る舞いそのもの。足し算専用の部品はどこにもないのに、ゲート2つで加算が成立する。1+1のときだけCOが1になり、答えが「10」と2桁になる様子を4パターン全部で試してみてほしい。
関連する講: 第7講「たし算とひき算の回路」
| A | B | S(サム) | CO(キャリー) |
|---|---|---|---|
| 0 | 0 | 0 | 0 |
| 0 | 1 | 1 | 0 |
| 1 | 0 | 1 | 0 |
| 1 | 1 | 0 | 1 |
半加算器は、同じ入力A・Bから「XORゲートでサムビットS」「ANDゲートでキャリービットCO」を 同時に計算する回路です。1+1のときだけCOが1になり、10進の「2」が2進数の「10」として出てきます。 入力が2つしかない——前の桁からのキャリービットを足し込めない——ため、使えるのは一番右の桁だけ。 それが「半」加算器と呼ばれる理由です。
スイッチの中身(物理)
論理ゲートの土台になる「電気で電気を制御するスイッチ」は、物理現象そのもの。
真空管(三極管)
加熱したフィラメントから飛び出す電子の流れを、途中に置いた格子(G)の電圧だけで堰き止める。可動部品ゼロで、リレーの約千倍速く状態が変わるこのスイッチが、初期の電子式コンピュータの主役だった。
関連する講: 第11講「そろばんからマイクロプロセッサへ」
加熱中
電子を反発
豆電球(外部回路): 消灯
格子電圧 -5V ― 格子の負電荷が電子を押し返すため、電子は陽極に届かず陰極側へ跳ね返されます。回路はOFFのまま。
真空管は、フィラメントが陰極を熱し続けていても、格子(グリッド)のわずかな電圧だけで 電流のON/OFFを切り替えられます。可動部品がないぶんリレーより約千倍速く状態が変わります。 この「小さな入力で大きな電流を制御する」仕組みは、次のセクションで見るトランジスタ (ベースの小さな電圧でコレクタからエミッタへの大きな電流を制御)へ、そのまま受け継がれます。
NPNトランジスタ
N型|P型|N型の3層を重ねただけの「固体」のスイッチ。ベース(B)にかける小さな電圧ひとつで、コレクタ(C)からエミッタ(E)へ流れる大きな電流をON/OFFできる。真空管の格子(G)が果たしていた役割を、ベースがそのまま引き継いでいる。真空も加熱も要らないこの部品が、現代のCPUに数十億個詰め込まれている。
関連する講: 第11講「そろばんからマイクロプロセッサへ」
豆電球(外部回路): 消灯
ベース(B)の電圧が0V ― コレクタ(C)からエミッタ(E)へ電流は流れず、事実上トランジスタはオフです。豆電球は消灯したまま。
| ベース電圧 | コレクタ→エミッタの電流 | 豆電球 |
|---|---|---|
| 0V(電圧なし) | 流れない | 消灯 |
| 小さな電圧をかける | 大きな電流が流れる | 点灯 |
NPNトランジスタは、N型・P型・N型の半導体を重ねただけの「固体」のスイッチです。 ベースにかける小さな電圧ひとつで、コレクタからエミッタへ流れる大きな電流をON/OFFできます。 真空管との対応でいえば、格子(G)の役割をベース(B)が、陰極(K)側をエミッタが、陽極(A)側をコレクタが受け持っています。 フィラメントの加熱も真空も要らないため、真空管よりずっと小さく、低電力で、長持ちします。
現実をビットに変換する
音や文字のような現実の情報を、0と1の列に変換して運ぶ。
アナログ→デジタル変換
連続した波を一定間隔で切り取り(サンプリング)、決まった段階に丸める(量子化)。サンプリングレート・ビット深度・ノイズの3つを動かして、デジタル化が何を取りこぼし、何をノイズから守るのかを確かめられる。
サンプリングは連続時間の波を一定間隔で切り取る操作、量子化は切り取った値を 2のビット深度乗個の段階(レベル)のどれかに丸める操作です。サンプリングレートを上げるほど波形の形を取りこぼしにくくなり、 ビット深度を上げるほど丸め誤差(量子化誤差)が小さくなります。ノイズを上げると量子化する前の生信号そのものが乱れ、 その乱れが下の2進数ストリームにそのまま刻まれることが分かります。
文字コード分解
入力欄に文字を打つと、各文字に割り当てられた7ビットのコードが16進と2進で1つずつ並ぶ。同じアルファベットの大文字と小文字を両方入れると、両者の差がちょうど20h——2進ではビット1つ分——であることが光って見える。ASCIIの設計の気配りを指先で確かめられる。
関連する講: 第13講「ASCIIと文字コードの舞台」
4文字 / 最大16文字(1文字 = 7ビットのコード)
同じアルファベットの大文字と小文字(例: C と c)を両方入力すると、ペアがハイライトされます。
キーを1つ打つたびに、その文字に割り当てられた7ビットのコードが1つ増えていきます。英字の2進表示で ピンク色の枠が付いているのが20h(=32)の位のビットで、大文字と小文字はこの1ビットしか 違いません。「大文字⇄小文字」を押すと全部の英字が一斉に入れ替わりますが、変わっているのは 各文字のこのビットだけ——並べ替えも大小変換もコードの計算だけで済むという、ASCIIの設計の気配りを 指先で確かめてみてください。
IEEE754単精度ラボ(小数を32ビットで表す)
32ビットのどれか1つをタップして反転させると、10進の値がその場で計算し直される。符号のビットは正負だけを入れ替え、指数のビットは値を2の累乗の単位で大きく飛ばし、有効部小数のビットは同じ枠の中を細かく刻む——同じ1ビットでも、どの区画にあるかで効き方がまるで違うことが目で確かめられる。
関連する講: 第16講「不動点、浮動点」
ビットをタップすると0と1が入れ替わり、下の10進の値がその場で変わります(上の数字はビット番号)。
- 符号 s
- 0 → 正の数
- 指数 e
- 保存値 127 − バイアス 127 = 実際の指数 0
- 有効部
- 1.0
- 32ビット全体
- 0x3F800000
正規化された形: 1.0 × 20
このシミュレータの本題である正規化数のパターンです。値は (−1)ˢ × 1.f × 2⁽ᵉ⁻¹²⁷⁾ で決まります。
符号のビットを反転すると、値の大きさはそのままで正負だけが入れ替わります。指数のビットを動かすと、 値は2の累乗の単位で大きく飛びます。有効部小数のビットは、暗黙の1のうしろに続く桁を足し引きして、 同じ2の累乗の枠の中を細かく刻みます——同じ1ビットでも、どの区画にあるかで効き方がまるで違います。 指数のビットをすべて0またはすべて1にすると、ゼロ・非正規化数・無限大・NaNという特別なパターンに入ります。 そのとき (−1)ˢ × 1.f × 2⁽ᵉ⁻¹²⁷⁾ の式は使えないので、どのパターンなのかを値のとなりに表示しています。
記憶して、実行する
「覚える回路」と「命令を繰り返し実行する仕組み」が揃うと、コンピュータになる。
RSフリップフロップ(1ビットの記憶)
NORゲート2つの出力を互いの入力へ戻すだけで、回路は入力が消えたあとも1ビットを覚え続ける。Setを一度ONにしてからOFFへ戻してもQが1のまま残る「保持」が主役。SetとResetを両方ONにすると、QとQ̄が反対でなくなる「禁止状態」も再現できる。
関連する講: 第8講「フィードバックとフリップフロップ」
保持中(直前の状態を維持)
| S | R | 動作 |
|---|---|---|
| 0 | 0 | 保持(直前のQを維持) |
| 1 | 0 | Set → Q = 1 |
| 0 | 1 | Reset → Q = 0 |
| 1 | 1 | 禁止(同時ONは不可) |
RSフリップフロップはNORゲート2つを互いにフィードバックさせただけの、最も単純な1ビットの記憶回路です。 SetでQ=1、ResetでQ=0にでき、両方OFFの間は最後にセット/リセットした状態を保ち続けます。 Setを一度ONにしてからOFFへ戻しても、Qが1のまま変わらない——この「保持」が、 コンピュータが1ビットを覚えておくための最小構成の原型です。
8×1 RAMアレイ
3個のスイッチが作る3ビットのアドレスが、8個のラッチのうちどれを読み書きするかを決める。デコーダが運ぶのはデータの値ではなく「ライト信号」で、選ばれた1個だけが書き換わる。いくつかのラッチに違う値を書いてからアドレスを切り替えると、それぞれの値が保存されたまま好きな順で読み出せる。
関連する講: 第9講「バイトとメモリ」
アドレス 000 → ラッチ0 を選択中
3個のスイッチが作る3ビットのアドレスが、8個のラッチのうちどれを読み書きするかを決めています。 書き込みのとき、デコーダが運ぶのはデータの値ではなくライト信号です。 データインの値は8個すべてのラッチに共通配線で届いていて、アドレスで選ばれた1個のW端子だけが 有効になるので、そのラッチだけが書き換わります。読み出し側では、同じアドレスを受け取ったセレクタが 8本のデータアウトから1本を選びます。いくつかのラッチに違う値を書き込んでからアドレスを切り替えると、 それぞれの値が保存されたまま、好きな順序で読み出せることを確かめられます。
バスの読み込み(部品をつなぐ4本の信号)
マイクロプロセッサがRAMから1つの値を読み込むとき、4本の信号は同時にではなく決まった順序で働く。アドレスを出す→制御信号で「読み込む」ことを伝える→RAMが中身を返す→受け取る、の一巡を1ステップずつ追える。アドレスを出しただけではRAMが応答しない点に注目してほしい。
関連する講: 第14講「バスに乗る」
バスのどのレーンにも信号は出ていません。読み込むアドレスを選び、「次のステップ」を押すと読み込みの一巡が始まります。
「次のステップ」を押すたびに、読み込みの一巡が1段階ずつ進みます。 まずマイクロプロセッサがアドレス信号にアドレスを出しますが、 それだけではRAMは応答しません。続いて制御信号が「読み込む」ことを伝えて、 はじめてRAMが中身をデータ入力信号に出します。アドレス信号と制御信号は、RAMが応答するまで 出したままである点にも注目してください。ここで値が流れる線が 「データ入力」と呼ばれるのは、マイクロプロセッサを基準にした呼び名だからです。 同じ1本の線でも、RAMの側から見れば自分が出しているデータ出力になります。読み出すアドレスを 選び直すと、その場所の中身が届くまでを何度でも確かめられます。
自動加算器(止まれない機械)
RAMに並べた数をカウンタが順に指し、累算器へ足し込んでいく。正しい合計が出てもカウンタは止まらず、末尾を過ぎると先頭へ巻き戻って同じ数を二重に足してしまう。「止まれ」をメモリの中に書いておく=停止命令という発想の転換が、なぜ必要だったのかを体験できる。
関連する講: 第10講「オートメーションの夢」
待機中
RAMアレイ(8番地に縮小)
色付きのマスが、カウンタの指している番地です
0〜2番地に3つの数が入っています。合計は50になるはずです。マシンを止める仕組みは、どこにもありません。
この自動加算器には「止まる」という動作そのものがありません。3つの数を足し終えて正しい合計50が出ても、 カウンタは素知らぬ顔で進み続け、末尾の次には0番地へ巻き戻って、足したはずの数をまた足してしまいます。 機械を正しく止めるには、部品を増やすのではなく、「止まれ」という指示=停止命令をメモリの中に 書いておくという発想の転換が必要です。次のセクションで、この「命令」という発想が マシン全体を作り替えていきます。
CPUシミュレーター(フェッチ・デコード・実行)
「1ステップ実行」を押すたびに、プロセッサがフェッチ(命令を読み込む)→デコード(解読する)→実行の3段階を1つずつ進める。命令は1〜3バイトの可変長なので、プログラムカウンタは命令の長さのぶんだけ進む。条件ジャンプでループが回り、停止命令で止まるまでを追える。
関連する講: 第12講「2つの古典的マイクロプロセッサ」
PC=0000h の命令「MVI A,5」(2バイト)をメモリから読み込む
| 番地 | ラベル | 命令 | バイト数 |
|---|---|---|---|
| 0000h | MVI A,5 | 2 | |
| 0002h | loop: | STA 2000h | 3 |
| 0005h | DCR A | 1 | |
| 0006h | JNZ loop | 3 | |
| 0009h | STA 2000h | 3 | |
| 000Ch | HLT | 1 |
「1ステップ実行」を押すたびに、プロセッサはフェッチ(命令を読み込む)→デコード(命令を解読する)→ 実行(実際に動かす)の3段階を1つずつ進めます。MVIが累算器Aに即値5をロードし、STAがその値を メモリの2000h番地へ書き込み、DCRがAを1減らします。結果がまだ0でなければZeroフラグはセットされず、 JNZ(条件ジャンプ)がプログラムカウンタをloopの番地へ書き戻すので、同じ区間が繰り返されます。 Aが0になるとジャンプは行われず、最後のSTAが0を書き込んでHLTで停止します。 番地の進み方にも注目してください——命令は1〜3バイトの可変長なので、 PCは命令の長さのぶんだけ進みます。
フレームバッファ
8×8=64ピクセルをタップすると、メモリ上の対応するビットが1つだけ書き換わる。1ピクセル=1ビットなので、ちょうど1行が1バイト。メモリに並んでいるのはただの0と1の列にすぎず、ディスプレイという文脈がそれを白と黒として解釈することで、初めて「絵」になる。
関連する講: 第18講「グラフィカル革命」
① 画面:8×8=64ピクセル(タップで白黒が反転)
② メモリ(フレームバッファ):64ビット=8バイト
ビット1(黒いピクセル): 0 / 64
このグリッドは1ピクセルに1ビットを割り当てているので、色数は2の1乗=2色(白黒)です。 ピクセルをタップするたびに、フレームバッファの対応するビットが1つだけ書き換わります。 8×8のグリッドではちょうど1行が1バイトです。メモリに並んでいるのはただの0と1の列に すぎず、ディスプレイという文脈がそれを白と黒として解釈することで、初めて「絵」になります。
人間の言葉でソフトウェアを書く
CPUが理解するのは二進数の命令だけ。人間が読めるコードとの橋渡しをするのがコンパイラ。
コンパイラの対応表
高級言語の1行が、アセンブリ言語の何命令に展開されるか。宣言・代入・数式・ループ・条件分岐をタブで切り替え、行をクリックすると相手側の対応行が光る。宣言文は命令を1つも生まないこと、for文のたった1行が10行以上の命令に膨らむことが目で見える。
関連する講: 第17講「高級言語、低級言語」
宣言文 integer a; は、変数の名前と種類(整数)をコンパイラに知らせるだけで、マシンコード命令には展開されません。いっぽう代入文 a := 5; は「アキュムレータAに即値5を転送する」「Aの値を変数aの番地へ保存する」の2命令になります。変数の名前はコンパイル後には残らず、ただのメモリの番地になります。
1つのCPUを分け合う
複数のプログラムが「同時に」動いて見えるのは、OSによる高速な入れ替えのおかげ。
時分割(マルチタスク)
3つのプログラムが同時に動いて見えるのは、1つのCPUを持ち時間ごとに順番に使っているだけ。「1ステップ」で進めると、持ち時間切れ→割り込み→実行位置の退避→次のプログラムの復元、という切り替えが1回ずつ進む。切り替え回数が積み上がるほど「同時実行」に見えてくる。
関連する講: 第15講「オペレーティングシステムの誕生」
CPUを使用中:ブラウザ
- 「再生」または「1ステップ」を押すと、割り込みと切り替えのログがここに表示されます
3つのプログラムは同時に動いているように見えますが、実際は1つのCPUを持ち時間ごとに 順番に使っているだけです。持ち時間が切れると割り込みが入り、オペレーティングシステムが 実行位置やレジスタの中身を退避してから、次のプログラムの状態を復元してCPUを渡します。 複数の端末に同時対応しているように見せる時分割(タイムシェアリング)も、 複数のプログラムを同時に走らせるマルチタスクも、この高速な切り替えの繰り返しでできています。
コンピュータ同士を会話させる
データを小さな断片に分けて運ぶ設計が、インターネットの頑健さを支えている。
パケット交換
データは宛先付きの小さなパケットに分割され、ルーターからルーターへそれぞれ自分の経路で運ばれる。途中のリンクを切断しても、パケットが自動で迂回して届く様子を試せる。
ブラウザ
「▶ 5パケット送信」を押すと、youtube.com からブラウザへ5つのパケットが送られます。
パケット交換では、送信順とネットワーク内の経路は必ずしも一致しません。ルーターBを切断すると、そこを通るはずだったパケットは自動的に別の経路(A・C)へ迂回します。経路ごとに通過にかかる時間が違うため、先に送ったパケットの方が後に届くこともあります。それでも受信側では届いた順にパケットを並べ直すことで、元のデータを正しく復元できます。
ページが表示されるまで(DNS・TCP・TLS・HTTP)
URLを入力してからページが描画されるまでに、DNSでの名前解決、TCPの3ウェイハンドシェイク、TLSでの暗号化鍵の合意、HTTPのやり取りという8ステップが毎回走っている。その全体を1ステップずつ再現する。
Webページを開くたびに、まずDNSでドメイン名をIPアドレスに変換し(電話帳を引く作業)、 次にTCPで接続を確立し(電話をかけて相手が出るのを待つ作業)、 TLSで相手の身元を確かめて暗号化鍵に合意し(盗聴されない専用線に切り替える作業)、 最後にHTTPでページの中身をやり取りします。URLを入力した瞬間、この4層の通信が舞台裏で毎回行われています。