Эмуляция и компиляция весьма различны, но имеют тенденцию смешиваться из-за того, что оба считаются "низкоуровневыми".
Эмуляция простой архитектуры, такой как 6502 или Z80, будет довольно простой для работы с ЦП, но будет существенный кусок кода для записи, так как вам нужно иметь функцию для каждой инструкции. Вы захотите автоматизировать это каким-то образом, начиная со спецификации набора команд со всеми временными интервалами и тому подобным, так как ввод всего этого будет очень утомительным :) Старые спецификации набора инструкций процессора легко найти, так что это очень помогает при сборке эмуляторов.
Кроме того, вам необходимо реализовать некоторый уровень аппаратной эмуляции , который обычно включает обработку и генерацию прерываний (таких как прерывание по вертикали и пробел на устройстве отображения, если эмулятор предназначен для игровая приставка, скажем). Для этого снова потребуется некоторый уровень спецификации и генерации кода, но вам, вероятно, придется писать большую часть этого вручную, поскольку он не будет таким повторяющимся (и, следовательно, автоматизируемым), как код набора команд.
Компиляция будет включать в себя какую-то языковую спецификацию любого языка, для которого вы собираетесь реализовывать компилятор, и цель, для которой вы будете стремиться выводить код. Вывод может быть прямым в двоичный, может быть сборкой или даже другим языком (на самом деле это просто переводчик, но он считается компиляцией, когда цель считается «достаточно» низкоуровневой). Поскольку вы будете работать на каком-либо оборудовании или платформе VM, вам вряд ли придется беспокоиться об обработке прерываний и подобных вещах.
Камни преткновения для обоих сложность и правильность - для эмулятора вам нужно будет заставить его работать очень точно, если вы не выбираете очень простые вещи подражать. Вам также нужно будет создать своего рода интегрированный отладчик для эмулятора, в противном случае почти невозможно определить, что происходит, когда это происходит неизменно. Для компилятора должно быть довольно просто перевести игрушечный язык или небольшое подмножество более сложного языка и создать его по ходу работы.
Помните, что с обоими этими элементами вы должны иметь возможность создавать входные данные для их тестирования, и если вы не можете создать простые входные данные, то вам будет очень трудно получить отладку с самого начала. Это само по себе облегчает работу компилятора, imho (Это и то, что вы захотите иметь что-то, что эмулирует полную консоль или что-то сразу:)