🖥️
概念 #CODE #OS #アセンブリ #コンパイラ #機械語 #プログラミング言語 #インターネット 📚 CODEコンピュータのからくり

OSとプログラミング:機械語から高水準言語まで

周辺機器・割り込み・OSの役割から、機械語→アセンブリ→コンパイラ→OSの抽象化の積み重ねまで。H.G. Wellsの「World Brain」とインターネットの接点も。CODE第2版 Ch.24-28。

ここまでの積み上げ

信号とコード → 電気と論理ゲート → 数値体系
→ 算術回路(加算・減算)→ 記憶(FF・RAM)→ CPU

CPU が完成した。次の問い:「この機械に何をさせるか」

周辺機器とI/O

CPU と外の世界(キーボード・ディスプレイ・ストレージ)をつなぐ仕組み。

【I/O の2方式】

メモリマップドI/O:
  I/O デバイスをメモリアドレスの一部として扱う
  「アドレス 0xFF00 に書き込む」= キーボードコントローラへの指示
  アドレスバスとデータバスを共用できる

ポートマップドI/O(Intel 8080方式):
  IN  命令:指定ポートからデータを読む
  OUT 命令:指定ポートへデータを書く
  メモリアクセスとは別の制御線で区別

割り込み(Interrupt)

問題:CPUはキーボード入力がいつ来るかわからない

解決策1(ポーリング):ループで「何か入力があったか?」を繰り返し確認
  → CPU時間を無駄に消費

解決策2(割り込み):
  デバイス → CPU に INT 信号を送る
  CPU → 現在の作業を中断 → 現在の状態(レジスタ)をスタックへPUSH
      → 割り込みハンドラ(Interrupt Service Routine)へジャンプ
      → ハンドラ完了後 → RETI で元の作業に復帰

  現代OS の I/O 処理はほぼすべて割り込みベース

オペレーティングシステムの役割

CPU・メモリ・デバイスを直接操作すると、アプリ開発者はハードウェアの詳細を全部知る必要がある。OS はその複雑さを隠す。

OSの主な役割:

1. リソース管理
   CPU時間の分配(スケジューリング)
   メモリの割り当て・回収
   デバイスアクセスの調停

2. 抽象化(API の提供)
   「ファイルを読む」→ 実際の物理セクタ位置はOSが管理
   「ソケットで送信」→ NICドライバ・TCP/IP スタックはOSが隠蔽

3. 保護(プロセス間の隔離)
   あるプロセスが他のプロセスのメモリを壊せないようにする
   カーネルモード / ユーザーモードの分離

4. ファイルシステム
   バイト列の羅列を「ファイルとディレクトリ」として見せる

機械語:CPUが直接理解する言語

CPU が実行できるのは機械語のバイト列のみ。Intel 8080 の例:

メモリ上の機械語(16進数で表示):

  アドレス  バイト
  0000:    3E 05   ; MVI A, 5    (A ← 5)
  0002:    06 03   ; MVI B, 3    (B ← 3)
  0004:    80      ; ADD B       (A ← A + B = 8)
  0005:    32 10 00; STA 0x0010  (0x0010番地 ← A)
  0008:    76      ; HLT

人間には読みにくい。また:
  ・アドレスを手で計算する必要がある
  ・CPU が変わると全部書き直し

アセンブリ言語

機械語の「人間向けニーモニック表現」。アセンブラ(プログラム)が機械語に変換する。

機械語      → アセンブリ言語
─────────────────────────────
3E 05       → MVI A, 5
06 03       → MVI B, 3
80          → ADD B
32 10 00    → STA result
76          → HLT

特徴:
  1命令 = 1機械語命令(ほぼ1対1)
  ラベルが使える(アドレスを自動計算)
  人間に読みやすいが CPU 依存
  用途:デバイスドライバ・BIOS・高速化が必要な部分

高水準言語とコンパイラ

機械語やアセンブリはCPU依存で可搬性がない。高水準言語は CPU を意識せずに書ける。

抽象化の積み重ね:

  if (x > 0) { result = x * 2; }   ← C言語

  コンパイラ(GCC, Clangなど)が変換

  CMP x, 0       ← アセンブリ
  JLE end
  MOV result, x
  SHL result, 1   ← ×2 は左シフトで実現
  end:

  機械語バイト列   ← CPU が実行

コンパイラの仕事:
  字句解析 → 構文解析 → 意味解析 → 最適化 → コード生成

インタープリタとの違い

コンパイラ:
  実行前にソース全体を機械語へ変換
  実行速度が速い(C, Rust, Go など)

インタープリタ:
  実行時に1行ずつ解釈・実行
  開発が柔軟(Python, Ruby など)
  現代は JIT コンパイルで速度向上(V8 の JavaScript など)

ジャンプとループとサブルーチン(Ch.24)

高水準言語の制御構造は、すべてジャンプ命令に変換される。

if文:
  if (A == 0) { ... } else { ... }
  →  CMP A, 0
     JNZ else_label
     ...(thenブランチ)
     JMP end
  else_label:
     ...(elseブランチ)
  end:

forループ:
  for (i = 0; i < 10; i++) { ... }
  →  MVI i, 0
  loop:
     CMP i, 10
     JGE end
     ...(ループ本体)
     INR i
     JMP loop
  end:

関数呼び出し:
  func(a, b)
  → 引数をスタックにPUSH
  → CALL func_addr
  → 戻り値をレジスタ or スタックから受け取り

OS の歴史的な積み重ね

1940年代:プログラムを手でパネルに打ち込む

1950年代:バッチ処理OS(IBSYS)
   カードリーダーから一括入力、順番に実行

1960年代:タイムシェアリング(Multics, Unix)
   複数ユーザーが1台を同時に使う
   プロセス・スケジューリングの誕生

1970年代:Unix の広まり
   「すべてはファイル」という哲学
   C言語での OS 記述 → 移植性の革命

1980年代:パーソナルコンピュータ(CP/M, MS-DOS)
   一人1台の時代。GUI(Macintosh, Windows)

1990年代〜:Linux, Windows NT
   ネットワーク対応・マルチタスク・保護メモリ

The World Brain:最終章

本書の締めくくり(第28章)は技術から少し離れ、思想的な展望に触れる。

H.G. Wells(1866-1946)の「World Brain」(1938):

  「世界中の知識を一箇所に集め、誰でもアクセスできる
   百科事典のような組織を作るべきだ」

Wells は電子コンピュータが生まれる前にこのビジョンを提唱した。

→ インターネット(1969 ARPANET)
→ World Wide Web(1991, Tim Berners-Lee)
→ Wikipedia(2001)
→ 検索エンジン・LLM(現代)

「一人の人間が持てる知識は限られている。
 しかし世界の知識を繋いだネットワークなら?」

28章のボトムアップを振り返る

懐中電灯の点滅
  ↓ スイッチを電気で制御する
リレー・論理ゲート
  ↓ ゲートで演算する
加算器・ALU
  ↓ 値を記憶する
フリップフロップ・RAM
  ↓ 演算と記憶を統合する
CPU(フェッチ→デコード→実行)
  ↓ CPU に命令を与える
機械語・アセンブリ・高水準言語
  ↓ 多くのプログラムを協調させる
オペレーティングシステム
  ↓ コンピュータをネットワークで繋ぐ
インターネット・World Wide Web

「すべては 0 と 1 から始まった」

参考:現代との接点

本書が扱うのは 1970〜80年代の技術(Intel 8080)だが、原理は現代も同じ。

本書の概念現代の実装
リレー → 論理ゲートCMOS トランジスタ(数十億個/チップ)
8ビット ALU64ビット AVX-512 SIMD(1命令で512ビット演算)
8080 の 8 レジスタx86-64 の 16本の汎用レジスタ + SIMD
リプルキャリーアダーキャリー先見加算器(Carry Lookahead Adder)
単一CPUサイクルアウトオブオーダー実行・パイプライン・投機的実行
シリアル I/OPCIe Gen5(〜128GB/s)・USB4
64KB アドレス空間48ビット仮想アドレス(256TB)

出典: https://www.amazon.co.jp/dp/4296080245