Различные операции ЦП (IA-32, ARM9 и т.д.) Должны быть эквивалентны по своей природе (перемещение, чтение, запись данных и т.д.). Разным процессорам не должно быть так больно подражать друг другу. Но кажется, что это не так просто, поскольку эмулированное программное обеспечение работает слишком медленно. Можем ли мы просто преобразовать исполняемый файл, а затем выполнить его? В любом случае, почему он так зависит от ресурсов (зачем мне нужен мощный процессор для эмуляции других процессоров)? Должен сказать, что у меня нет больших навыков программирования низкого уровня. Большое спасибо.
2 ответа
Различные операции ЦП (IA-32, ARM9 и т.д.) Должны быть эквивалентны по своей природе (перемещение, чтение, запись данных и т.д.).
Они должны быть, но это не так. Архитектура ЦП реализует эти основные операции в соответствии с тем, как его проектировщики предвидели - и это может сильно отличаться в зависимости от того, что дизайнеры пытаются выполнить. Вещи, которые могут быть выполнены в одной инструкции на некоторых процессорах, могут потребовать много, много инструкций на других.
Можем ли мы просто преобразовать исполняемый файл, а затем выполнить его? В любом случае, почему он так зависит от ресурсов (зачем мне нужен мощный процессор для эмуляции других процессоров)?
Если все, что вы хотите сделать, это эмулировать процессор, то это можно сделать и сделать относительно легко. "Преобразование" исполняемого файла на лету называется "диамической перекомпиляцией", и многие эмуляторы уже делают это. Как правило, хотя, кто-то хочет подражать всей платформе. Это включает в себя оборудование, отличное от ЦП, и иногда это оборудование сложно эмулировать (например, Atari 2600 TIA) или плохо документировать (видеооборудование NES PPU или даже текущее оборудование графического процессора) или и то, и другое. Процессоры всегда функционируют в контексте платформы, и обычно программное обеспечение ожидает, что платформа CPU + вместе будет работать определенным образом. Требования для эмуляции платформы и выполнения часто требуемых строгих требований к времени - вот что является сложной и ресурсоемкой частью.
Во-первых, хотя, безусловно, есть инструкции, которые очень похожи, это не тот случай, когда есть некоторый набор инструкций, которые всегда ведут себя одинаково на разных архитектурах ЦП. Для точной эмуляции (обычно) недостаточно перевести каждую инструкцию - вы должны обрабатывать обращения к памяти, синхронизацию, прерывания ... и это только для процессора.
Кажется, что вы думаете о статической перекомпиляции, но это очень сложно сделать (на самом деле, я думаю, что это сводится к проблеме остановки, что делает ее фактически невозможной в теории). На практике мы иногда можем сделать это для подмножества программ, но вы не можете написать компилятор общего назначения, который принимает объектный код для одной архитектуры в качестве входных данных и выводит совершенно эквивалентный код для другой. Например, было бы трудно обрабатывать самоизменяющийся код с помощью этого метода.
Динамическая перекомпиляция (которая генерирует код на лету во время выполнения программы) более успешна (все еще нетривиально делать правильно). Однако конкретные проблемы будут зависеть от архитектуры. Во многих случаях эмуляция процессора не является проблемой, но эмуляция различных периферийных устройств, поддерживая точную синхронизацию, (см., Например , статью Бюу об эмуляции SNES).
Иногда вы можете игнорировать многие из этих ограничений и по-прежнему достаточно хорошо эмулировать аппаратное обеспечение, чтобы заставить подмножество программного обеспечения работать, но никогда (насколько я знаю) никогда не будет возможно 100% точности с нулевыми накладными расходами, если у вас нет реального аппаратного обеспечения.