Thi đua là một lĩnh vực nhiều mặt. Dưới đây là những ý tưởng cơ bản và các thành phần chức năng. Tôi sẽ chia nó thành từng mảnh và sau đó điền chi tiết thông qua các chỉnh sửa. Nhiều điều tôi sẽ mô tả sẽ đòi hỏi kiến thức về hoạt động bên trong của bộ xử lý - kiến thức lắp ráp là cần thiết. Nếu tôi hơi mơ hồ về một số điều nhất định, xin vui lòng đặt câu hỏi để tôi có thể tiếp tục cải thiện câu trả lời này.
Ý kiến cơ bản:
Thi đua hoạt động bằng cách xử lý hành vi của bộ xử lý và các thành phần riêng lẻ. Bạn xây dựng từng phần riêng lẻ của hệ thống và sau đó kết nối các phần giống như dây dẫn trong phần cứng.
Thi đua xử lý:
Có ba cách xử lý mô phỏng bộ xử lý:
- Diễn dịch
- Biên dịch động
- Biên dịch tĩnh
Với tất cả các đường dẫn này, bạn có cùng một mục tiêu chung: thực thi một đoạn mã để sửa đổi trạng thái bộ xử lý và tương tác với 'phần cứng'. Trạng thái bộ xử lý là tập hợp các thanh ghi bộ xử lý, bộ xử lý ngắt, v.v. cho một mục tiêu bộ xử lý đã cho. Đối với 6502, bạn muốn có một số nguyên 8-bit đại diện cho thanh ghi: A
, X
, Y
, P
, và S
; bạn cũng có một thanh ghi 16 bit PC
.
Với giải thích, bạn bắt đầu tại IP
(con trỏ lệnh - còn được gọi là bộ PC
đếm chương trình) và đọc hướng dẫn từ bộ nhớ. Mã của bạn phân tích cú pháp hướng dẫn này và sử dụng thông tin này để thay đổi trạng thái bộ xử lý như được chỉ định bởi bộ xử lý của bạn. Vấn đề cốt lõi với giải thích là nó rất chậm; mỗi lần bạn xử lý một lệnh đã cho, bạn phải giải mã nó và thực hiện thao tác cần thiết.
Với tính năng biên dịch lại động, bạn lặp lại mã giống như diễn giải, nhưng thay vì chỉ thực thi các mã, bạn xây dựng một danh sách các hoạt động. Khi bạn đạt được một hướng dẫn chi nhánh, bạn biên dịch danh sách các hoạt động này thành mã máy cho nền tảng máy chủ của bạn, sau đó bạn lưu bộ đệm được biên dịch mã này và thực hiện nó. Sau đó, khi bạn nhấn lại một nhóm hướng dẫn cụ thể, bạn chỉ phải thực thi mã từ bộ đệm. .
Với biên dịch lại tĩnh, bạn thực hiện tương tự như trong biên dịch lại động, nhưng bạn theo các nhánh. Cuối cùng, bạn xây dựng một đoạn mã đại diện cho tất cả các mã trong chương trình, sau đó có thể được thực thi mà không bị can thiệp thêm. Đây sẽ là một cơ chế tuyệt vời nếu không có các vấn đề sau:
- Mã không có trong chương trình để bắt đầu (ví dụ: được nén, mã hóa, tạo / sửa đổi trong thời gian chạy, v.v.) sẽ không được biên dịch lại, vì vậy nó sẽ không chạy
- Nó đã được chứng minh rằng việc tìm tất cả các mã trong một nhị phân nhất định là tương đương với vấn đề Dừng
Chúng kết hợp để làm cho biên dịch lại hoàn toàn không khả thi trong 99% trường hợp. Để biết thêm thông tin, Michael Steil đã thực hiện một số nghiên cứu tuyệt vời về biên dịch tĩnh - thứ tốt nhất tôi từng thấy.
Mặt khác của mô phỏng bộ xử lý là cách bạn tương tác với phần cứng. Điều này thực sự có hai mặt:
- Thời gian xử lý
- Xử lý ngắt
Thời gian xử lý:
Một số nền tảng - đặc biệt là các bảng điều khiển cũ hơn như NES, SNES, v.v. - yêu cầu trình giả lập của bạn phải có thời gian nghiêm ngặt để hoàn toàn tương thích. Với NES, bạn có PPU (đơn vị xử lý pixel) yêu cầu CPU đưa pixel vào bộ nhớ vào những thời điểm chính xác. Nếu bạn sử dụng giải thích, bạn có thể dễ dàng đếm chu kỳ và mô phỏng thời gian thích hợp; với biên dịch lại động / tĩnh, mọi thứ rất / phức tạp / phức tạp hơn.
Xử lý ngắt:
Ngắt là cơ chế chính mà CPU giao tiếp với phần cứng. Nói chung, các thành phần phần cứng của bạn sẽ cho CPU biết những gì làm gián đoạn nó quan tâm. Điều này khá đơn giản - khi mã của bạn ném một ngắt nhất định, bạn nhìn vào bảng xử lý ngắt và gọi hàm gọi lại thích hợp.
Giả lập phần cứng:
Có hai mặt để mô phỏng một thiết bị phần cứng nhất định:
- Mô phỏng chức năng của thiết bị
- Mô phỏng các giao diện thiết bị thực tế
Lấy trường hợp của một ổ cứng. Các chức năng được mô phỏng bằng cách tạo lưu trữ sao lưu, thói quen đọc / ghi / định dạng, vv Phần này thường rất đơn giản.
Giao diện thực tế của thiết bị phức tạp hơn một chút. Đây thường là một số kết hợp của các thanh ghi ánh xạ bộ nhớ (ví dụ như các phần của bộ nhớ mà thiết bị theo dõi để thay đổi để thực hiện báo hiệu) và ngắt. Đối với ổ cứng, bạn có thể có một khu vực được ánh xạ bộ nhớ nơi bạn đặt các lệnh đọc, ghi, v.v., sau đó đọc lại dữ liệu này.
Tôi sẽ đi vào chi tiết hơn, nhưng có một triệu cách bạn có thể đi với nó. Nếu bạn có bất kỳ câu hỏi cụ thể nào ở đây, vui lòng hỏi và tôi sẽ thêm thông tin.
Tài nguyên:
Tôi nghĩ rằng tôi đã đưa cho một tốt đẹp giới thiệu ở đây, nhưng có một tấn của khu vực bổ sung. Tôi rất vui được giúp đỡ với bất kỳ câu hỏi nào; Tôi đã rất mơ hồ trong hầu hết điều này chỉ đơn giản là do sự phức tạp to lớn.
Liên kết Wikipedia bắt buộc:
Tài nguyên thi đua chung:
- Zophar - Đây là nơi tôi bắt đầu với việc mô phỏng, đầu tiên tải xuống trình giả lập và cuối cùng là đánh cắp tài liệu lưu trữ khổng lồ của họ. Đây là tài nguyên tuyệt đối tốt nhất bạn có thể có.
- NGEmu - Không có nhiều tài nguyên trực tiếp, nhưng diễn đàn của họ là vô địch.
- RomHacking.net - Phần tài liệu chứa các tài nguyên liên quan đến kiến trúc máy cho các bảng điều khiển phổ biến
Dự án giả lập để tham khảo:
- IronBabel - Đây là một nền tảng mô phỏng cho .NET, được viết bằng Nemerle và biên dịch lại mã thành C # một cách nhanh chóng. Tuyên bố từ chối trách nhiệm: Đây là dự án của tôi, vì vậy xin lỗi không biết xấu hổ.
- BSnes - Trình giả lập SNES tuyệt vời với mục tiêu chính xác theo chu kỳ.
- MAME - Trình giả lập arcade. Tài liệu tham khảo tuyệt vời.
- 6502asm.com - Đây là trình giả lập JavaScript 6502 với một diễn đàn nhỏ thú vị.
- dynarec'd 6502asm - Đây là một bản hack nhỏ tôi đã thực hiện trong một hoặc hai ngày. Tôi đã lấy trình giả lập hiện có từ 6502asm.com và thay đổi nó để tự động biên dịch lại mã thành JavaScript để tăng tốc độ lớn.
Tài liệu tham khảo biên dịch lại bộ xử lý:
- Nghiên cứu về biên dịch lại tĩnh được thực hiện bởi Michael Steil (được tham khảo ở trên) lên đến đỉnh điểm trong bài báo này và bạn có thể tìm thấy nguồn và như vậy ở đây .
Phụ lục:
Đã hơn một năm kể từ khi câu trả lời này được gửi và với tất cả sự chú ý mà nó đang nhận được, tôi cho rằng đã đến lúc cập nhật một số thứ.
Có lẽ điều thú vị nhất trong thi đua ngay bây giờ là libcpu , được bắt đầu bởi Michael Steil đã nói ở trên. Đó là một thư viện nhằm hỗ trợ một số lượng lớn các lõi CPU, sử dụng LLVM để biên dịch lại (tĩnh và động!). Nó có tiềm năng rất lớn và tôi nghĩ nó sẽ làm những điều tuyệt vời cho việc thi đua.
emu-docs cũng đã được tôi chú ý, nơi chứa một kho tài liệu hệ thống tuyệt vời, rất hữu ích cho mục đích mô phỏng. Tôi đã không dành nhiều thời gian ở đó, nhưng có vẻ như họ có rất nhiều tài nguyên tuyệt vời.
Tôi rất vui vì bài đăng này rất hữu ích và tôi hy vọng tôi có thể rời khỏi mông của mình và hoàn thành cuốn sách của mình về chủ đề này vào cuối năm / đầu năm tới.