Cổng logic & bộ cộng — bên dưới ALU

Trong mô hình CPU, khối ALU “cộng” hai số. Nhưng cộng thực sự xảy ra thế nào trong silicon? Không có phép cộng kỳ diệu nào cả — chỉ có vài cổng logic bật/tắt, ghép lại. Đi từ một cổng đến bộ cộng 8-bit hoàn chỉnh.

Logic số · dành cho lập trình viên & học sinh khá
1

Một cổng logic là gì? logic gate

Mọi thứ trong CPU rút gọn về bit: chỉ 0 hoặc 1 (thấp/cao điện áp). Một cổng logic nhận một hoặc hai bit vào và cho ra một bit, theo một quy tắc cố định. Đây là viên gạch nhỏ nhất. Bấm vào các nút input để bật/tắt và xem output đổi theo:

Đầu vào:
Ra 0
Bảng chân trị (truth table)
AND: ra 1 chỉ khi cả hai vào là 1. OR: ra 1 khi có ít nhất một vào là 1.
NOT: đảo bit (1→0, 0→1). XOR: ra 1 khi hai vào khác nhau — sẽ rất quan trọng ở bước sau.
Cổng logic được làm từ vài transistor — công tắc điện tử tí hon. Một con chip có hàng tỉ transistor, tức hàng tỉ cổng như thế này.
2

Cộng 1 bit + 1 bit: bộ bán cộng half-adder

Thử bài toán nhỏ nhất: cộng hai bit. 0+0=0, 0+1=1, 1+0=1, và 1+1=? — bằng 2, nhưng một bit không chứa nổi số 2! Kết quả là 0 nhớ 1 (giống 9+1=10 trong hệ thập phân). Vậy ta cần hai bit ra: Tổng (Sum)Nhớ (Carry).

Điều kỳ diệu: Sum chính là A XOR B, và Carry chính là A AND B. Chỉ hai cổng. Bật/tắt A, B để kiểm chứng:

A B Carry 0 Sum 0
Bảng chân trị
Sum = A XOR B — đúng 1 khi hai bit khác nhau.
Carry = A AND B — chỉ “nhớ” khi cả hai cùng là 1 (trường hợp 1+1).
“Nhớ” quen không? Đây chính là cờ CARRY bạn thấy trong mô hình CPU. Khi cộng tràn, CARRY = 1.
3

Cộng có nhớ vào: bộ cộng đầy đủ full-adder

Bộ bán cộng thiếu một thứ: khi cộng số nhiều bit, mỗi cột còn phải nhận nhớ từ cột bên phải. Bộ cộng đầy đủ có ba đầu vào: A, B, và Cin (carry vào). Nó vẫn cho ra Sum và Cout (carry ra) — ghép từ hai bộ bán cộng và một cổng OR. Bật cả ba để xem:

A B Cin Cout 0 Sum 0
Bảng chân trị
Sum = A XOR B XOR Cin — tổng ba bit, lấy phần lẻ.
Cout = 1 khi có từ hai bit trở lên trong A, B, Cin là 1.
4

Ghép 8 cái lại: bộ cộng 8-bit 8-bit ripple-carry adder

Đây là mấu chốt. Xếp 8 bộ cộng đầy đủ cạnh nhau, một cái cho mỗi bit. Carry ra của bộ này nối vào carry vào của bộ bên trái — nhớ “gợn” từ phải sang trái, đúng như khi ta cộng tay. Đặt hai số (bấm vào bit để đổi), rồi bấm “Cộng” để xem nhớ lan từng bước:

A
= 0
B
= 0
nhớ
Tổng
= 0⚠ TRÀN — carry ra ngoài 8 bit
Ripple-carry: mỗi bit phải đợi nhớ từ bit phải → cộng tuần tự từ phải sang trái.
Nếu bit thứ 8 (ngoài cùng trái) vẫn đẻ ra nhớ → đó là TRÀN SỐ: kết quả vượt 255.
Chính là ALU của bạn. Khối ALU trong mô hình CPU làm đúng việc này. Khi nhớ tràn ra khỏi 8 bit, cờ CARRY bật và mô hình báo “Tràn số” rồi dừng. Giờ bạn biết cái “tràn” đó đến từ đâu: bit nhớ cuối cùng không còn chỗ.
5

Thế còn phép trừ? Số bù hai two's complement

CPU không cần mạch trừ riêng. Mẹo: trừ = cộng với số âm, và số âm được biểu diễn bằng số bù hai — đảo tất cả các bit rồi +1. Khi đó A − B trở thành A + (đảo B) + 1, dùng chính bộ cộng vừa xây. Thử xem −B được tạo thế nào:

B
= 5
đảo bit
(NOT B)
−B
đảo + 1 = 0
Vì sao +1? Để 0 chỉ có một cách biểu diễn và phép cộng “chạy vòng” khớp nhau.
Bit trái cùng thành dấu: 0 = dương, 1 = âm. Đây là lý do CPU 8-bit có dải −128…127.
Nối với mô hình CPU: mô hình hiện chỉ làm số 0–255 (không dấu) và dừng khi tràn — cố ý cho đơn giản. Số bù hai là cách CPU thật xử lý số âm bằng cùng một bộ cộng.
6

Toàn cảnh: từ transistor đến lệnh ADD the abstraction stack

Lùi lại nhìn cả chồng tầng. Mỗi tầng chỉ dùng tầng ngay dưới nó — đó là sức mạnh của trừu tượng hoá. Lập trình viên gõ a + b, và tận đáy là vài transistor bật/tắt:

Mỗi tầng giấu chi tiết tầng dưới. Bạn viết ADD mà không cần nghĩ tới XOR.
Đây là lý do cùng một CPU chạy được mọi phần mềm: tầng trên không phụ thuộc vật lý bên dưới.
Quay lại mô hình: lệnh ADD bạn chạy trong mô phỏng nằm ở tầng trên cùng. Mở mô hình CPU → và giờ bạn biết khối ALU đang giấu cả một rừng cổng logic bên trong.

?

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

Cổng logic được làm từ gì?

Từ transistor — về cơ bản là công tắc điện điều khiển bằng điện. Vài transistor mắc với nhau tạo thành một cổng (ví dụ cổng NAND dùng 4 transistor). Một CPU hiện đại có hàng chục tỉ transistor, khắc trên miếng silicon nhỏ hơn móng tay.

Vì sao Sum lại đúng bằng XOR?

Vì khi cộng hai bit, chữ số hàng đơn vị của kết quả là 1 chỉ khi đúng một trong hai bit là 1 (0+1 hoặc 1+0). Khi cả hai là 1, hàng đơn vị về 0 và sinh nhớ. “Đúng một trong hai” chính là định nghĩa của XOR.

“Ripple-carry” có phải cách nhanh nhất không?

Không — nó là cách dễ hiểu nhất. Vì mỗi bit phải đợi nhớ từ bit trước, bit cuối phải đợi cả chuỗi, nên chậm. CPU thật dùng các thiết kế nhanh hơn như carry-lookahead (tính trước nhớ song song). Nhưng kết quả cộng thì giống hệt.

Vì sao dùng số bù hai mà không phải “bit dấu” đơn giản?

Vì số bù hai cho phép dùng chung một bộ cộng cho cả cộng lẫn trừ, và chỉ có một cách biểu diễn số 0. Cách “bit dấu” ngây thơ tạo ra cả +0 và −0, và cần mạch riêng cho phép trừ — phức tạp và tốn hơn.

Nhân và chia cũng làm từ cổng logic à?

Đúng. Nhân có thể làm bằng cách cộng dịch (shift-and-add) lặp lại — về bản chất là nhiều bộ cộng. Trong mô hình CPU 8-bit, ta thấy điều này ở mức lệnh: phép nhân là cộng nhiều lần. Trong silicon, có cả khối nhân chuyên dụng ghép từ rất nhiều bộ cộng.

Cái này liên quan gì tới mô hình CPU 8-bit?

Trực tiếp. Khối ALU trong mô hình CPU chính là một bộ cộng 8-bit như ở bước 4. Cờ CARRY và trạng thái “Tràn số” bạn thấy khi cộng quá 255 chính là bit nhớ cuối cùng tràn ra khỏi 8 bit. Trang này mở nắp khối ALU đó ra.

Bài tập về nhà

6 bài để chắc chắn em hiểu sâu về cổng logic & bộ cộng. Mỗi bài có đề bài rõ ràng và mục “✅ Hoàn thành khi” để em biết thế nào là làm đúng. Bấm “In bài tập” để in ra giấy làm sau; mở “Đáp án” chỉ sau khi đã tự làm.

1

Điền bảng chân trị

Cơ bản

Cho hai bit AB. Hãy điền kết quả của AND, OR, XOR cho cả 4 tổ hợp: 00, 01, 10, 11.

✅ Hoàn thành khi: điền đúng — AND = 0,0,0,1; OR = 0,1,1,1; XOR = 0,1,1,0.

Đáp án
A B │ AND  OR  XOR
0 0 │  0    0    0
0 1 │  0    1    1
1 0 │  0    1    1
1 1 │  1    1    0
2

Bộ bán cộng (half-adder)

Vận dụng

Bộ bán cộng nhận hai bit a, b và cho ra Tổng (Sum)Nhớ (Carry). (a) Viết công thức của Sum và Carry theo cổng logic. (b) Với a=1, b=1 thì Sum và Carry bằng mấy?

✅ Hoàn thành khi: (a) Sum = a XOR b, Carry = a AND b; (b) với 1,1 → Sum = 0, Carry = 1 (tức 1+1 = “10” nhị phân).

Đáp án

1 + 1 = 10 trong nhị phân: bit tổng là 0, bit nhớ là 1. Đúng như Carry = AND (chỉ 1 khi cả hai cùng 1) và Sum = XOR (1 khi hai bit khác nhau).

3

Cộng nhị phân 8-bit

Vận dụng

Tính 0101 1010 + 0010 0011 (tức 90 + 35) bằng tay. Cho kết quả ở dạng nhị phânthập phân, và cho biết có bit nhớ tràn ra ngoài 8 bit không.

✅ Hoàn thành khi: ra 125 = 0111 1101, không tràn (kết quả ≤ 255, carry-out = 0).

Đáp án
  0101 1010   (90)
+ 0010 0011   (35)
-----------
  0111 1101   (125)   → carry-out = 0, không tràn
4

Khi nào thì tràn số?

Vận dụng

Tính 1100 1000 + 0101 0000 (tức 200 + 80) trong 8 bit. Điều gì xảy ra? Giá trị thực sự giữ lại trong 8 bit là bao nhiêu?

✅ Hoàn thành khi: nhận ra 200 + 80 = 280 > 255 → có bit nhớ tràn ra (carry-out = 1); 8 bit chỉ giữ 280 − 256 = 24 = 0001 1000. Trong mô hình CPU, đây chính là lúc báo TRÀN SỐ.

Đáp án
  1100 1000   (200)
+ 0101 0000   (80)
-----------
1 0001 1000   (280)
↑ bit thứ 9 = carry-out (tràn). 8 bit còn lại = 24.
5

Số bù hai: trừ bằng cách cộng

Nâng cao

(a) Biểu diễn −5 trong 8 bit bằng số bù hai. (b) Dùng nó để tính 9 + (−5) trong 8 bit và kiểm tra kết quả có bằng 4 không.

✅ Hoàn thành khi: (a) −5 = 1111 1011 (đảo bit của 5 rồi +1); (b) 0000 1001 + 1111 1011 = 1 0000 0100; bỏ bit tràn thứ 9 → 0000 0100 = 4 ✓.

Đáp án
5      = 0000 0101
đảo bit = 1111 1010
+1      = 1111 1011   (= −5)

  0000 1001   (9)
+ 1111 1011   (−5)
-----------
1 0000 0100   → bỏ bit thứ 9 → 0000 0100 = 4 ✓

Đây là lý do CPU chỉ cần một bộ cộng: phép trừ = cộng với số bù hai.

6

Nối sang Bài 3 (mô hình CPU)

Vận dụng

Mở Bài 3 — Mô hình CPU 8-bit. (a) Khối nào trong CPU chính là bộ cộng 8-bit em vừa học? (b) Cờ nào sáng lên khi kết quả phép cộng vượt quá 255?

✅ Hoàn thành khi: (a) chỉ ra khối ALU; (b) cờ CARRY (kèm trạng thái “Tràn số”).