Создание машины MIPS на Java / C / C ++ - PullRequest
4 голосов
/ 28 марта 2011

Привет всем, я учусь на ассемблере и в компьютерной организации. Недавно я получил задание, которое требует, чтобы я создал программу, которая emulates a MIPS machine in Java, C, or C++.

Программа читает hex из файла ASM и сохраняет строки в массиве. Затем предполагается эмулировать машину MIPS.

Я искал все вокруг, но понятия не имею, с чего начать. У кого-нибудь есть идеи или даже псевдокод, чтобы направить меня на правильный путь?

Пример файла для чтения:

24080019
2409001e
240a0023
01094020
010a4020
00082021

Если кто-то может просто заставить меня начать правильный путь, который был бы фантастическим, спасибо!

Ответы [ 6 ]

3 голосов
/ 28 марта 2011

Первое, что вам нужно сделать, это научиться расшифровывать эти инструкции.

Похоже, это 8 шестнадцатеричных цифр. Это хорошо, потому что инструкции MIPS имеют длину 32 бита. (шестнадцатеричная цифра, конечно, 4 бита.)

Таким образом, каждая строка в файле соответствует одной инструкции.

Смотрите формат инструкций здесь: http://www.d.umn.edu/~gshute/spimsal/talref.html

Вам необходимо отслеживать несколько регистров внутри машины. (Вы знаете, что такое регистры MIPS, верно?)

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

1 голос
/ 28 марта 2011

Вам нужно подумать о двух вопросах: отображении внутреннего состояния эмулировать машину с переменными в вашем эмуляторе и выполнять код. Первый обычно обрабатывается массивом для регистров, вероятно, в структура с различной другой информацией: счетчик программ, битовая карта с кодами условий (предположим, что процессор имеет эти --- я не знаю архитектура MIPS) и т. д. Вторым будет либо коммутатор, либо таблица указателей на функции или функциональные объекты. Если архитектура использует различные форматы машинных инструкций, это может быть многоуровневый стол. Затем эмулятор читает «инструкцию» на указатель текущей инструкции, затем «выполняет» его, включив его или используя его для индексации в таблице. Снова и снова, в бесконечной петле.

1 голос
/ 28 марта 2011

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

Первый и самый простой - зарегистрировать блок.Я сделал это как простую структуру.Для флаговых регистров я создал несколько функций set / clear для удобства.

Второе и, вероятно, требующее наибольшего усилия - декодирование команд.У меня был справочник по целевому набору команд ЦП, который объяснял значение различных битов в двоичном коде.Обычно существует несколько основных классов инструкций: арифметические / логические операции, инструкции потока управления, копирование / обмен памяти / регистра и, возможно, пара других.Другой аспект заключается в том, как операнды рассматриваются в инструкции.Обычно существует 2 операнда, и адресация каждого из них кодируется в двоичной команде.Поэтому для их интерпретации вам понадобятся две вещи:

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

Третий - память.Это зависит от целевой архитектуры.В моем случае не было сегментов / селекторов, и максимальный объем памяти был небольшим, поэтому я просто выделил соответствующий блок.Для доступа к конкретным ячейкам памяти я добавил функции set / get.Некоторые области памяти должны были быть заняты ПЗУ, поэтому этот тонкий слой был полезен для его реализации.

Далее - ввод-вывод и прерывания.И здесь все может быть очень сложно, в зависимости от требований и платформы.Простейший вывод терминала можно получить, выделив блок памяти для какого-либо экранного буфера.Когда ваша функция mem-setter видит запись в этот блок, она обновляет эмуляцию консоли (вам нужен графический интерфейс в вашем приложении, верно?).Простейший консольный ввод также будет напоминать архитектуру 8086 - когда пользователь нажимает клавишу, вы эмулируете прерывание, передаете код ключа в него и т. Д. Если вам нужно что-то более сложное, например реальная поддержка BIOS с загружаемыми обработчиками прерываний и / или эмуляциянекоторые контроллеры ввода / вывода могут занять столько же времени, сколько вы потратили на предыдущие части машины.Так что не откладывайте это на последнюю неделю.

1 голос
/ 28 марта 2011

Таким образом, в основном ваша программа будет циклом, который читает одну инструкцию (одну строку во входном файле) * и изменяет свои переменные таким же образом, как инструкция изменяет свои регистры.

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

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

Тогда работа с кодами операций - это в основном вопрос изменения ваших регистров и вашей памяти. Возможно, вы сможете воспользоваться вашим языком для выполнения некоторых операций (например, sum, product, ...), но вам, безусловно, придется обрабатывать немного больше, чем это: например, установите флаги в вашем регистре состояния.

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

*: На самом деле, это должно быть умнее, чем просто читать входной файл построчно: сначала вы должны загрузить свою программу в этот массив «памяти» и обработать счетчик программ, который будет запускаться при первой инструкции и увеличиваться после обработки текущей инструкции. Иногда поток может переместить ПК назад. В идеале вы также хотели бы сделать эту часть «памяти» неизменяемой, но в первую очередь это не то, на чем вы хотите сосредоточиться.

Надеюсь, я не сказал ничего не относящегося к MIPS.

Итак, с точки зрения структуры, этот псевдокод дает представление:

set all your register variables to their default value
allocate memory for the "memory"
load your program in the "memory"
for (initialize PC ; ??? ; PC"++")
{
    read the "memory" at the address in PC -> opcode
    switch (opcode)
    {
        case op1:
            handle_op1(); // modify registers and/or "memory", set status register
        break;
        [...]
    }
}
1 голос
/ 28 марта 2011

SPIM может быть хорошим местом, чтобы начать смотреть на то, как такая программа может быть построена.Это симулятор MIPS32.

0 голосов
/ 28 марта 2011

Это должно помочь вам начать:

http://www.oberle.org/procsimu-index.html

Вы должны настроить его для набора команд MIPS.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...