← Quay lại
10/01/2026
•
16 phút
•
Chương 12: Byte và thập lục phân
Bit tuy nhỏ nhưng có thể đưa ra những tuyên bố lớn lao: có hay không, đúng hay sai, đậu hay trượt. Nhưng cách dùng phổ biến hơn cả là nhóm nhiều bit lại để biểu diễn số rồi từ đó đại diện được cho các kiểu dữ liệu bao gồm văn bản, âm thanh, nhạc, ảnh và phim. Một mạch cộng 2 bit đã thú vị rồi nhưng một mạch cộng được nhiều bit mới là phần quan trọng của máy tính.
Để tiện lợi di chuyển và thao tác với bit, hệ thống máy tính thường nhóm một số lượng bit nhất định thành một đại lượng gọi là từ. Độ dài hay kích thước của từ này—nghĩa là số lượng bit cấu thành nó—rất hệ trọng với kiến trúc máy tính bởi vì tất cả dữ liệu máy tính đi chung với nhau theo nhóm gồm một hoặc nhiều từ.
Vài hệ thống máy tính trước đây dùng từ có độ dài là bội số của 6 như 12, 18, 24 bit. Những độ dài này mang một vẻ hấp dẫn đặc biệt chỉ vì một lí do đơn giản đó là giá trị của chúng dễ dàng được đại diện bằng số bát phân. Nhớ lại xem, chữ số bát phân là 0, 1, 2, 3, 4, 5, 6 và 7 tương ứng với giá trị 3 bit như bảng dưới đây:
Nhị phân | Bát phân 000 | 0 001 | 1 010 | 2 011 | 3 100 | 4 101 | 5 110 | 6 111 | 7
Một từ 6 bit có thể được đại diện chính xác bởi 2 chữ số bát phân, và các kích thước 12, 18, 24 bit chỉ là bội số của nó. Một từ 24 bit cần 8 chữ số bát phân.
Tuy nhiên, ngành công nghiệp máy tính đã đi theo một hướng hơi khác. Một khi tầm quan trọng của hệ nhị phân được nhận ra, việc sử dụng độ dài từ 6, 12, 18, 24 bit - không phải là lũy thừa của 2 mà là bội của 3 - dường như là điều hoàn toàn phi lý.
Đó là lúc byte xuất hiện.
Từ byte bắt nguồn từ IBM, có lẽ khoảng năm 1956. Nó có nguồn gốc từ chữ bite nhưng được viết là y để không ai phải nhầm lẫn sang từ bit. Ban đầu, một byte đơn giản chỉ là số lượng bit theo một dạng dữ liệu cụ thể. Nhưng vào giữa những năm 60, theo cùng với sự phát triển máy tính doanh nghiệp siêu phức tạp của IBM tên là System/360, từ byte bắt đầu mang nghĩa là một nhóm 8 bit.
Và từ đó, 8 bit tạo thành 1 byte giờ là một đại lượng đo lường dữ liệu điện tử.
Như một lượng 8 bit bình thường, một byte có thể nhận giá trị từ 00000000 tới 11111111, biểu diễn được số thập phân từ 0 tới 255, hay 1 trong 2^8 (256) thứ khác nhau. Hoá ra 8 lại là một miếng cắn (bite) vào bit vừa vặn, không quá nhỏ cũng không quá to. Byte đã đúng, về nhiều mặt chứ không chỉ một. Như bạn sẽ thấy trong các chương tới, một byte rất lý tưởng để lưu trữ văn bản bởi vì nhiều chữ viết trên khắp thế giới có thể được đại diện với ít hơn 256 kí tự. Và khi 1 byte không đủ (trường hợp biểu diễn chữ tượng hình của Trung, Nhật, Hàn) thì 2 byte—cho phép biểu diễn tới 2^16 (65.536) thứ—chắc là sẽ đủ. 1 byte cũng lý tưởng để đại diện các sắc độ xám trong ảnh đen trắng bởi vì mắt người có thể phân biệt xấp xỉ 256 sắc xám. Với màu sắc trên màn hình video, 3 byte đủ dùng để đại diện cho các phần tử màu đỏ, xanh lá và xanh dương.
Cuộc cách mạng máy tính cá nhân bắt đầu vào cuối những năm 70, đầu 80 với máy tính 8 bit. Những tiến bộ kĩ thuật theo sau đã gấp đôi số lượng bit dùng bên trong máy tính: từ 16 bit lên 32 bit rồi tới 64 bit—2 byte, 4 byte rồi 8 byte. Với các mục đích đặt biệt cũng có máy tính 128 và 256 bit tương ứng.
Nửa byte (4 bit) có khi gọi là nibble (và cũng được viết là nybble), nhưng từ này không thường dùng trong giao tiếp giống byte. Bởi vì byte xuất hiện rất nhiều bên trong máy tính, nên sẽ tiện hơn cho việc đọc gọn giá trị thay vì một chuỗi lô lốc các số nhị phân. Tất nhiên bạn cũng có thể dùng bát phân cho mục đích này: Ví dụ với byte 10110110, có thể tách thành các nhóm 3 bắt đầu từ bên phải rồi chuyển mỗi nhóm này thành bát phân bằng bảng lúc nãy:
10 110 110 |_| |_| |_| 2 6 6
Số bát phân 266 gọn ghẽ hơn 10110110 thế nhưng lại có một sự không tương thích căn bản giữa byte và bát phân: 8 không chia hết cho 3 nên khi biểu diễn một số 16 bit bằng bát phân:
1 011 001 111 000 101 | |_| |_| |_| |_| |_| 1 3 1 7 0 5
không giống với biểu diễn 2 byte bằng bát phân:
10 110 011 11 000 101 |_| |_| |_| |_| |_| |_| 2 6 3 3 0 5
Để thống nhất cách biểu diễn nhiều byte với một byte riêng ta cần một hệ số mà mỗi byte có thể chia thành các bit đều nhau.
Ta có thể chia mỗi byte thành 4 giá trị 2 bit, và biểu diễn bằng hệ cơ số 4 hay tứ phân đã được mô tả trong chương 10. Nhưng vẫn chưa đủ gọn như mong muốn.
Hay ta có thể chia byte thành 2 giá trị 4 bit. Như thế phải cần một hệ đặc biệt có cơ số 16.
Cơ số 16. Mới đúng không, nhưng có lí do cả đấy. Hệ cơ số 16 được gọi là thập lục phân (hexadecimal), và ngay đến cái tên đã là một đống bùi nhùi rồi. Phần lớn các từ bắt đầu với tiền tố hexa (như là hexagon, lục giác, hexapod, côn trùng, hay hexameter, thơ 6 âm) ám chỉ có 6 thứ gì đó. Thập lục phân mang nghĩa là mười sáu hay sáu cộng mười. Mặc dù tôi đã được bảo là phải viết sao cho tuân theo hướng dẫn online của Microsoft, đã nêu rõ ràng là "Không được viết tắt thành hex", nhưng mà ai chả nói thế, tới tôi đôi khi cũng vậy mà. (Và kể từ đây mình sẽ viết hex thay cho thập lục phân cho gọn)
Không phải chỉ cái tên là điều kì lạ duy nhất của hệ số này. Trong thập phân ta đếm là:
0 1 2 3 4 5 6 7 8 9 10 11 12...
Nhưng hex lại khác vì nó cần nhiều chữ số hơn. Đếm số hex như này:
0 1 2 3 4 5 6 7 8 9 cần thêm ký hiệu số học 10 11 12
với 10 (đọc là một-không) tương đương với 16 trong thập phân.
Ta dùng gì cho 6 ký hiệu còn thiếu này đây? Chúng đến từ đâu? Chúng không giống truyền thống của các hệ số khác nên điều hợp lý là tạo ra 6 ký hiệu mới, ví dụ như:
🤠 🏉 🥞 🐈⬛ 🌕 🔪
Không như các ký hiệu số ta hay dùng, những ký hiệu này có điểm lợi là dễ nhớ và xác định số lượng thực tế mà chúng đại diện. Có một chiếc mũ cao bồi to tướng (10 gallon cowboy hat), một quả bóng đá Mỹ (11 người trong một đội), một tá (12) bánh, một con mèo đen (liên hệ với số 13 xui xẻo), mặt trăng tròn hay xuất hiện vào ngày rằm (14) và một con dao gợi ta nhớ về vụ ám sát Julius Caesar (vào ngày 15 tháng 3).
Nhưng không. Thật không may (hoặc có lẽ nhẹ nhõm hơn) ta không thật sự phải dùng bóng đá và bánh donut để viết số hex. Làm thế cũng được nhưng mà hổng ai làm. Thay vào đó, ký hiệu hex dùng phổ biến ngày nay sẽ đảm bảo mọi người đều nhận được sự lúng túng như nhau. 6 chữ số hex còn thiếu đó được biểu diễn bằng 6 chữ cái đầu trong bảng chữ cái Latin, như sau:
Nhị phân | Thập lục phân | Thập phân 0000 | 0 | 0 0001 | 1 | 1 0010 | 2 | 2 0011 | 3 | 3 0100 | 4 | 4 0101 | 5 | 5 0110 | 6 | 6 0111 | 7 | 7 1000 | 8 | 8 1001 | 9 | 9 1010 | A | 10 1011 | B | 11 1100 | C | 12 1101 | D | 13 1110 | E | 14 1111 | F | 15
Không dễ chịu mấy khi phải dùng chữ biểu diễn số (và còn lúng túng hơn nữa khi phải dùng số biểu diễn chữ) nhưng hex là như vậy. Nó tồn tại vì một và chỉ một lý do duy nhất: để đại diện giá trị của byte một cách đủ và hợp lý nhất có thể và nó đã làm rất tốt điều này.
Mỗi byte là 8 bit hay 2 chữ số hex trong khoảng từ 00 tới FF. Byte 10110110 là B6 trong hex và byte 01010111 là 57.
Giờ thì rõ ràng B6 là một số hex vì có chữ cái nhưng 57 lại có thể là số thập phân. Để tránh nhầm lẫn, ta cần một cách nào đó để dễ dàng phân biệt 2 hệ số này. Và không chỉ 1 mà có tới khoảng 20 cách khác nhau để thể hiện số hex trong các môi trường và ngôn ngữ lập trình. Trong sách này tôi sẽ dùng chữ h theo sau số để biểu thị hex ví dụ như B6h, 57h.
Dưới đây là bảng chứa vài số hex đại diện cho 1 byte kèm số thập phân tương đương:
Nhị phân | Thập lục phân | Thập phân 00000000 | 00h | 0 00010000 | 10h | 16 00011000 | 18h | 24 00100000 | 20h | 32 01000000 | 40h | 64 01100100 | 64h | 100 10000000 | 80h | 128 11000000 | C0h | 192 11001000 | C8h | 200 11100000 | E0h | 224 11110000 | F0h | 240 11111111 | FFh | 255
Như số nhị phân, số hex thường được viết với 0 ở đầu để làm rõ số chữ số ta cần. Với những số nhị phân dài hơn, mỗi 4 chữ số nhị phân tương ứng với một chữ số hex. Một giá trị 16 bit là 2 byte với 4 chữ số hex. Một giá trị 32 bit là 4 byte với 8 chữ số hex.
Với sự phổ biến của hex, cách thông dụng để viết số nhị phân dài là với gạch ngang hoặc khoảng trống giữa mỗi 4 chữ số. Ví dụ số nhị phân 0010010001101000101011001110 trông đỡ sợ hơn nếu viết thành 0010 0100 0110 1000 1010 1100 1110 hoặc 0010-0100-0110-1010-1100-1110 và dễ nhận ra được chữ số hex tương ứng:
0010 = 2
0100 = 4
0110 = 6
1000 = 8
1010 = A
1100 = C
1110 = E
Đó là số 2468ACE gồm 7 chữ số chẵn trong hex. (Khi đội cổ động hô "2 4 6 8 A C E! Work for that Comp Sci degree!" hẳn bạn phải biết trường mình "nerd" đến nhường nào!)
Nếu bạn đã từng viết HTML, Hypertext Markup Language dùng cho các trang web trên mạng, thì có lẽ bạn cũng đã quen thuộc với một công dụng phổ biến của hex. Mỗi chấm màu (hay pixel) trên màn hình máy tính là tổng hợp của 3 màu cơ bản: đỏ, xanh lá và xanh dương, được gọi là màu RGB. Cường độ hoặc độ sáng của một trong ba phần tử này được cho bởi một giá trị byte, có nghĩa là cần 3 byte để chỉ định một màu cụ thể. Thường thường trên trang HTML, một màu được biểu diễn bằng một giá trị hex 6 chữ số kèm dấu # ở đầu. Ví dụ, sắc đỏ dùng trong các minh hoạ của sách có giá trị màu #E74536, là tổ hợp của màu đỏ E7h, màu xanh lá 45h và xanh dương 36h. Màu này có thể dùng số thập phân bằng rgb (231, 69, 54).
Biết rằng 3 byte tạo được màu của một pixel trên màn hình, ta có thể làm toán và rút ra vài điều: Nếu màn hình máy tính chứa 1920 pixel theo chiều ngang và 1080 pixel theo chiều dọc (kích thước TV chuẩn HD), thì tổng số byte cần để lưu ảnh vừa màn hình đó là 1920 x 1080 x 3 byte, hay 6.220.800 byte.
Mỗi màu cơ bản nằm trong khoảng từ 0 tới 255, có nghĩa là tổng số kết hợp có thể có là 256 x 256 x 256 hay 16.777.216 màu. Trong hex con số đó là 100h x 100h x 100h, 1000000h.
Trong một số hex cụ thể, vị trí của mỗi chữ số tương ứng với số mũ của 16:
⬜️ ⬜️ ⬜️ ⬜️ ⬜️ | | | | |___ Số một | | | |_______ Số mười sáu | | |__________ Số hai trăm năm mươi sáu | |______________ Số bốn ngàn chín mươi sáu |_________________ Số sáu mươi lăm ngàn năm trăm ba mươi sáu
Số hex 9A48Ch là
9A48Ch = 9 × 10000h + A × 1000h + 4 × 100h + 8 × 10h + C × 1h
Viết lại bằng luỹ thừa 16:
9A48Ch = 9 × 16^4 + A × 16^3 + 4 × 16^2 + 8 × 16^1 + C × 16^0
Hoặc dùng hệ thập phân:
9A48Ch = 9 × 65536 + A × 4096 + 4 × 256 + 8 × 16 + C × 1
Chú ý là không có gì nhập nhằng khi viết chữ số (9, A, 4, 8 và C) mà không chỉ ra hệ số. 9 tự nó đã là 9 dù trong hệ thập phân hay hex. Còn A rõ ràng là hex − tương đương với 10 trong thập phân.
Chuyển tất cả chữ số sang thập phân giúp chúng ta tính được:
9A48Ch = 9 × 65536 + 10 × 4096 + 4 × 256 + 8 × 16 + 12 × 1
Kết quả là 631.948. Đây là cách để đổi từ hex sang thập phân.
Dưới đây là mẫu chuyển bất kì số hex 4 chữ số nào sang thập phân:
⬜️ ⬜️ ⬜️ ⬜️ x4096 x256 x16 x1 ⬜️ + ⬜️ + ⬜️ + ⬜️ = ⬜️
Ví dụ với 79ACh. Nhớ là chữ số hex A và C tương đương với 10 và 12 trong thập phân:
7 9 A C x4096 x256 x16 x1 28672 + 2304 + 160 + 12 = 31148
Chuyển số thập phân sang hex cần dùng phép chia. Nếu số đó nhỏ hơn hoặc bằng 255 thì có thể dùng 1 byte để biểu diễn hay 2 chữ số hex. Để tính được 2 chữ số này, hãy chia số cần đổi cho 16 được thương với dư. Ví dụ với số thập phân 182, chia nó cho 16 được 11 (là B trong hex) dư 6. Số hex tương đương là B6h.
Nếu số cần chuyển nhỏ hơn 65.536, số hex tương đương sẽ có 4 chữ số hoặc ít hơn. Đây là mẫu chuyển cho chúng:
⬜️ ⬜️ ⬜️ ⬜️ ÷4096 ÷256 ÷16 ÷1 ⬜️ ⬜️ ⬜️ ⬜️
Bạn bắt đầu bằng cách đặt cả số thập phân vào ô phía trên bên trái:
31148 ⬜️ ⬜️ ⬜️ ÷4096 ÷256 ÷16 ÷1 ⬜️ ⬜️ ⬜️ ⬜️
Chia số cho 4096, lấy được thương và dư. Thương đặt vào ô đầu tiên bên dưới, còn dư đưa vào ô tiếp theo bên trên:
31148 2476 ⬜️ ⬜️ ÷4096 ÷256 ÷16 ÷1 7 ⬜️ ⬜️ ⬜️
Giờ chia số dư vừa nãy cho 256, và cũng chỉ cần lấy thương là 9 và dư mới là 172. Tiếp tục quá trình:
31148 2476 172 12 ÷4096 ÷256 ÷16 ÷1 7 9 10 12
Số thập phân 10 và 12 tương đương với A và C trong hex nên kết quả là 79ACh.
Một cách khác để chuyển số thập phân tới 65.535 sang hex đó là trước hết tách số đó thành 2 byte bằng cách chia cho 256. Rồi với mỗi byte chia tiếp cho 16. Đây là mẫu:
⬜️
÷256
⬜️ ⬜️
÷16 ÷16
⬜️ ⬜️ ⬜️ ⬜️Bắt đầu từ trên. Với mỗi lần chia, thương đặt vào ô bên trái còn dư vào ô bên phải. Ví dụ, đây là cách đổi 51.966:
51966
÷256
202 254
÷16 ÷16
12 10 15 14Chữ số hex là 12, 10, 15 và 14 bằng CAFE, giống chữ hơn là số nhỉ! (Nếu bạn tới quán có thể gọi ly cà phê là 56495.) (Bạn hãy thử đổi ra hex xem số này nghĩa là gì nhé!)
Giống những hệ số khác, hex cũng có bảng cộng:
Dùng bảng này kèm quy tắc nhớ là có thể cộng được hex:
4A3378E2 + 877AB982 ---------- D1AE3264
Nếu không thích tính tay thì bạn có thể dùng ứng chế độ Programmer của ứng dụng máy tính trên macOS hoặc Windows để tính nhị phân, bát phân, hex và chuyển giữa những hệ số này.
Hoặc bạn có thể tạo một máy cộng nhị phân 8 bit trong Chương 14.