← Máy tính hoạt động thế nào?

Bài 6 · Nâng cao · 30 phút· Cập nhật 11/06/2026

Mô hình CPU 8-bit

Biên soạn bởi Nguyễn Anh Tuấn

Mô phỏng CPU 8-bit tương tác: ráp thanh ghi (register), RAM, ALU và xung nhịp; xem chu trình Nạp → Giải mã → Thực thi chạy một chương trình thật.

Đây là phần ráp tất cả lại: một CPU 8-bit hoàn chỉnh với RAM, các thanh ghi, ALU (bộ cộng ở Bài 2) và xung nhịp (Bài 1). Chọn một chương trình mẫu, bấm “Một bước” để xem từng nhịp, hoặc tự viết chương trình của riêng bạn.

Chọn chương trình
Bảng mạch CPU
RAM 16×8-bit
0
30
1
47
2
224
3
240
4
0
5
0
6
0
7
0
8
0
9
0
10
0
11
0
12
0
13
0
14
5
15
3
Thanh ghi lệnh (IR)
00000000 · NOP
Bộ đếm CT (PC)
Trỏ tới ô: 0
Bộ điều khiển
Đang chờ…
Bus dữ liệu
Thanh ghi A
0 · 00000000
Thanh ghi B
0 · 00000000
ALU
Bộ số học · cộng/trừ
ZERO = 0 CARRY = 0
Đèn kết quả
-
Nhật ký

Chưa có bước nào. Nhấn “Một bước” hoặc “Chạy”.

Tự viết chương trình
0 0001 1110 LDA 14
1 0010 1111 ADD 15
2 1110 0000 OUT
3 1111 0000 HLT
14 0000 0101 DAT 5
15 0000 0011 DAT 3
Sẵn sàng

Nhấn “Một bước” để chạy chậm từng nhịp, hoặc “Chạy” để tự động.

nhịp: 0

Mỗi lệnh đi qua ba nhịp: Nạp (lấy byte lệnh từ RAM vào IR) → Giải mã (bộ điều khiển đọc opcode) → Thực thi (làm việc: cộng, lưu, nhảy…). Rồi PC tăng và lặp lại. Bấm “Một bước” và để ý màu khối sáng lên theo từng nhịp.

PCcon trỏ lệnhRAM16 ô: lệnh + dữ liệuđịa chỉIRlệnh hiện tạiGiải mãlệnh này làm gì?nạp lệnhđiều khiểnAtích luỹBtoán hạngALUCờ Z, COUTkết quả
Các khối của CPU và đường đi của lệnh/dữ liệu (sơ đồ đơn giản hoá theo mô hình dạy học).
lặp lại; PC + 1 mỗi vòngNạplấy lệnh ở ô PCGiải mãlệnh này làm gì?Thực thilàm + cập nhật A, cờ
Chu trình CPU lặp mãi: Nạp lệnh ở ô PC → Giải mã → Thực thi, rồi PC tiến một ô.
  • PC trỏ tới ô lệnh kế tiếp; sau mỗi lệnh PC + 1.
  • IR giữ byte lệnh; 4 bit đầu = opcode, 4 bit sau = tham số.
  • JMP/JZ thay đổi PC để tạo vòng lặp và rẽ nhánh.

Chỉ 10 lệnh (9 lệnh chính + NOP), mỗi byte gồm opcode (nibble cao) + tham số (nibble thấp):

LDA n - nạp ô n vào A ADD n - A += ô n SUB n - A −= ô n STA n - lưu A vào ô n LDI n - nạp thẳng n JMP n - nhảy tới ô n JZ n - nhảy nếu cờ ZERO bật (kết quả ADD/SUB = 0) OUT - hiện A ra đèn HLT - dừng NOP - không làm gì

Lưu ý: đây là tập lệnh dạy học, không phải hợp ngữ chuẩn

Tập lệnh này tự tạo và đơn giản hoá để học - không phải hợp ngữ tiêu chuẩn như x86/ARM dùng trong máy thật. Tên lệnh theo quy ước CPU thật (vd chip 6502), và mô hình thuộc dòng dạy học kinh điển SAP-1 / máy 8-bit của Ben Eater. Bạn sẽ tập viết loại lệnh này ở Bài “Lập trình cho CPU”.
  • 16 ô RAM, mỗi ô 1 byte; thanh ghi A, B, IR, PC + cờ ZERO, CARRY.
  • Cố tình BỎ bộ nhớ đệm (cache) để nhìn rõ từng lần đọc RAM.
  • Giới hạn 8-bit: A chỉ 0-255 - quá ngưỡng là TRÀN SỐ và dừng (cảnh báo “ồn ào”, không âm thầm).

Trung thực

Đây là mô hình đơn giản hoá để hiểu nguyên lý. CPU thật phức tạp hơn nhiều (pipeline, cache, nhiều nhân…), nhưng chu trình Nạp → Giải mã → Thực thi thì vẫn đúng như vậy.

Câu hỏi thường gặp

Con người viết hợp ngữ (vd LDA 14), trình dịch đổi thành mã máy nhị phân, rồi đặt sẵn các byte đó vào RAM trước khi CPU chạy. Bạn tự làm điều này ở khu “Tự viết chương trình” rồi bấm “Nạp vào CPU”.

Nhãn chỉ là tên thay cho số địa chỉ, để khỏi đếm thủ công. Khi dịch, JMP lap được đổi thành JMP tới đúng ô mà nhãn lap: đứng - nhìn khu “Nạp vào CPU” sẽ thấy nhãn biến mất, chỉ còn con số.

“Một bước” chạy đúng một nhịp xung rồi dừng để quan sát thật chậm. “Chạy” là xung nhịp tự động lặp lại, tốc độ chỉnh bằng thanh trượt (như đổi “GHz”).

Mỗi nhịp ghi lại một dòng. Nhấn vào một dòng cũ để “tua lại” - bảng mạch quay về đúng trạng thái lúc đó. Rất hữu ích khi cần giảng lại một bước.

Để giữ mô hình đủ nhỏ mà vẫn thấy rõ nguyên lý. Nhân là cộng nhiều lần; chia là trừ nhiều lần. CPU thật có thêm khối nhân/chia, nhưng tất cả vẫn xây trên bộ cộng (xem Bài 2).

Tick những điều em tự tin làm được. Càng lên cao, em càng hiểu sâu.

Tick những điều em tự tin làm được sau khi học bài này. 0/6

Trả lời vài câu để chắc rằng em đã nắm bài.

Câu 1/3 Điểm: 0

Chu trình ba nhịp mà mỗi lệnh đi qua trong mô hình CPU là gì?

  1. 1

    Đọc chương trình

    Chương trình “LDI 6OUTHLT” in ra số mấy ở đèn kết quả?

    Hoàn thành khi: 6 - LDI nạp thẳng 6 vào A, OUT đưa A ra đèn.

  2. 2

    Chạy nhẩm (dự đoán)

    Giả sử ô 14 = 7, ô 15 = 5. Chạy nhẩm “LDA 14ADD 15OUTHLT”: sau mỗi lệnh A bằng mấy, đèn hiện số nào? Gõ thêm ORG 14 / DAT 7 / DAT 5 để tự kiểm tra.

    Hoàn thành khi: Sau LDA 14: A = 7; sau ADD 15: A = 12; đèn hiện 12.

  3. 3

    Viết: tính 9 − 4

    Viết chương trình tính 9 − 4 rồi hiện kết quả. Gợi ý: đặt số 4 vào ô nhớ bằng ORG + DAT, dùng LDI 9 rồi SUB.

    Hoàn thành khi: Nạp không lỗi, chạy tới khi dừng, đèn hiện 5. (Mẫu: LDI 9 / SUB 15 / OUT / HLT / ORG 15 / DAT 4.)

  4. 4

    Viết: tính 3 + 4 + 5

    Viết chương trình tính tổng 3 + 4 + 5 và hiện kết quả. Gợi ý: LDI 3 rồi ADD hai ô chứa 4 và 5.

    Hoàn thành khi: Đèn hiện 12. (Mẫu: LDI 3 / ADD 14 / ADD 15 / OUT / HLT / ORG 14 / DAT 4 / DAT 5.)

  5. 5

    Tìm lỗi

    Chương trình “LDI 5ADD 15OUT” với (ORG 15, DAT 3) đáng lẽ hiện 8 rồi dừng, nhưng nó chạy mãi không dừng. Tìm và sửa lỗi.

    Hoàn thành khi: Thiếu HLT sau OUT: thêm HLT → đèn hiện 8 và CPU dừng hẳn (không chạy lan vào vùng dữ liệu).

  6. 6

    Giới hạn phần cứng

    (a) A đang là 200 mà cộng thêm 100 thì điều gì xảy ra, vì sao? (b) Vì sao không thể viết phép nhân tổng quát bằng vòng lặp gói trong 16 ô?

    Hoàn thành khi: (a) 200+100 = 300 > 255 → TRÀN SỐ, CPU dừng, cờ CARRY bật (8-bit chỉ chứa 0-255). (b) nhân-vòng-lặp cần ~13 lệnh + dữ liệu > 16 ô; lại chỉ có JZ nên khó điều khiển vòng đếm - giới hạn thật của phần cứng nhỏ.