🖥️
CPUの構造:ALU・レジスタ・バス・制御信号
算術回路とメモリを統合してCPUを組み立てる。ALU・レジスタアレイ・データバス・フェッチ→デコード→実行サイクルをIntel 8080を例に解説。CODE第2版 Ch.20-23。
ここまでの積み上げ
スイッチ → 論理ゲート → 加算器・ALU (前前章)
→ フリップフロップ・RAM (前章)
↓
CPU(本章)
CPU は「ALU」と「制御装置」と「レジスタ」を組み合わせた機械。加算・比較・分岐・メモリアクセスを自動的に繰り返すことができる。
ALU(算術論理演算装置)
前のdocで加算器を作った。ALU はそれを拡張し、複数の演算を一つの回路に統合したもの。
【ALU の入出力】
8ビット A ──┐
├──[ALU]──→ 8ビット 結果
8ビット B ──┘ ↑
操作コード(何をするか)
操作コードの例:
000 = ADD (A + B)
001 = SUB (A - B)
010 = AND (A AND B)
011 = OR (A OR B)
100 = XOR (A XOR B)
101 = NOT A
110 = シフト左
111 = シフト右
ALU の出力フラグ:
Z(Zero) : 結果が 0
C(Carry) : キャリーアウト発生
S(Sign) : 結果の最上位ビット(符号)
V(Overflow) : 符号付き演算のオーバーフロー
レジスタアレイ
CPUの内部に置く高速な一時記憶。外部 RAM よりはるかに速い。
【Intel 8080 のレジスタ構成】
8ビットレジスタ × 7本:
A (アキュムレータ:演算の主役)
B, C(汎用レジスタ・ペア BC)
D, E(汎用レジスタ・ペア DE)
H, L(汎用レジスタ・ペア HL)
16ビットレジスタ:
SP(スタックポインタ)
PC(プログラムカウンタ)
フラグレジスタ(F):
Z / S / C / V / ... 各演算後に更新される
BC・DE・HL ペアは 16ビットアドレスとして使える
HL = H(上位8ビット) + L(下位8ビット)
→ メモリアドレス指定に使用
バス:データの「高速道路」
CPUの各部品(ALU・レジスタ・メモリ)をつなぐ共有の配線束。
【バスの種類】
データバス(8本 = 8ビット):
データそのものを運ぶ
CPU ↔ メモリ ↔ I/O デバイス
アドレスバス(16本 = 16ビット):
「どこのデータか」を指定
CPU → メモリ(一方向)
16ビット = 64KB のアドレス空間
制御バス(複数本):
WE(書き込み許可)
OE(読み出し許可)
CLK(クロック)
INT(割り込み要求)
RESET
【バス競合の解決】
複数の送信元が同時に同じバスに乗ることはできない
→ トライステートバッファで「使わないときはバスから切り離す」
High / Low / Hi-Z(高インピーダンス:バスから切り離し)
フェッチ→デコード→実行サイクル
CPUの動作は3ステップの繰り返し。
【命令実行サイクル(Fetch-Decode-Execute)】
┌─────────────────────────┐
↓ │
1. FETCH(取得) │
PC が指すアドレスからメモリを読む │
→ 命令レジスタ(IR)に格納 │
→ PC を +1(次の命令へ) │
↓ │
2. DECODE(解読) │
IR の内容を解析 │
→ 操作コード(opcode)の確認 │
→ オペランドが必要なら追加フェッチ │
↓ │
3. EXECUTE(実行) │
ALU・レジスタ・メモリを操作 │
→ 演算・データ転送・ジャンプ etc. │
│ │
└─────────────────────────┘
(繰り返し)
Intel 8080 の命令セット(抜粋)
命令形式(機械語):1〜3バイト
【データ転送命令】
MOV r1, r2 → レジスタ間コピー 1バイト
MVI r, d8 → 即値をレジスタへ 2バイト
LDA a16 → メモリ→Aレジスタ 3バイト
STA a16 → Aレジスタ→メモリ 3バイト
【算術・論理命令】
ADD r → A += r 1バイト
SUB r → A -= r 1バイト
INR r → r++ 1バイト
DCR r → r-- 1バイト
ANA r → A = A AND r 1バイト
【ジャンプ命令】
JMP a16 → PC = a16(無条件) 3バイト
JZ a16 → Zフラグが1のときジャンプ
JNZ a16 → Zフラグが0のときジャンプ
JC a16 → キャリーフラグが1のとき
例:10に1を足す機械語プログラム
アドレス 命令バイト ニーモニック 意味
0000 3E 0A MVI A, 10 A ← 10
0002 3C INR A A++
0003 76 HLT 停止
MVI A, 10 のバイト:
3E = オペコード(Aレジスタに即値をロード)
0A = 10 の16進表現
制御信号と制御装置
命令の各ステップで「どの回路を動かすか」を制御する。
【制御信号の役割(ADD命令の例)】
クロックサイクル 1(FETCH):
→ PC の値をアドレスバスへ出力
→ メモリのOEをON → データバスに命令バイト
→ IR にキャプチャ
→ PC += 1
クロックサイクル 2(DECODE):
→ IR の上位3ビットを解析 → ADD = 10000xxx
→ 下位3ビットからソースレジスタを特定
クロックサイクル 3(EXECUTE):
→ ALUへの入力にAレジスタとソースレジスタを選択
→ ALU の操作コードに ADD をセット
→ ALU 出力をAレジスタへ書き込み
→ フラグレジスタを更新
この「どのサイクルでどの制御信号をONにするか」を定めたのが制御装置(Control Unit)
スタックとサブルーチン
実際のプログラムでは同じ処理を「関数」として呼び出したい。
【スタック(LIFO)】
SP(スタックポインタ):スタックの先頭アドレスを指す
PUSH:SP-- して、SP の指すアドレスに値を書き込む
POP :SP の指すアドレスから値を読み込んで SP++
【CALL と RET (サブルーチン呼び出し)】
CALL addr:
1. PUSH PC(戻りアドレスをスタックに積む)
2. PC = addr(サブルーチンへジャンプ)
RET:
1. POP PC(スタックから戻りアドレスを取り出す)
2. PC = 戻りアドレス(呼び出し元へジャンプ)
ネスト(関数が関数を呼ぶ)は何段でも可能:
main → funcA → funcB
funcB の RET → funcA へ戻る
funcA の RET → main へ戻る
CPUの全体像
┌─────────────────────────────────────────┐
│ CPU │
│ │
│ ┌──────────┐ ┌────────────────────┐│
│ │プログラム │←→ │ レジスタアレイ ││
│ │カウンタ │ │ A, B, C, D, E, ││
│ │(PC) │ │ H, L, SP, flags ││
│ └────┬─────┘ └──────────┬─────────┘│
│ │ │ │
│ ┌────▼─────┐ ┌──────────▼─────────┐│
│ │命令レジスタ│ │ ALU ││
│ │(IR) │ │ +,-,AND,OR,XOR ││
│ └────┬─────┘ └──────────┬─────────┘│
│ │ │ │
│ ┌────▼─────────────────────▼─────────┐│
│ │ 制御装置(CU) ││
│ │ 「今何をすべきか」を各回路に指示 ││
│ └──────────────────────┬─────────────┘│
└─────────────────────────┼──────────────┘
│
┌───────────────┼───────────────┐
│ │ │
アドレスバス データバス 制御バス
│ │ │
┌──────▼───────────────▼───────────────▼──────┐
│ メモリ(RAM/ROM) │
└──────────────────────────────────────────────┘
加算器・フリップフロップ・レジスタ・RAM、すべてが一つの「計算機械」として統合された。次はこの機械に何を命令するか — プログラムと OS の話へ。
- 1. 📖CODE:コンピュータのからくり — シリーズ概要
- 2. 📡信号とコード:点字・モールス・情報伝達の原理
- 3. ⚡電気とリレー:懐中電灯から論理ゲートへ
- 4. 🔢数の体系:2進数・16進数・ASCIIからUnicodeへ
- 5. ➕算術回路:加算器・2の補数・減算の実装
- 6. 💾記憶と時計:フリップフロップ・クロック・RAM
- 7. 🖥️CPUの構造:ALU・レジスタ・バス・制御信号
- 8. 🖥️OSとプログラミング:機械語から高水準言語まで
出典: https://www.amazon.co.jp/dp/4296080245