Як працюють емулятори та як вони записуються? [зачинено]


968

Як працюють емулятори? Коли я бачу емулятори NES / SNES або C64, це мене вражає.

http://www.tommowalker.co.uk/snemzelda.png

Чи потрібно вам наслідувати процесор цих машин, інтерпретуючи його конкретні інструкції по збірці? Що ще йде в це? Як вони зазвичай розроблені?

Чи можете ви дати будь-яку пораду тому, хто зацікавлений у написанні емулятора (зокрема, ігрової системи)?


15
Найважливіше, що вам потрібно знайти, - це "посібник з програміста" для цієї системи, оскільки він детально описує "контракт" між постачальником HW та програмістами, а також приховує деталі, які не є актуальними та можуть змінитися. Ваші шанси залежать від популярності системи.
Урі

155
Гарний вибір гри.
Кріштіан Ромо


16
Для всіх, хто цікавиться Емуляція проти Моделювання
Lazer

8
З першого разу, коли я грав у цю гру, я завжди цікавився, чому Hyrule завалений валунами «8-Ball» :-)
Вівіан-Рівер,

Відповіді:


1124

Емуляція - багатогранна область. Ось основні ідеї та функціональні компоненти. Я збираюся розбити його на шматки, а потім заповнити деталі через правки. Для багатьох речей, які я збираюсь описати, знадобляться внутрішні роботи процесорів - знання про збірку необхідні. Якщо я трохи розпливчав певні речі, будь ласка, задайте питання, щоб я міг продовжувати вдосконалювати цю відповідь.

Основна ідея:

Емуляція працює за допомогою поведінки процесора та окремих компонентів. Ви будуєте кожен окремий фрагмент системи, а потім з'єднуєте шматки, як і дроти в апараті.

Емуляція процесора:

Існує три способи обробки емуляції процесора:

  • Інтерпретація
  • Динамічна рекомпіляція
  • Статична рекомпіляція

З усіма цими шляхами у вас однакова загальна мета: виконати фрагмент коду, щоб змінити стан процесора та взаємодіяти з "обладнанням". Стан процесора - це конгломерація регістрів процесорів, обробників переривань тощо для заданої цілі процесора. Для 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 , де розміщено чудовий сховище системної документації, що дуже корисно для цілей емуляції. Я там не проводив багато часу, але, схоже, у них багато великих ресурсів.

Я радий, що цей пост був корисним, і я сподіваюся, що зможу зійти з дупи і закінчити свою книгу на цю тему до кінця року / початку наступного року.


37
Це вже є епічною відповіддю. Якщо ви можете вказати мені на будь-які ресурси, то в кінцевому підсумку це буде вдячно. Я дивлюся, можливо, на систему SNES або NES, щоб наслідувати і зробити це моїм семестровим проектом.
mmcdole

8
Звичайно. Я збираюся зібрати хороший список ресурсів. Якщо у вас є якісь конкретні запити, я зроблю все можливе, щоб їх заповнити.
Cody Brocious

3
@thenonhacker, проект IronBabel, на який йдеться у розділі моїх ресурсів, є моїм. (Безсоромний штекер позначений;))
Коді Броші

1
"Доведено, що пошук усіх кодів у заданому бінарному еквіваленті задачі зупинки" - Посилання, будь ласка? Або це повинно бути "Доведено, що пошук усіх кодів у будь-якому двійковому еквіваленті еквівалентний проблемі зупинки"? Також не можна отримати доступ до папери
Steil

4
Ви згадуєте, що пишете книгу; Ви можете, будь ласка, надати нам оновлення щодо цього? Мені, наприклад, було б цікаво її прочитати.
алекс

126

Хлопець на ім’я Віктор Моя дель Барріо написав дисертацію на цю тему. Багато хорошої інформації на 152 сторінках. Ви можете завантажити PDF тут .

Якщо ви не хочете реєструватися в scribd , ви можете перейти в Google за назвою PDF "Вивчення методів програмування емуляції" . Існує кілька різних джерел для PDF.


43

Емуляція може здатися жахливою, але насправді є досить легшою, ніж імітувати.

Будь-який процесор, як правило, має добре написану специфікацію, яка описує стани, взаємодії тощо.

Якщо ви взагалі не піклувались про продуктивність, то ви могли легко наслідувати більшість старих процесорів, використовуючи дуже елегантні об'єктно-орієнтовані програми. Наприклад, процесору X86 знадобиться щось для підтримання стану регістрів (легко), щось для підтримки стану пам'яті (легко), а також щось, що займе кожну вхідну команду і застосує її до поточного стану машини. Якщо ви дійсно хотіли точності, ви також імітували б переклади пам'яті, кешування тощо, але це можливо.

Насправді багато виробників мікрочіпів і процесорів тестують програми на емуляторі мікросхеми, а потім і на самій мікросхемі, що допомагає їм з'ясувати, чи є проблеми в специфікаціях мікросхеми або в реальній реалізації чіпа в апаратному забезпеченні. Наприклад, можна написати специфікацію мікросхеми, яка б призвела до тупикових ситуацій, і коли в апараті настає крайній термін, важливо зрозуміти, чи може він бути відтворений у специфікації, оскільки це свідчить про більшу проблему, ніж щось у реалізації чіпа.

Звичайно, емулятори для відеоігор зазвичай дбають про продуктивність, тому вони не використовують наївних реалізацій, а також вони включають код, який взаємодіє з ОС приймаючої системи, наприклад, для використання малювання та звуку.

Враховуючи дуже повільну продуктивність старих відеоігор (NES / SNES тощо), емуляція в сучасних системах досить проста. Насправді, навіть дивовижніше, що ви можете просто завантажити набір будь-якої гри SNES будь-коли або будь-яку гру Atari 2600 коли-небудь, враховуючи, що коли ці системи були популярними, вільний доступ до кожного картриджа був би мрією.


1
Які відмінності між емуляцією та імітацією?
Вей Ху

2
@Wei: Взагалі кажучи, емулятор повинен поводитися "зовні", як система, яку він емулює, але нічого не можна сказати, що він повинен бути реалізований аналогічно. Симулятор реалізований таким чином, що імітує змодельовану систему, і в результаті поводиться так.
Урі

Коли ви бачите "Симулятор", подумайте про його схоже, тоді як емулятор "емулює"
mP.


29

Я знаю, що це питання трохи старе, але я хотів би щось додати до дискусії. Більшість відповідей тут зосереджені на емуляторах, що інтерпретують машинні інструкції систем, які вони емулюють.

Однак є дуже відомий виняток із цього під назвою "UltraHLE" ( стаття WIKIpedia ). UltraHLE, один з найвідоміших емуляторів, який коли-небудь створювався, наслідував комерційні ігри Nintendo 64 (з гідною продуктивністю на домашніх комп’ютерах) у той час, коли це вважалося неможливим зробити. По суті, Nintendo все ще випускав нові назви для Nintendo 64, коли був створений UltraHLE!

Вперше я побачив статті про емулятори в журналах друку, де раніше я бачив лише їх обговорення в Інтернеті.

Концепція UltraHLE полягала в тому, щоб зробити неможливим шляхом емуляції викликів бібліотеки C замість викликів машинного рівня.


22

Щось, на що варто звернути увагу, - це спроба Імрана Назара написати емулятор Gameboy на JavaScript.


1
Як ми можемо отримати необроблені інструкції з коду для гри Gameboy?
Pacerier

Існує ряд пристроїв, доступних для продажу на "сірому ринку". Ви їх не знайдете в жодному великому магазині розвиненого світу. Ці пристрої здатні копіювати інструкції з ігрового картриджа у файли, які зазвичай називаються "ПЗУ". Google "Gameboy Roms", але стежте за небезпечними для роботи посиланнями та атаками на сайти!
Вівіан-Рівер

18

Створивши власний емулятор мікрокомп'ютера BBC 80-х років (введіть VBeeb в Google), потрібно знати кілька речей.

  • Ви не наслідуєте справжню річ як таку, що була б реплікаю. Натомість ви емілюєте штат . Хороший приклад - це калькулятор, у реальній речі є кнопки, екран, корпус і т. Д. Але для емуляції калькулятора потрібно лише емулювати, чи кнопки вгору чи вниз, на яких сегментах РК є і т.д. В основному, набір цифр що представляють усі можливі комбінації речей, які можуть змінюватися в калькуляторі.
  • Вам потрібен лише інтерфейс емулятора, щоб він відображався і поводився як реальна річ. Чим переконливіше це, тим ближче емуляція. Те, що відбувається за лаштунками, може бути чим завгодно. Але для зручності написання емулятора існує ментальне відображення, яке відбувається між реальною системою, тобто мікросхеми, дисплеї, клавіатури, плати та абстрактний комп'ютерний код.
  • Щоб наслідувати комп'ютерну систему, найпростіше розбити її на менші шматки та імітувати ці шматки окремо. Потім з'єднайте цілу партію разом для готового продукту. Так само, як набір чорних коробок із входами та виходами, який прекрасно піддається об'єктно-орієнтованому програмуванню. Ви можете далі поділити ці шматки, щоб полегшити життя.

Практично кажучи, ви, як правило, прагнете писати для швидкості та вірності емуляції. Це відбувається тому, що програмне забезпечення в цільовій системі (може) працювати повільніше, ніж оригінальне обладнання в вихідній системі. Це може обмежувати вибір мови програмування, компіляторів, цільової системи тощо.
Крім того, вам доведеться описати те, що ви готові емулювати, наприклад, його не потрібно емулювати стан напруги транзисторів у мікропроцесорі, але, ймовірно, це необхідно емуляція стану регістрового набору мікропроцесора.
Взагалі кажучи, чим менший рівень деталізації емуляції, тим більше вірності ви отримаєте до оригінальної системи.
Нарешті, інформація для старих систем може бути неповною або неіснуючою. Отож, захоплення оригінального обладнання є надзвичайно важливим або, принаймні, розірвати ще один хороший емулятор, який написав хтось інший!


17

Так, ви повинні інтерпретувати весь безлад бінарного коду машини "вручну". Мало того, більшість часу вам також доведеться імітувати екзотичне обладнання, яке не має еквівалента на цільовій машині.

Простий підхід - інтерпретувати інструкції по одному. Це працює добре, але це повільно. Більш швидким підходом є рекомпіляція - переведення вихідного машинного коду на цільовий код машини. Це складніше, оскільки більшість інструкцій не відображає один на один. Натомість вам доведеться скласти складні робочі кола, які містять додатковий код. Але зрештою це набагато швидше. Більшість сучасних емуляторів роблять це.


1
Найгірше - це відсутність документації. Коли ви дізнаєтесь, що в модифікованому ядрі Z80 в GameBoy Color є недокументовані операції з прапором, які гра, яку ви протестуєте, використовує, що ви дійсно починаєте втрачати віру.
Callum Rogers

1
Pet peeve: це машинний код (однина), а не машинні коди (множина); так само, як це Морзе Кодекс, а не Морзе Кодекси .
Лоуренс Дол

1
@Vilx: Насправді ні - термін "машинний код", що посилається на набір інструкцій для центрального процесора, використовується з моменту створення програмного забезпечення і не є множиною. Це стосується " набору інструкцій ", форми однини, а не форми "множини" множини. Те саме, що програмний код, код Морзе та ін. Використання форми множини виникла з-за неправильного використання, як правило, тими, хто говорить англійською мовою як другою мовою.
Лоуренс Дол

1
@Software Monkey - Але чи не можу я використати слово "код" для позначення одного елемента з набору? Наприклад: " ... --- ...- ці три коди Морзе представляють три букви S, O, S." Тому що ...це код, що представляє букву "S". Ні?
Vilx-

1
Ні, код - це незлічуваний іменник, він не має форми множини, як вода чи пісок ..
Іван

15

Коли ви розробляєте емулятор, ви інтерпретуєте збірку процесора, над якою працює система (Z80, 8080, процесор PS та ін.).

Вам також потрібно емулювати всі периферійні пристрої, які має система (відеовихід, контролер).

Ви повинні почати писати емулятори для спрощених систем, таких як старий хороший Game Boy (які використовують процесор Z80, я не помиляюся) АБО для C64.


9
C64 "проста" система? У той час як 6510 порівняно простий (після того, як ви покрили незакреслені опкоди), звукові (SID) та відео (VIC) мікросхеми - це не що інше, як просте. Щоб досягти будь-якого гідного рівня сумісності, вам потрібно буде імітувати їх - апаратні помилки та інше.
moobaa

10

Емулятор дуже важко створити, оскільки існує безліч хак (як у незвичайних ефектах), проблем із тимчасовим позначенням тощо, які потрібно імітувати.

Для прикладу цього див. Http://queue.acm.org/detail.cfm?id=1755886 .

Це також покаже вам, чому вам потрібен процесор багато ГГц для емуляції 1 МГц.


9

Також перегляньте Emulators.com Darek Mihocka для чудових порад щодо оптимізації рівня інструкцій для JIT та багатьох інших приємностей щодо створення ефективних емуляторів.


7

Я ніколи не робив нічого такого фантазійного, щоб наслідувати ігрову консоль, але я одного разу пройшов курс, коли завданням було написати емулятор для машини, описану в організації «Structured Computer Organisation» Andrew Tanenbaums . Це було весело, дало мені багато ага моментів. Можливо, ви захочете забрати цю книгу, перш ніж зануритися, щоб написати справжній емулятор.


4

Поради щодо емуляції реальної системи чи власної речі? Я можу сказати, що емулятори працюють за допомогою емуляції цілого обладнання. Можливо, не вниз до ланцюга (як би це робило переміщення бітів, як HW. Переміщення байта - це кінцевий результат, тому копіювання байта добре). Емулятор дуже важко створити, оскільки існує безліч хак (як у незвичайних ефектах), проблем із тимчасовим позначенням тощо, які потрібно імітувати. Якщо один (вхідний) фрагмент невірний, то вся система може знищити або в кращому випадку мати помилку / збій.


4

Shared Source Device Emulator містить працездатна вихідний код емулятора PocketPC / Smartphone (Потрібно Visual Studio, працює на Windows). Я працював над V1 та V2 бінарного випуску.

Він вирішує багато питань емуляції: - ефективний переклад адрес з віртуального гостя до фізичного гостя до віртуального хоста - компіляція гостьового коду JIT - моделювання периферійних пристроїв, таких як мережеві адаптери, сенсорний екран та аудіо - інтеграція інтерфейсу користувача, для клавіатури та миші хосту - зберегти / відновлення стану, для моделювання резюме з режиму малої потужності


1

Щоб додати відповідь, надану @Cody Brocious
У контексті віртуалізації, де ви емулюєте нову систему (процесор, введення / виведення тощо) у віртуальну машину, ми можемо побачити наступні категорії емуляторів.

Інтерпретація: bochs - приклад інтерпретатора, це емулятор ПК x86, кожна інструкція від гостьової системи переводить її в інший набір інструкцій (про ISA хоста) для отримання наміченого ефекту. Так, це дуже повільно, це не робить не кешуйте нічого, тому кожна інструкція проходить в одному циклі.

Динамічний емулятор: Qemu - це динамічний емулятор. Це робить при перекладі гостьової інструкції також кешування результатів. Найкраща частина полягає в тому, щоб виконати якомога більше вказівок безпосередньо на хост-системі, щоб емуляція була швидшою. Також, як згадував Коді, він ділить код на блоки (1 єдиний потік виконання).

Статичний емулятор: Наскільки я знаю, не існує статичного емулятора, який може бути корисним у віртуалізації.


1

Як би я почав емуляцію

1.Будьте книги, засновані на програмуванні низького рівня, вам знадобляться для "прикидання" операційної системи Nintendo ... ігровий хлопчик ...

2.Отримайте книги про емуляцію, зокрема, і, можливо, осн. (ви не будете робити ос, але найближчий до нього.

3.перегляньте деякі емулятори з відкритим кодом, особливо в тій системі, для якої потрібно зробити емулятор.

4.копіюйте фрагменти більш складного коду у свій IDE / компілятор. Це допоможе вам заощадити довгий код. Це те, що я роблю для розробки ОС, використовую район Linux


1

Я написав статтю про емуляцію системи Chip-8 в JavaScript .

Це чудове місце для початку, оскільки система не дуже складна, але ви все одно дізнаєтесь, як працюють опкоди, стек, регістри тощо.

Я незабаром буду писати довший посібник для ДНЗ.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.