Я не считаю это огромным и сложным, чем ближе к оборудованию, тем проще.
Напишите дизассемблер, вот как это делает аппаратное обеспечение. Большинство процессоров содержат коды операций или набор команд в том же руководстве, что и язык ассемблера.
Посмотрите на код операции, скажем, инструкцию добавления, используя регистры, несколько битов определяют регистр источника, несколько битов для регистра назначения, несколько бит говорят, что это инструкция добавления. Допустим, этот набор инструкций, который вы просматриваете, использует только два регистра для добавления на основе регистров. Существует некоторая логика, сумматор, который может добавлять два элемента размером регистров и выводить результат и бит переноса. Регистры хранятся на чипе в битах памяти, которые иногда называют триггерами. Поэтому, когда добавление декодируется, входные регистры привязываются к логике добавления с помощью электронных переключателей. В эти дни это происходит в начале тактового цикла, к концу тактового цикла результат суммируется, и выходной сигнал направляется в биты для регистра назначения, и ответ захватывается. Обычно добавление изменяет флаги в регистре флагов. Когда результат слишком велик, чтобы его можно было сохранить в регистре (подумайте о том, что произойдет, если вы добавите десятичные числа 9 и 1, и вы получите 0, а справа - 1)? Существует некоторая логика, которая просматривает выходные данные сумматора и сравнивает биты со значением ноль, которое устанавливает или очищает флаг z в регистре флагов. Другой бит флага - это бит знака или n бит для отрицательного значения, то есть наиболее значимый бит ответа. Все это делается параллельно.
Тогда скажите, что вашей следующей инструкцией является переход, если ноль (переход, если равен), логика смотрит на флаг z. Если установлено, то следующая выбранная инструкция основана на битах в инструкции, которые добавляются к счетчику программ через тот же или другой сумматор. Или, возможно, биты в инструкции указывают на адрес в памяти, который содержит новое значение для счетчика программы. Или, может быть, условие ложно, тогда счетчик программ все еще запускается через сумматор, но к нему добавляется размер инструкции, чтобы она получала следующую инструкцию.
Протяженность от дизассемблера до симулятора не длинная. Вы создаете переменные для каждого из регистров, декодируете инструкции, выполняете инструкции, продолжаете. Память - это массив, из которого вы читаете или записываете. Дизассемблер ваш шаг декодирования. Симулятор выполняет те же шаги, что и аппаратные средства, аппаратные средства выполняют это параллельно, используя разные приемы программирования и разные языки программирования.
В зависимости от того, как реализован ваш дизассемблер, который может начинаться в начале программы и дизассемблировать до конца, ваш симулятор запускается с начала, но следует за выполнением кода, которое не обязательно начинает заканчиваться.
В старых симуляторах игровых приставок, таких как MAME, есть симуляторы процессора, на которые вы можете посмотреть. К сожалению, особенно в MAME, код разработан с учетом скорости выполнения, а не читабельности, и большинство из них полностью нечитаемы. Хотя, если посмотреть, есть несколько читаемых симуляторов.
Друг указал мне на эту книгу http://www1.idc.ac.il/tecs/, которую я хотел бы прочитать, но пока не читал. Возможно, это просто книга, которую вы ищете.
Конечно, аппаратное обеспечение развилось из простых конечных автоматов, которым требуется много часов для выборки, декодирования и выполнения последовательно. Я думаю, что если вы только что поняли классическую выборку, декодирование и выполнение, этого достаточно для этого вопроса. Тогда у вас могут возникнуть другие более конкретные вопросы, или, возможно, я неправильно понял вопрос, и вы действительно хотели понять шину памяти, а не декодер.