Как работают эмуляторы и как они написаны?[закрыто]

StackOverflow https://stackoverflow.com/questions/448673

  •  19-08-2019
  •  | 
  •  

Вопрос

Как работают эмуляторы?Когда я вижу эмуляторы NES / SNES или C64, это поражает меня.

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

Нужно ли вам эмулировать процессор этих машин, интерпретируя его конкретные инструкции по сборке?Что еще входит в это?Как они обычно проектируются?

Можете ли вы дать какой-либо совет для тех, кто заинтересован в написании эмулятора (в частности, игровой системы)?

Это было полезно?

Решение

Эмуляция - это многогранная область.Вот основные идеи и функциональные компоненты.Я собираюсь разбить его на части, а затем внести детали с помощью правок.Многие вещи, которые я собираюсь описать, потребуют знания внутренней работы процессоров - знание сборки необходимо.Если я слишком расплывчато излагаю некоторые вещи, пожалуйста, задавайте вопросы, чтобы я мог продолжать улучшать этот ответ.

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

Эмуляция работает путем обработки поведения процессора и отдельных компонентов.Вы создаете каждую отдельную часть системы, а затем соединяете их так же, как провода соединяются в оборудовании.

Эмуляция процессора:

Существует три способа обработки эмуляции процессора:

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

Используя все эти пути, вы преследуете одну и ту же общую цель:выполните фрагмент кода для изменения состояния процессора и взаимодействия с "оборудованием".Состояние процессора - это совокупность регистров процессора, обработчиков прерываний и т.д. Для данного целевого процессора.Для 6502 у вас будет несколько 8-битных целых чисел, представляющих регистры: A, X, Y, P, и S;у вас также был бы 16-битный PC Зарегистрироваться.

Что касается устного перевода, вы начинаете с IP (указатель инструкции - также называется PC, счетчик программ) и считывает инструкцию из памяти.Ваш код анализирует эту инструкцию и использует эту информацию для изменения состояния процессора, как указано вашим процессором.Основная проблема с интерпретацией заключается в том, что она очень медленно;каждый раз, когда вы обрабатываете данную инструкцию, вы должны расшифровать ее и выполнить необходимую операцию.

При динамической перекомпиляции вы выполняете итерацию по коду, во многом аналогичную интерпретации, но вместо простого выполнения кодов операций вы создаете список операций.Как только вы достигнете инструкции перехода, вы компилируете этот список операций в машинный код для вашей хост-платформы, затем кэшируете этот скомпилированный код и выполняете его.Затем, когда вы снова нажмете на заданную группу команд, вам останется только выполнить код из кэша.(Кстати, большинство людей на самом деле не составляют список инструкций, а компилируют их в машинный код "на лету" - это затрудняет оптимизацию, но это выходит за рамки данного ответа, если только достаточное количество людей не заинтересовано)

При статической перекомпиляции вы делаете то же самое, что и при динамической перекомпиляции, но вы следуете ветвям.В конечном итоге вы создаете фрагмент кода, представляющий весь код в программе, который затем может быть выполнен без дальнейшего вмешательства.Это был бы отличный механизм, если бы не следующие проблемы:

  • Код, которого нет в программе с самого начала (напримерсжатый, зашифрованный, сгенерированный / измененный во время выполнения и т.д.) Не будет перекомпилирован, поэтому он не будет запущен
  • Было доказано, что нахождение всего кода в данном двоичном файле эквивалентно Проблема остановки

Все это в совокупности делает статическую перекомпиляцию полностью неосуществимой в 99% случаев.Для получения дополнительной информации Майкл Стайл провел несколько замечательных исследований в области статической перекомпиляции - лучшее, что я видел.

Другой стороной эмуляции процессора является способ, которым вы взаимодействуете с оборудованием.У этого действительно есть две стороны:

  • Синхронизация процессора
  • Обработка прерываний

Синхронизация процессора:

Некоторые платформы, особенно старые консоли, такие как NES, SNES и т.д., Требуют, чтобы ваш эмулятор имел строгую синхронизацию для обеспечения полной совместимости.В NES у вас есть PPU (модуль обработки пикселей), который требует, чтобы центральный процессор вводил пиксели в свою память в определенные моменты.Если вы используете интерпретацию, вы можете легко подсчитывать циклы и эмулировать правильное время;при динамической / статической перекомпиляции все становится намного сложнее.

Обработка прерываний:

Прерывания - это основной механизм, с помощью которого центральный процессор взаимодействует с аппаратным обеспечением.Как правило, ваши аппаратные компоненты сообщают процессору, о каких прерываниях он заботится.Это довольно просто - когда ваш код выдает заданное прерывание, вы смотрите на таблицу обработчиков прерываний и вызываете соответствующий обратный вызов.

Аппаратная эмуляция:

Эмуляция данного аппаратного устройства имеет две стороны:

  • Эмулирование функциональности устройства
  • Эмуляция реальных интерфейсов устройств

Возьмем случай с жестким диском.Функциональность эмулируется путем создания резервного хранилища, процедур чтения / записи / форматирования и т.д.Эта часть, как правило, очень проста.

Фактический интерфейс устройства немного сложнее.Обычно это некоторая комбинация отображенных в память регистров (например,части памяти, которые устройство отслеживает на предмет изменений для подачи сигналов) и прерываний.Для жесткого диска у вас может быть отображенная область памяти, куда вы помещаете команды чтения, записи и т.д., а затем считываете эти данные обратно.

Я бы вдался в подробности, но есть миллион способов, которыми вы можете воспользоваться.Если у вас есть какие-либо конкретные вопросы здесь, не стесняйтесь задавать, и я добавлю информацию.

Ресурсы:

Я думаю, что я дал здесь довольно хорошее вступление, но есть тонна дополнительных областей.Я более чем рад помочь с любыми вопросами;Я был очень расплывчат в большинстве этих вопросов просто из-за огромной сложности.

Обязательные ссылки на Википедию:

Общие ресурсы эмуляции:

  • Зофар -- Именно здесь я начал заниматься эмуляцией, сначала скачав эмуляторы и в конце концов разграбив их огромные архивы документации.Это абсолютно лучший ресурс, который у вас только может быть.
  • НГЕму -- Не так много прямых ресурсов, но их форумы непревзойденны.
  • RomHacking.net -- Раздел "Документы" содержит ресурсы, касающиеся архитектуры компьютера для популярных консолей

Проекты эмулятора для ссылки:

  • Айронбейбл -- Это платформа эмуляции для .NET, написанная на Nemerle и перекомпилирующая код на C # "на лету".Отказ от ответственности:Это мой проект, так что простите за бесстыдную затычку.
  • БСнес -- Потрясающий эмулятор SNES с целью обеспечения идеальной точности цикла.
  • МЭЙМ -- Тот Самый аркадный эмулятор.Отличная рекомендация.
  • 6502asm.com -- Это эмулятор JavaScript 6502 с классным маленьким форумом.
  • dynarec'd 6502asm -- Это небольшой хак, который я сделал за день или два.Я взял существующий эмулятор из 6502asm.com и изменил его, чтобы динамически перекомпилировать код на JavaScript для значительного увеличения скорости.

Ссылки на перекомпиляцию процессора:

  • Исследование статической перекомпиляции, проведенное Майклом Стайлом (упомянутым выше), завершилось этот документ и вы можете найти источник и тому подобное здесь.

Добавление:

Прошло уже больше года с тех пор, как был отправлен этот ответ, и, учитывая все внимание, которое он привлек, я решил, что пришло время кое-что обновить.

Пожалуй, самая захватывающая вещь в эмуляции прямо сейчас - это libcpu, начатый вышеупомянутым Майклом Стайлом.Это библиотека, предназначенная для поддержки большого количества ядер процессора, которые используют LLVM для перекомпиляции (статической и динамической!).У него огромный потенциал, и я думаю, что он отлично подойдет для подражания.

emu-документы также было доведено до моего сведения, что в нем находится отличное хранилище системной документации, которое очень полезно для целей эмуляции.Я провел там не так уж много времени, но, похоже, у них много замечательных ресурсов.

Я рад, что этот пост был полезен, и я надеюсь, что смогу оторвать свою задницу от работы и закончить свою книгу на эту тему к концу года / началу следующего.

Другие советы

Парень по имени Виктор Мойя дель Баррио написал свою диссертацию на эту тему. Много полезной информации на 152 страницах. Вы можете загрузить PDF .

Если вы не хотите регистрироваться с scribd , вы можете поискать заголовок PDF в Google, " Изучение методов эмуляции программирование Quot &; . Есть несколько источников для PDF.

Эмуляция может показаться сложной, но на самом деле это гораздо проще, чем симуляция.

Любой процессор обычно имеет хорошо написанную спецификацию, которая описывает состояния, взаимодействия и т. д.

Если вы вообще не заботитесь о производительности, вы можете легко эмулировать большинство старых процессоров, используя очень элегантные объектно-ориентированные программы. Например, процессору X86 понадобится что-то, чтобы поддерживать состояние регистров (легко), что-то, чтобы поддерживать состояние памяти (легко), и что-то, что будет принимать каждую входящую команду и применять ее к текущему состоянию машины. Если бы вы действительно хотели точности, вы бы также эмулировали переводы памяти, кэширование и т. Д., Но это выполнимо.

Фактически, многие производители микросхем и процессоров тестируют программы на эмуляторе чипа, а затем на самом чипе, что помогает им выяснить, есть ли проблемы в спецификациях чипа или в фактической реализации чипа. в аппаратном обеспечении. Например, можно написать спецификацию микросхемы, которая привела бы к взаимным блокировкам, и когда в аппаратном обеспечении наступает крайний срок, важно посмотреть, можно ли его воспроизвести в спецификации, поскольку это указывает на большую проблему, чем что-либо в реализации микросхемы.

Конечно, эмуляторы для видеоигр обычно заботятся о производительности, поэтому они не используют наивные реализации, а также включают в себя код, взаимодействующий с операционной системой хост-системы, например, для использования рисования и звука.

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

Я знаю, что этот вопрос немного устарел, но я бы хотел кое-что добавить к обсуждению. Большинство ответов здесь сосредоточены вокруг эмуляторов, интерпретирующих машинные инструкции систем, которые они эмулируют.

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

Впервые я увидел статьи об эмуляторах в печатных журналах, где раньше я видел их только в Интернете.

Концепция UltraHLE заключалась в том, чтобы сделать невозможное возможным путем эмуляции вызовов библиотеки C вместо вызовов на уровне машины.

Стоит обратить внимание на попытку Имрана Назара написать Gameboy эмулятор в JavaScript.

Создав свой собственный эмулятор микрокомпьютера BBC 80-х годов (введите VBeeb в Google), я должен знать ряд вещей.

  • Вы не имитируете реальную вещь как таковую, это была бы точная копия.Вместо этого вы подражаете Состояние.Хороший пример - калькулятор, у реальной вещи есть кнопки, экран, корпус и т.д.Но чтобы эмулировать калькулятор, вам нужно только эмулировать, расположены ли кнопки вверх или вниз, какие сегменты ЖК-дисплея включены и т.д.По сути, набор чисел, представляющих все возможные комбинации вещей, которые могут измениться в калькуляторе.
  • Вам нужно только, чтобы интерфейс эмулятора отображался и вел себя как настоящий.Чем убедительнее это звучит, тем ближе эмуляция.То, что происходит за кулисами, может быть чем угодно.Но для простоты написания эмулятора существует ментальное сопоставление, которое происходит между реальной системой, т.е.чипы, дисплеи, клавиатуры, печатные платы и абстрактный компьютерный код.
  • Чтобы эмулировать компьютерную систему, проще всего разбить ее на более мелкие фрагменты и эмулировать эти фрагменты по отдельности.Затем нанизайте всю массу вместе для получения готового изделия.Очень похоже на набор черных ящиков с входами и выходами, который прекрасно подходит для объектно-ориентированного программирования.Вы можете дополнительно разделить эти фрагменты, чтобы облегчить себе жизнь.

Практически говоря, вы, как правило, стремитесь писать для скорости и точности эмуляции.Это связано с тем, что программное обеспечение в целевой системе будет (может) работать медленнее, чем исходное оборудование в исходной системе.Это может ограничить выбор языка программирования, компиляторов, целевой системы и т.д.
В дополнение к этому вы должны описать, что вы готовы эмулировать, например, нет необходимости эмулировать состояние напряжения транзисторов в микропроцессоре, но, вероятно, необходимо эмулировать состояние набора регистров микропроцессора.
Вообще говоря, чем меньше уровень детализации эмуляции, тем большую точность вы получите по отношению к исходной системе.
Наконец, информация для старых систем может быть неполной или вообще отсутствовать.Поэтому очень важно заполучить оригинальное оборудование или, по крайней мере, разобрать еще один хороший эмулятор, написанный кем-то другим!

Да, вы должны интерпретировать всю путаницу двоичного машинного кода & вручную " ;. Мало того, в большинстве случаев вам также приходится моделировать какое-то экзотическое оборудование, которое не имеет эквивалента на целевой машине.

Простой подход состоит в том, чтобы интерпретировать инструкции один за другим. Это хорошо работает, но медленно. Более быстрый подход - это перекомпиляция - перевод исходного машинного кода в целевой машинный код. Это сложнее, так как большинство инструкций не будут отображаться один на один. Вместо этого вам придется делать сложные обходные пути, которые включают дополнительный код. Но в конце концов это намного быстрее. Большинство современных эмуляторов делают это.

При разработке эмулятора вы интерпретируете сборку процессора, на которой работает система (Z80, 8080, процессор PS и т. д.).

Вам также необходимо эмулировать все периферийные устройства, которые есть в системе (видеовыход, контроллер).

Вы должны начать писать эмуляторы для систем simpe, таких как старый добрый Game Boy (который использует процессор Z80, я не ошибаюсь) ИЛИ для C64.

  

Эмулятор очень сложно создать, так как есть много хаков (как в необычном   эффекты), проблемы времени и т. д., которые вам нужно смоделировать.

Пример этого см. в http://queue.acm.org/detail .cfm? ID = 1755886 .

Это также покажет вам, почему вы & # 8216; нужны & # 8217; многогГц процессор для эмуляции 1 МГц.

Также ознакомьтесь с Emulators.com Дареком Михоцкой (Darek Mihocka) за полезные советы по оптимизации уровня инструкций для JIT и многими другими полезными моментами. по созданию эффективных эмуляторов.

Я никогда не делал ничего такого фантастического, чтобы эмулировать игровую консоль, но однажды я прошел курс, где было задание написать эмулятор для машины, описанной в Andrew Tanenbaums Структурированная компьютерная организация . Это было весело и дало мне много моментов ага. Возможно, вы захотите взять эту книгу, прежде чем углубиться в написание настоящего эмулятора.

Советы по эмуляции реальной системы или вашей собственной вещи? Я могу сказать, что эмуляторы работают, эмулируя все оборудование. Может быть, не в цепи (как перемещение битов, как HW сделал бы. Перемещение байта является конечным результатом, поэтому копирование байта в порядке). Эмулятор очень сложно создать, так как вам нужно смоделировать множество хаков (например, необычных эффектов), проблем с синхронизацией и т. Д. Если один (входной) фрагмент неправильный, вся система может не работать или в лучшем случае иметь ошибку / сбой.

Эмулятор устройства с общим исходным кодом содержит сборку исходный код для эмулятора PocketPC / Smartphone (требуется Visual Studio, работает под Windows). Я работал над V1 и V2 двоичного релиза.

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

Чтобы добавить ответ, предоставленный @Cody Brocious
В контексте виртуализации, когда вы эмулируете новую систему (ЦП, В / В и т. Д.) Для виртуальной машины, мы можем видеть следующие категории эмуляторов.

Интерпретация: bochs является примером интерпретатора, это эмулятор ПК для x86, он берет каждую инструкцию из гостевой системы, переводит ее в другой набор инструкций (ISA хоста) для получения желаемого эффекта. Да, это очень медленно , он ничего не кэширует, поэтому каждая инструкция проходит один и тот же цикл.

Динамический эмулятор: Qemu - это динамический эмулятор. Он выполняет на лету перевод гостевой инструкции, а также кеширует результаты. Лучшая часть заключается в том, что как можно больше команд выполняется непосредственно в хост-системе, что ускоряет эмуляцию. Также, как упомянул Коди, он делит код на блоки (1 поток выполнения).

Статический эмулятор. Насколько я знаю, нет статического эмулятора, который мог бы помочь в виртуализации.

Как мне начать эмуляцию.

1.Получайте книги, основанные на низкоуровневом программировании, вам это понадобится для " pretend " операционная система Nintendo ... Game Boy ...

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

3. посмотрите на некоторые эмуляторы с открытым исходным кодом, особенно те, для которых вы хотите создать эмулятор.

4. скопируйте фрагменты более сложного кода в ваш IDE / компилятор. Это избавит вас от написания длинного кода. Это то, что я делаю для разработки под OS, использую район linux

Я написал статью об эмуляции системы Chip-8 в JavaScript .

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

Я скоро напишу более длинное руководство для NES.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top