Bỏ qua tới nội dung chính
Quay lại tin tức

Tôi đã viết một trò chơi bằng mã máy và nó có dung lượng khoảng 300 byte

Medium Towards AI· Yashraj Behera· 6/8/2026general

Nhiều người thường nói rằng ai đó đã "viết một trò chơi bằng mã nhị phân thuần túy", bằng các số 0 và 1, bằng tay. Đây là một hình ảnh ấn tượng, nhưng gần như hoàn toàn là một huyền thoại. Không ai gõ trực tiếp các bit thô để tạo ra một trò chơi, bởi vì chỉ cần một bit bị đảo ngược trong số hàng nghìn bit cũng có thể làm hỏng mọi thứ mà không có cách nào để tìm ra lỗi. Tuy nhiên, có một phiên bản thực tế, chân thực của huyền thoại đó, đó là viết một trò chơi bằng hợp ngữ (assembly), lớp ngôn ngữ dễ đọc hơn nằm ngay trên mã máy, và sau đó xem xét các byte thực tế mà bộ xử lý thực thi. Vì vậy, tôi đã viết một trò chơi đoán nhỏ theo cách đó, biên dịch nó thành khoảng 300 byte mã máy, chơi thử và trích xuất...

Nhiều người thường nói rằng ai đó đã "viết một trò chơi bằng mã nhị phân thuần túy", bằng các số 0 và 1, bằng tay. Đó là một hình ảnh tuyệt vời, nhưng gần như hoàn toàn là một huyền thoại. Không ai gõ các bit thô để tạo ra một trò chơi, bởi vì chỉ một bit bị đảo ngược trong số hàng nghìn bit cũng có thể làm hỏng mọi thứ mà không có cách nào để tìm ra lỗi. Tuy nhiên, có một phiên bản thực tế, chân thực của truyền thuyết đó, đó là viết một trò chơi bằng hợp ngữ (assembly), lớp ngôn ngữ dễ đọc nằm ngay trên mã máy, và sau đó xem xét các byte thực tế mà bộ xử lý thực thi. Vì vậy, tôi đã viết một trò chơi đoán số nhỏ theo cách đó, biên dịch nó thành khoảng 300 byte mã máy, chơi thử và trích xuất mã nhị phân thực tế để trình bày. Đây là ý nghĩa thực sự của việc "viết một trò chơi bằng mã nhị phân". Cụm từ này nghe có vẻ anh hùng. Ai đó, thường trong một câu chuyện được kể với một chút ngưỡng mộ, đã "viết toàn bộ bằng mã nhị phân", bằng các số 0 và 1 thô, không có ngôn ngữ, chỉ có các bit. Đó là điều tương đương trong lập trình với việc xây một ngôi nhà bằng tay không. Và cần phải thành thật ngay lập tức, điều đó về cơ bản là một huyền thoại, ít nhất là như một mô tả về cách mọi người thực sự làm việc. Đây là lý do. Một chương trình thực sự có hàng nghìn, hàng nghìn bit, và mỗi bit trong số đó phải hoàn toàn chính xác. Chỉ cần đảo ngược một bit, chương trình sẽ không lịch sự cho bạn biết điều gì đã sai, nó sẽ gặp sự cố, hoặc tệ hơn, âm thầm hoạt động sai, và bạn sẽ phải đối mặt với một biển các số 0 và 1 mà không có cách nào để biết bit nào đã phản bội bạn. Không có cấu trúc để đọc, không có tên, không có gợi ý. Làm điều đó bằng tay cho bất cứ thứ gì phức tạp như một trò chơi không phải là một kỳ công về kỹ năng mà là một kỳ công về sự tự hành hạ, và đó không phải là cách ngay cả những lập trình viên cấp thấp chuyên nghiệp nhất cũng dành thời gian của họ. Nhưng có một điều thực tế ẩn dưới huyền thoại, và nó thực sự gần với phần cứng, và bạn thực sự có thể làm được điều đó. Nó được gọi là hợp ngữ (assembly), và đó là phiên bản chân thực của việc "viết một trò chơi bằng mã nhị phân". Vì vậy, tôi đã viết một trò chơi đoán số nhỏ bằng hợp ngữ, biến nó thành mã máy thực sự, chơi thử để đảm bảo nó hoạt động, và sau đó trích xuất các byte thực tế mà bộ xử lý thực thi để bạn có thể xem. Đây là nội dung của bài viết này, phiên bản thực sự của truyền thuyết, với mã nhị phân thực tế được trình bày. Mã máy và hợp ngữ thực sự là gì Để xem những gì tôi đã xây dựng, bạn cần hai lớp ngay trên các bit, và chúng đơn giản hơn bạn nghĩ. Ở cấp thấp nhất, thứ mà bộ xử lý của bạn thực sự chạy là mã máy, thực sự chỉ là các byte, các số, mà chip diễn giải thành các lệnh. Một byte nhất định có nghĩa là "cộng hai thứ này", một byte khác có nghĩa là "nhảy đến vị trí này", một byte khác có nghĩa là "sao chép giá trị này vào đây". Đây là các số 0 và 1 mà huyền thoại nói đến, và đó thực sự là thứ được thực thi. Vấn đề duy nhất là việc viết trực tiếp, từng byte một, là phi nhân tính, vì những lý do đã nêu ở trên. Một lớp mỏng hơn là hợp ngữ. Hợp ngữ là một tên dễ đọc cho con người đối với mỗi lệnh máy đó. Thay vì viết byte, bạn viết một từ gợi nhớ ngắn gọn như "mov" cho di chuyển (move), "add" cho cộng (add), "cmp" cho so sánh (compare), "jmp" cho nhảy (jump). Mỗi từ đó tương ứng gần như chính xác với một lệnh máy, vì vậy hợp ngữ không che giấu máy móc khỏi bạn như cách một ngôn ngữ lập trình thông thường làm, nó chỉ cung cấp cho các lệnh thô những cái tên mà bạn có thể đọc. Sau đó, một công cụ gọi là trình biên dịch hợp ngữ (assembler) sẽ dịch các từ gợi nhớ của bạn thành các byte thực tế. Bạn viết phiên bản dễ đọc, và bạn nhận được mã nhị phân ở đầu kia, từng byte có thể dự đoán được. Vì vậy, "viết một trò chơi bằng mã nhị phân", được thực hiện một cách trung thực, có nghĩa là viết bằng hợp ngữ, mỗi dòng dễ đọc tương ứng với một lệnh máy, và sau đó biên dịch nó thành mã máy thực sự. Bạn đang làm việc. ở cấp độ lệnh của từng bộ xử lý riêng lẻ, đây là mức gần với phần cứng nhất mà bất kỳ ai cũng có thể đạt được một cách thực tế. Đó chính xác là những gì tôi đã làm. Trò chơi Tôi cố tình giữ cho trò chơi đơn giản, vì phần thú vị là cấp độ mà nó được viết, chứ không phải lối chơi. Đây là trò chơi đoán số cổ điển. Chương trình chọn một số bí mật từ 1 đến 100, bạn nhập một số đoán và nó cho bạn biết số thực cao hơn hay thấp hơn, cho đến khi bạn đoán đúng, lúc đó nó sẽ thông báo bạn đã đoán đúng và thoát. Đơn giản như vậy, nhưng nó cần mọi thành phần cơ bản của một chương trình thực sự. Nó phải tạo ra một số ngẫu nhiên ở một mức độ nào đó. Nó phải in văn bản ra màn hình. Nó phải đọc những gì bạn nhập. Nó phải biến các ký tự bạn đã nhập thành một số thực tế. Nó phải so sánh hai số và đưa ra quyết định dựa trên kết quả. Và nó phải lặp lại, thực hiện điều này lặp đi lặp lại cho đến khi bạn thắng. Đó là cấu trúc chương trình thực sự, đầu vào, đầu ra, số học, so sánh, phân nhánh và một vòng lặp, chỉ được viết ở cấp độ lệnh. Và đây là điều làm cho bài tập này thành công, toàn bộ trò chơi, sau khi được lắp ráp, chỉ khoảng 300 byte mã máy. Ba trăm số. Đó là toàn bộ trò chơi có thể chơi được. Viết nó ở cấp độ lệnh Để bạn có cảm nhận về mã thực sự trông như thế nào, đây là phần in dòng mở đầu. Trong hợp ngữ, việc yêu cầu hệ điều hành ghi văn bản ra màn hình được thực hiện bằng cách điền một vài thanh ghi bộ xử lý, các khe nhỏ có tên mà CPU làm việc, với các giá trị cụ thể và sau đó kích hoạt một lệnh gọi hệ thống, đây là cách một chương trình yêu cầu hệ điều hành thực hiện điều gì đó cho nó. mov rax, 1 ; 1 là mã cho "write" mov rdi, 1 ; 1 có nghĩa là "ra màn hình" mov rsi, banner ; địa chỉ của văn bản mov rdx, banner_len ; số lượng ký tự syscall ; yêu cầu hệ điều hành thực hiện Mỗi dòng là một lệnh máy. Ba dòng đầu tiên tải các giá trị vào các thanh ghi, một dòng cho biết chúng ta muốn thao tác nào, một dòng cho biết nơi gửi đầu ra, một dòng trỏ đến văn bản, một dòng cho biết độ dài của nó. Sau đó, syscall chuyển quyền điều khiển cho hệ điều hành để thực sự thực hiện thao tác ghi. Đây là cấp độ bạn làm việc, không có lệnh "in" nào được cung cấp cho bạn, bạn tự sắp xếp yêu cầu và yêu cầu hệ thống thực hiện. Phần cốt lõi của trò chơi thậm chí còn tiết lộ nhiều hơn, bởi vì đó là nơi đưa ra quyết định. Sau khi biến số đoán bạn đã nhập thành một số được giữ trong một thanh ghi, toàn bộ logic trò chơi chỉ còn là một phép so sánh và một số lệnh nhảy. cmp r8, rax ; so sánh số đoán của bạn với số bí mật je correct ; nếu bằng

Nguồn tin: Medium Towards AI — Tác giả: Yashraj Behera. Bản dịch tiếng Việt do AI thực hiện, có thể có sai sót.