Cộng là phép toán căn bản nhất trong số học, nên nếu muốn tạo ra máy tính (và đó là mục tiêu không hề che giấu của cuốn sách này) thì trước hết ta phải biết cách tạo một thứ cộng được hai số. Suy cho cùng, cộng gần như là thứ duy nhất mà máy tính làm. Nếu ta có thể tạo được một món gì có thể làm phép cộng, đó sẽ là một bước tiến trên con đường tạo ra một loại máy tận dụng phép cộng để làm cả phép trừ, nhân, chia hoặc tính tiền trả nợ, chỉ đường tên lửa lên sao Hoả, chơi cờ và dùng mạng xã hội để chia sẻ những điệu nhảy "trend" nhất, chiến tích nấu ăn cũng như những khoảnh khắc ngộ nghĩnh của thú cưng.
Máy cộng mà ta tạo trong chương này sẽ to, cồng kềnh, chậm chạp và ồn ào, ít nhất là khi đem so với máy tính hiện đại. Điều thú vị nhất là ta sắp tạo ra nó hoàn toàn từ các thiết bị điện đơn giản đã được học trong các chương trước - công tắc, bóng đèn, dây dẫn, pin và rơle đã được mắc sẵn thành cổng logic. Những thành phần này đều có sẵn trước thế kỉ 20. Và thật tuyệt khi ta không phải tạo ra bất kì thứ gì có thật trong phòng khách mà thay vào đó sẽ tạo máy cộng này trên giấy và trong đầu.
Máy này hoạt động hoàn toàn bằng số nhị phân và sẽ thiếu vài tính năng hiện đại. Bạn sẽ không thể dùng bàn phím để gõ số; thay vào đó bạn sẽ dùng một dãy công tắc. Thay vì một màn hình số để hiện kết quả máy cộng này sẽ có một dãy bóng đèn.
Nhưng nó chắc chắn sẽ cộng 2 số lại và sẽ làm thế bằng cách rất giống với cách mà máy tính dùng để cộng.
Cộng số nhị phân rất giống cộng số thập phân. Khi bạn muốn cộng 2 số thập phân như 245 và 673, bạn chia nhỏ vấn đề thành các bước đơn giản hơn. Mỗi bước chỉ cần phải cộng một cặp chữ số thập phân. Trong ví dụ này bạn bắt đầu với 5 cộng 3. Sẽ dễ dàng hơn nếu bạn luôn nhớ một bảng cộng.
Ưu điểm lớn của số nhị phân so với thập phân là bảng cộng rất đơn giản:
Bảng cộng nhị phân
Nếu bạn lớn lên trong cộng đồng cá heo và nhớ bảng này khi đi học, bạn có thể hát hoặc huýt sáo vang: 0 cộng 0 bằng 0. 0 cộng 1 bằng 1. 1 cộng 0 bằng 1. 1 cộng 1 bằng 0, nhớ 1.
Bạn có thể viết lại bảng trên với số 0 ở đầu để được giá trị 2 bit:
Bảng cộng với số 0 ở đầu
Nếu nhìn theo hướng này thì cộng một cặp số nhị phân được 2 bit, 1 cho bit tổng 1 cho bit nhớ (như trong câu "1 cộng 1 bằng 0, nhớ 1"). Giờ ta có thể chia bảng cộng nhị phân thành 2 bảng, bảng đầu cho bit tổng:
Bảng bit tổng
Và bảng thứ hai cho bit nhớ:
Bảng bit nhớ
Làm phép cộng nhị phân theo cách này thuận tiện hơn vì máy cộng sẽ tìm tổng và nhớ riêng biệt. Tạo một máy cộng nhị phân yêu cầu ta phải thiết kế một mạch thực hiện những phép tính này. Chỉ tập trung vào nhị phân đơn giản hoá vấn đề đi rất nhiều vì tất cả thành phần của mạch - công tắc, bóng đèn và dây dẫn - đều có thể là chữ số nhị phân.
Như với cộng thập phân, ta cộng 2 số nhị phân theo từng cột, bắt đầu với bit ít quan trọng nhất trong cột cuối cùng bên phải:
01100101
+ 10110110
----------
100011011
Để ý khi ta cộng cột thứ 3 từ phải sang, nhớ 1 sang cột tiếp theo. Tương tự cho cột thứ 6, 7 và 8 từ phải sang.
Ta muốn cộng nhị phân với số lớn cỡ nào? Vì ta chỉ tạo máy cộng này trong đầu nên có thể tạo được máy cộng những số rất dài. Nhưng để sát với thực tế ta chỉ cho phép cộng lên tới 8 bit hay 1 byte. Có nghĩa là ta muốn cộng số nhị phân từ 00000000 tới 11111111. Giá trị hex của chúng là từ 00h tới FFh, hay 0 tới 255 trong thập phân. Tổng của 2 số 8 bit có giá trị tối đa là 510 trong thập phân hay 1FEh trong hex hay 111111110 trong nhị phân.
Bảng điều khiển cho máy cộng nhị phân có thể trông như này:
Bảng cộng nhị phân
Bảng có 2 hàng 8 công tắc. Tập hợp các công tắc này được gọi là thiết bị đầu vào và ta sẽ dùng nó để "nhập vào" 2 số 8 bit. Trong thiết bị đầu vào này, công tắc tắt (xuống) cho 0 và bật (lên) cho 1, giống như công tắc tường nhà bạn. Như thường lệ, bit ít quan trọng nhất ở ngoài cùng bên phải và bit quan trọng nhất ở bên trái. Thiết bị đầu ra ở bên dưới là một hàng 9 bóng đèn. Chúng sẽ biểu thị đáp án. Bóng đèn tắt là 0, sáng là 1. Cần 9 bóng đèn là do tổng của 2 số 8 bit có thể là một số 9 bit. Bóng đèn nằm cuối cùng bên trái chỉ sáng nếu tổng lớn hơn số thập phân 255.
Phần còn lại của máy cộng sẽ gồm các cổng logic mắc với nhau theo vài cách. Công tắc sẽ kích hoạt rơle trong cổng logic rồi bật đúng bóng đèn. Ví dụ, nếu ta muốn cộng 01100101 và 10110110 (2 số xuất hiện trong ví dụ trước), ta đẩy công tắc tương ứng như sau:
Bảng cộng 01100101 với 10110110
Bóng đèn sáng cho đáp án là 100011011. (Hê hê, cứ cho là vậy đi vì ta vẫn chưa tạo ra nó mà! 😹)
Tôi đã nói trước là sẽ dùng rất nhiều rơle trong sách. Máy cộng 8 bit mà ta sắp tạo ra trong chương này cần không dưới 144 rơle - 18 cho mỗi 1 trong 8 cặp bit đem cộng. Nếu tôi cho bạn thấy toàn bộ mạch điện bạn chắc sẽ hãi lắm. Không đời nào bạn có thể hiểu hết được 144 rơle nối với nhau theo các cách lạ lùng. Thay vì vậy, tôi sẽ tiếp cận vấn đề này theo các bước đơn giản tăng dần.
Có thể bạn đã nhận ra ngay mối liên kết giữa cổng logic và cộng nhị phân khi nhìn vào bảng bit nhớ là kết quả của cộng 2 số 1 bit:
Bảng bit nhớ
Bạn có lẽ đã nhận ra là nó giống với phép toán logic AND với đầu ra của cổng AND trong chương 8:
Đầu ra của cổng AND
Hoặc như này nếu 2 đầu vào được đặt tên:
Đầu vào và đầu ra cổng AND
Thay vì vẽ một đống rơle, kĩ sư điện kí hiệu cổng AND như này:
Kí hiệu cổng AND
Đầu vào bên trái đặt tên là A và B cho 2 bit được đem cộng. Đầu ra bên phải là bit nhớ cho phép cộng 2 chữ số nhị phân này.
A ha! Tiến triển rồi đó. Việc hơi khó hơn là làm sao để thuyết phục rơle làm được như này:
Bảng bit tổng
Đây là nửa còn lại của vấn đề cộng cặp chữ số nhị phân. Bit tổng hoá ra lại không dễ hiểu như bit nhớ nhưng rồi bạn cũng làm được thôi.
Đầu tiên bạn nhận ra là phép toán logic OR gần giống với thứ ta muốn ngoại trừ trường hợp ở góc dưới bên phải:
Bảng đầu ra cổng OR
Bạn có thể nhớ lại trong chương 8 cổng OR được kí hiệu như này:
Kí hiệu cổng OR
Cũng tương tự như thứ ta muốn, cổng logic NAND (hay NOT AND) có đầu ra ngược với cổng AND. Giống với tổng của 2 số 1 bit ngoại trừ trường hợp góc trên bên trái:
Đầu ra cổng NAND
Đây là cách cổng NAND được biểu diễn:
Kí hiệu cổng NAND
Giống với cổng AND ngoại trừ một chấm tròn nhỏ ở bên phải kí hiệu cho đầu ra ngược với cổng AND.
Hãy nối cả 2 cổng OR và NAND vào cùng đầu ra. Như thường lệ, chấm nhỏ thể hiện nơi dây dẫn nối với nhau còn không thì chỉ chồng lên:
Nối chung đầu vào cồng OR và NAND
Bảng sau tóm lại đầu ra của cổng OR và NAND rồi so sánh nó với thứ ta muốn cho máy cộng:
So sánh với thứ ta muốn
Bạn có thấy thứ ta muốn là 1 chỉ khi đầu ra từ cổng OR và cổng NAND phải cùng là 1. Nó gợi ý rằng 2 đầu ra này có thể là đầu vào cho cổng AND:
Nối 2 đầu ra thành đầu vào cho cổng AND
Chú ý là vẫn chỉ có 2 đầu vào và 1 đầu ra trong toàn bộ mạch này. 2 đầu vào đi vào cả cổng OR và cổng NAND. Đầu ra từ cổng OR và NAND đi vào cổng AND và điều đó cho ta chính xác thứ luôn muốn:
Thứ ta muốn
Thậm chí mạch này còn có tên nữa cơ. Nó được gọi là cổng Exclusive OR (OR loại trừ) hay ngắn gọn hơn là cổng XOR. Có người đọc nó là "eks or" (éc so) còn người khác thì đánh vần từng chữ: X O R. Nó được gọi là cổng Exclusive OR vì đầu ra là 1 chỉ khi đầu vào A là 1 hoặc đầu vào B là 1, chứ không phải cả 2. Nên thay vì phải vẽ cổng OR, cổng NAND và cổng AND như trước, ta có thể dùng kí hiệu mà thợ điện dùng cho cổng XOR:
Kí hiệu cổng XOR
Nó rất giống cổng OR chỉ khác là có một đường cong phía đầu vào. Cổng XOR hoạt động như sau:
Bảng đầu ra cổng XOR
Cổng XOR là cổng logic cuối cùng mà tôi sẽ mô tả trong sách. (Còn có một cổng khác đôi khi xuất hiện trong kĩ thuật điện. Nó tên là cổng coincidence (trùng) hay cổng equivalence (tương đương) bởi vì đầu ra là 1 chỉ khi 2 đầu vào giống nhau. Cổng coincidence có đầu ra ngược với cổng XOR, nên kí hiệu của nó giống cổng XOR nhưng với một hình tròn nhỏ ở đầu ra.)
Hãy ôn lại những gì ta biết tới giờ. Cộng 2 số nhị phân được 1 bit tổng và 1 bit nhớ:
Bit tổng và bit nhớ
Bạn có thể dùng 2 cổng logic sau để nhận kết quả giống trên:
Đầu ra cổng XOR và AND
Tổng 2 số nhị phân được cho bởi đầu ra cổng XOR còn bit nhớ được cho bởi đầu ra cổng AND. Nên ta có thể kết hợp cổng AND và cổng XOR để cộng 2 chữ số nhị phân gọi là A và B:
A + B bằng XOR và AND
Luôn nhớ là nó phức tạp hơn hình này nhiều! Cổng XOR thực chất là kết hợp của cổng OR, cổng NAND và cổng AND, rồi mỗi cổng này lại gồm 2 rơle. Nhưng sẽ dễ hiểu hơn nếu giấu bớt chi tiết. Quá trình này đôi khi được gọi là encapsulation (đóng gói): Một tập hợp các thứ phức tạp bị giấu đi trong lớp gói đơn giản hơn. Bất cứ lúc nào ta cũng có thể gỡ lớp gói nếu ta muốn nhìn thấy hết chi tiết bên trong, nhưng nó không cần thiết.
Đây là một đóng gói khác: Thay vì vẽ đi vẽ lại cổng AND và cổng XOR, bạn có thể đơn giản đại diện toàn bộ mạch này bằng một hộp như sau, được gọi là half adder (bộ cộng một nửa):
Half Adder
Nhãn S và CO đại diện cho Sum (Tổng) và Carry Out (Nhớ Ra). Đôi khi một hộp như này được gọi là hộp đen. Một tập hợp đầu vào cụ thể cho đầu ra tương ứng, nhưng cách thực hiện bị ẩn. Nhưng vì ta đã rành những thứ xảy ra bên trong half adder quá, thiết nghĩ nên gọi nó là hộp rõ thì đúng hơn.
Hộp này được đặt tên là Half Adder là có lí của nó. Chắc chắn là nó phải cộng 2 chữ số nhị phân để được 1 bit tổng và 1 bit nhớ. Nhưng với số nhị phân lớn hơn 1 bit, half adder lại không đủ để cộng số khác ngoại trừ 2 bit ít quan trọng nhất. Nó thiếu chức năng cộng thêm bit nhớ từ phép cộng 1 bit trước đó. Ví dụ như ta đang cộng 2 số nhị phân sau:
1111
+ 1111
------
11110
Ta chỉ có thể dùng half adder để cộng cột ngoài cùng bên phải: 1 cộng 1 bằng 0, nhớ 1. Với cột thứ 2 từ phải qua ta thực sự cần phải cộng 3 số nhị phân vì có thêm nhớ. Và cứ thế với những cột tiếp theo. Mỗi phép cộng 2 số nhị phân tiếp theo phải kèm theo bit nhớ từ cột trước.
Để cộng 3 số nhị phân ta cần 2 half adder và 1 cổng OR nối như sau:
Cộng 3 số nhị phân
Không dễ để hình dung cách nó hoạt động. Bắt đầu với đầu vào A và B của half adder đầu tiên bên trái. Đầu ra là tổng và nhớ. Tổng phải cộng thêm nhớ từ cột trước, được gọi là Carry In (Nhớ Vào). Carry In này và Sum từ half adder đầu tiên là đầu vào cho half adder tiếp theo. Tổng của half adder thứ 2 này là tổng cuối. 2 Carry Out từ 2 half adder là đầu vào cho cổng OR. Bạn có thể nghĩ là thay bằng half adder ở đây cũng được, và chắc chắn rồi. Nhưng nếu liệt kê ra hết tất các các trường hợp bạn sẽ phát hiện ra là Carry Out từ 2 half adder không bao giờ cùng bằng 1. Cổng OR là đủ để cộng chúng vì cổng OR giống với cổng XOR nếu đầu vào không cùng bằng 1.
Thay vì phải vẽ đi vẽ lại sơ đồ trên ta có thể chỉ cần gọi nó là một full adder (bộ cộng đầy đủ):
Full Adder
Bảng dưới tóm lại tất cả tổ hợp khả dĩ của đầu vào cho full adder và kết quả đầu ra:
Bảng đầu ra của Full Adder
Tôi đã nói trước là chương này dùng tới 144 rơle cho máy cộng nhị phân. Đây là cách tôi tính ra được con số đó: Mỗi cổng AND, OR và NAND cần 2 rơle. Nên một cổng XOR gồm 6 rơle. Một half adder là một cổng XOR và một cổng AND nên nó cần 8 rơle. Mỗi full adder là 2 half adder và 1 cổng OR, hay 18 rơle. Ta cần 8 full adder cho máy cộng 8 bit. Đó là 144 rơle.
Nhớ lại bảng điều khiển ban đầu với công tắc và bóng đèn:
Bảng điều khiển máy cộng
Giờ ta có thể bắt đầu nối công tắc và bóng đèn này với 8 full adder.
Bắt đầu với bit ít quan trọng trước: đầu tiên nối 2 công tắc ngoài cùng bên phải với bóng đèn ngoài cùng với 1 full adder:
Cộng cột ngoài cùng bên phải
Khi bạn bắt đầu cộng 2 số nhị phân, cột số đầu tiên từ phải qua khác với phần còn lại. Là bởi mỗi cột theo sau có thể thêm một bit nhớ từ cột trước đó. Còn cột đầu tiên không có bit nhớ, đó là lí do tại sao đầu vào nhớ cho full adder được nối đất. Là 1 bit 0. Cộng cặp số nhị phân đầu tiên tất nhiên có thể được một bit nhớ. Đầu ra nhớ đó là đầu vào cho cột tiếp theo.
Với 2 số tiếp theo và bóng đèn kế tiếp bạn dùng 1 full adder nối như này:
Cộng các cột tiếp theo
Đầu ra nhớ từ full adder đầu tiên là đầu vào cho full adder thứ hai. Mỗi cột số tiếp theo được nối tương tự. Mỗi đầu ra nhớ từ một cột là đầu vào nhớ cho cột tiếp theo.
Cuối cùng cặp thứ 8 và cũng là cặp công tắc cuối (nằm ngoài cũng bên trái bảng điều khiển) được nối với full adder cuối cùng:
Cộng cột cuối cùng
Ở đây đầu ra nhớ cuối cùng đi vào bóng đèn thứ 9.
Xong!
Dưới đây là một cách nhìn khác vào tập hợp 8 full adder với mỗi Carry Out là một đầu vào cho Carry In tiếp theo:
Toàn bộ full adder được nối lại
Thứ tự của full adder giống với thứ tự công tắc và bóng đèn trong bảng điều khiển: Bit ít quan trọng nhất bên phải và bit quan trọng nhất bên trái, như cách viết số thông thường. Chú ý cách mỗi Carry Out vòng ngược lại để trở thành Carry In cho bit quan trọng tiếp theo. Carry In đầu tiên được đặt nối đất (nghĩa là bit 0) trong khi Carry Out cuối cùng thắp sáng bóng đèn thứ 9.
Đây là bộ cộng 8 bit hoàn chỉnh được đóng gói vào một hộp. Đầu vào gắn nhãn từ A0 tới A7 và B0 tới B7. Đầu ra từ S0 tới S7 (cho tổng):
Hộp cộng 8 bit hoàn chỉnh
Đây là cách phổ biến để đặt tên các bit riêng lẻ trong một số nhiều bit. Bit A0, B0 và S0 là bit ít quan trọng nhất hay ngoài cùng bên phải. Bit A7, B7 và S7 là bit quan trọng nhất hay ngoài cùng bên trái. Ví dụ, đây là cách những chữ cái viết dưới này áp dụng cho số nhị phân 01101001:
01101001
Chỉ số dưới bắt đầu từ 0 và tăng lên tương ứng với mức độ quan trọng vì chúng tương đương với số mũ của luỹ thừa 2:
Luỹ thừa 2 của 01101001
Nếu bạn nhân từng luỹ thừa 2 với chữ số bên dưới và cộng chúng lại sẽ được số thập phân tương đương 01101001, là 64 + 32 + 8 + 1 = 105.
Một cách vẽ bộ cộng 8 bit nữa là:
Bộ cộng 8 bit
Những mũi tên kép với số 8 bên trong biểu thị một nhóm 8 tín hiệu riêng lẻ. Đó là những đường dẫn dữ liệu 1 byte. Chúng cũng được đặt tên là A7...A0, B7...B0 và S7...S0 để biểu thị số 8 bit.
Khi bạn đã tạo được 1 bộ cộng 8 bit thì ngại gì không tạo thêm cái nữa. Sau đó nó trở nên dễ cascade (xếp chồng) để cộng 2 số 16 bit:
Cộng số 16 bit
Hai giá trị đầu vào 16 bit được tách ra thành 2 byte, gọi là low byte (byte thấp) và high byte (byte cao). Carry Out của bộ cộng bên phải nối với Carry In của bộ cộng bên trái. Bộ cộng bên trái có đầu vào là 8 chữ số quan trọng nhất của 2 số đem cộng và tạo được đầu ra là 8 chữ số quan trọng nhất của kết quả.
Và giờ bạn có thể hỏi: "Liệu đây có thực sự là cách máy tính dùng để cộng số?
Hỏi hay đó!
9
Open to Work
Looking for a Fullstack Ruby on Rails developer?
I am open to new remote/hybrid opportunities and contract work.