Емуляція - багатогранна область. Ось основні ідеї та функціональні компоненти. Я збираюся розбити його на шматки, а потім заповнити деталі через правки. Для багатьох речей, які я збираюсь описати, знадобляться внутрішні роботи процесорів - знання про збірку необхідні. Якщо я трохи розпливчав певні речі, будь ласка, задайте питання, щоб я міг продовжувати вдосконалювати цю відповідь.
Основна ідея:
Емуляція працює за допомогою поведінки процесора та окремих компонентів. Ви будуєте кожен окремий фрагмент системи, а потім з'єднуєте шматки, як і дроти в апараті.
Емуляція процесора:
Існує три способи обробки емуляції процесора:
- Інтерпретація
- Динамічна рекомпіляція
- Статична рекомпіляція
З усіма цими шляхами у вас однакова загальна мета: виконати фрагмент коду, щоб змінити стан процесора та взаємодіяти з "обладнанням". Стан процесора - це конгломерація регістрів процесорів, обробників переривань тощо для заданої цілі процесора. Для 6502, потрібно мати ряд 8-розрядних цілих чисел , що представляють регістри: A
, X
, Y
, P
, і S
; у вас також буде 16-розрядний PC
реєстр.
З інтерпретацією ви починаєте з IP
(покажчик інструкцій - також називається PC
, лічильник програми) і читаєте інструкцію з пам'яті. Ваш код аналізує цю інструкцію і використовує цю інформацію для зміни стану процесора, як зазначено вашим процесором. Основна проблема інтерпретації полягає в тому, що це дуже повільно; щоразу, коли ви обробляєте дану інструкцію, вам доведеться її розшифрувати і виконати необхідну операцію.
За допомогою динамічної рекомпіляції ви повторюєте код, як інтерпретація, але замість того, щоб просто виконувати опкоди, ви складаєте список операцій. Як тільки ви отримаєте інструкцію з філії, ви складете цей список операцій для машинного коду для вашої хост-платформи, потім ви кешіруєте цей складений код і виконайте його. Потім, коли ви знову натиснете задану групу інструкцій, вам потрібно виконати код лише з кешу. (BTW, більшість людей насправді не складають перелік інструкцій, але складають їх для машинного коду на льоту - це ускладнює оптимізацію, але це не входить у сферу цієї відповіді, якщо недостатньо зацікавлених людей)
За допомогою статичної рекомпіляції ви робите те саме, що і в динамічній рекомпіляції, але ви дотримуєтесь гілок. Ви в кінцевому підсумку створюєте шматок коду, який представляє весь код програми, який потім може бути виконаний без додаткових втручань. Це було б чудовим механізмом, якби не наступні проблеми:
- Код, який не починається з програми (наприклад, стиснутий, зашифрований, згенерований / модифікований під час виконання тощо), не буде перекомпільований, тому він не запуститься
- Доведено, що пошук усіх кодів у даному бінарному еквіваленті задачі зупинки
Вони поєднуються, щоб зробити статичну рекомпіляцію абсолютно неможливою у 99% випадків. Для отримання додаткової інформації Майкл Стейл провів кілька чудових досліджень статичної рекомпіляції - найкраще, що я бачив.
Інша сторона емуляції процесора - це спосіб взаємодії з обладнанням. Це дійсно має дві сторони:
- Час виконання процесора
- Переривання роботи
Час виконання процесора:
Деякі платформи - особливо старі консолі, такі як NES, SNES тощо - вимагають, щоб ваш емулятор мав чіткі строки, щоб вони були повністю сумісними. За допомогою NES у вас є ППУ (блок обробки пікселів), який вимагає, щоб ЦП вводив пікселі в свою пам'ять у точні моменти. Якщо ви використовуєте інтерпретацію, ви можете легко рахувати цикли та наслідувати належну хронологію; з динамічною / статичною перекомпіляцією, речі є складнішими.
Переривання роботи:
Переривання - це основний механізм, за допомогою якого процесор спілкується з обладнанням. Як правило, ваші апаратні компоненти повідомлять процесор про те, що його перериває. Це досить просто - коли ваш код кидає задане переривання, ви дивитесь на таблицю обробника переривань і викликаєте належний зворотний виклик.
Емуляція обладнання:
Для емуляції певного апаратного пристрою є дві сторони:
- Емуляція функціональності пристрою
- Емуляція фактичних інтерфейсів пристрою
Візьміть корпус жорсткого диска. Функціонал емулюється створенням резервного сховища, процедурами читання / запису / форматування тощо. Ця частина, як правило, дуже проста.
Фактичний інтерфейс пристрою дещо складніший. Це, як правило, деяка комбінація регістрів, відображених на пам'ять (наприклад, частини пам'яті, які пристрій спостерігає за змінами для сигналізації) та переривання. Для жорсткого диска у вас може бути обладнана карта пам'яті, де ви розміщуєте команди для читання, записи тощо, а потім читаєте ці дані назад.
Я б детальніше зупинився, але є мільйон способів, як ви можете піти з цим. Якщо у вас є якісь конкретні питання тут, не соромтесь запитати, і я додам інформацію.
Ресурси:
Я думаю , що я дав досить гарне інтро тут, але є тонни додаткові області. Я більш ніж радий допомогти з будь-якими питаннями; Я був дуже розпливчастим у більшості цього просто через величезну складність.
Обов’язкові посилання Вікіпедії:
Загальні емуляційні ресурси:
- Zophar - Тут я почав займатися емуляцією, спочатку завантажуючи емулятори та врешті-решт грабуючи їх величезні архіви документації. Це абсолютно найкращий ресурс, який ти можеш мати.
- NGEmu - Не багато прямих ресурсів, але їхні форуми є неперевершеними.
- RomHacking.net - У розділі документів містяться ресурси щодо архітектури машини для популярних консолей
Емуляторні проекти для посилання:
- IronBabel - це емуляційна платформа для .NET, написана в Немерле та перекомпілює код на C # на ходу. Відмова: Це мій проект, тож пробачте безсоромну пробку.
- BSnes - дивовижний емулятор SNES з цільовою ідеальною точністю.
- MAME - емулятор ігрових автоматів . Чудова довідка.
- 6502asm.com - Це емулятор JavaScript 6502 з прохолодним маленьким форумом.
- dynarec'd 6502asm - Це маленький хакер, який я робив протягом дня або двох. Я взяв існуючий емулятор від 6502asm.com і змінив його, щоб динамічно перекомпілювати код у JavaScript для масового збільшення швидкості.
Посилання на перекомпіляцію процесора:
- Дослідження статичної рекомпіляції, проведене Майклом Стейлом (згадане вище), завершилося в цій роботі, і ви можете знайти джерело та подібне тут .
Додаток:
З моменту подання цієї відповіді минуло вже рік, і при всій увазі, яку я привертав, я подумав, що настав час оновити деякі речі.
Мабуть, найцікавіша річ в емуляції зараз - це libcpu , започаткований вищезгаданим Майклом Стейлем. Це бібліотека, призначена для підтримки великої кількості ядер процесора, які використовують LLVM для перекомпіляції (статичної та динамічної!). Він має величезний потенціал, і я думаю, що це зробить чудові речі для наслідування.
Також до мене звернуто увагу emu-docs , де розміщено чудовий сховище системної документації, що дуже корисно для цілей емуляції. Я там не проводив багато часу, але, схоже, у них багато великих ресурсів.
Я радий, що цей пост був корисним, і я сподіваюся, що зможу зійти з дупи і закінчити свою книгу на цю тему до кінця року / початку наступного року.