У меня на 2 курсе студенты пишут курсовые работы - реализация виртуальной машины.
Требования к реализации:
0. Реализовать интерпретатор как консольное приложение.
1. Объектно-ориентированный подход.
1.1 Процессор – отдельный класс, разделение на интерфейс и реализацию;
Выполнение команд – вызов функтора (не использовать оператор-переключатель!)
Память – динамический массив, поле-указатель в классе.
1.2 Команды процессора – иерархия классов-функторов; базовый класс – абстрактный класс Command с перегруженной операцией operator()

2. Разработать и описать в пояснительной записке:
– коды команд
– методы адресации операндов
– множество флагов-результатов
– форматы команд переходов (если не определены)
Обязательно должны быть реализованы команды:
2.1 Пересылки (по необходимости)
2.2 Арифметика (целые и дробные)
2.3 Сравнения (целые и дробные)
2.3 Ввод-вывод (целые и дробные)
2.4 Переходы
– безусловный
– условный
– к подпрограмме
– возврат из подпрограммы

3. Загрузчик программы для виртуальной машины  – независимая функция, вызываемая главной программой интерпретатора..
3.1 Код программы для виртуальной машины должен быть записан в текстовом файле.
3.2 Формат представления кода программы в файле должен быть разработан и описан в пояснительной записке.
3.3 Загрузчик должен быть способен загружать код программы по любому адресу памяти
3.3 Главная программа должна получать имя файла как параметр командной строки, и передавать загрузчику как параметр при вызове.

Примеры заданий:
4. Двухадресная, с Регистрами Общего Назначения, универсальная адресация операндов
PSW = IP + Flags, 16+16 = 32 бит. ¬
Память – слова 16 бит, объединяются в двойные слова. Размер адреса – 16 бит.
Данные:
Целые знаковые, беззнаковые – 2 байта
Целые знаковые – 4 байта
Дробные – 4 байта
РОН – 8 штук, 16 бит; содержимое – целое со знаком, целое без знака (адрес)
Они же – 4 регистра, 32 бит, номера – четные; содержимое – целое со знаком
Они же	– 4 регистра с плавающей точкой по 32 бита, номера – четные.

Структура команд: 2 байта, 4 байта, 6 байт; результат по второму адресу
КОП – 7 бит, s – 1 бит, dd – 2 бита, r1 – 3 бита, r2 – 3 бита, о1 – 16 бит, o2 – 16 бит
s – размер операнда (для целых)
s = 0 – 2 байта
s = 1 – 4 байта
dd – формат операнда (первый и второй)
dd = 00 – операнды в регистрах; o1, o2 – отсутствуют;
dd = 01 – регистр – адрес
dd = 10 – адрес – регистр
dd = 11 – адрес– адрес
Адрес = регистр + смещение (если регистр используется)
Адрес = смещение (если регистр не используется)
Особые случаи: s=1, d = 0 (аргумент в регистре)  и номер регистра – нечетный
Это формат пересылок, арифметики целой, арифметики дробной;
Пересылка:
Регистр-регистр, Регистр-память, Память-регистр, Память-память
арифметика дробная, арифметика целая – то же самое
Переходы:
Безусловный (использование битов s, dd – отличается от стандартного), r1 – не используется
– s = 0: прямой, IP = адрес
– s = 1: относительный, IP = IP + адрес
dd = 10: адрес = r2
dd = 11: адрес = r2+o2
dd = 01: адрес = o2
dd = 00 – запрещено (резерв!)
Условный — то же самое, только проверяются флаги
Вызов подпрограммы — адрес возврата запоминается в первом операнде
Возврат – безусловный прямой переход (по любому варианту)
Если регистр в команде не используется, то можно использовать для дополнительных кодов операций

6. Трехадресная, с регистрами общего назначения, все операнды в регистрах
PSW = IP + Flags, 16 + 16 = 32 бит
Память: слова по 2 байта, размер адреса – 16 бит
Типы данных:
Целые знаковые, беззнаковые – 4 байта
Дробные – 4 байта
РОН – 	8 штук, 32 бит – целые
Они же 8 штук, 32 бита – дробные

Структура команды: 2 байта, 4 байта; результат в первом операнде
16 бит:		КОП – 7 бит, r1 ¬– 3 бита, r2 ¬– 3 бита, r3 ¬– 3 бита
32 бита:		КОП – 7 бит, r1 – 3 бита, r2 ¬– 3 бита, r3 ¬– 3 бита, адрес (константа) – 16 бит
Пересылка:
Память-регистр, регистр-память, регистр–регистр;
r2 = xxx – биты пересылки
000 – регистр-регистр
001 – регистр-память, адрес (константа) в команде
011 – регистр-память, адрес = r3+константа (в команде)
101 – память-регистр, адрес (константа) в команде
111 – память-регистр, адрес = r3+константа (в команде)
010 – загрузка адреса в регистр, адрес (константа) в команде
110 – загрузка адреса в регистр, адрес = r3+константа (в команде)
100 – резерв
Арифметика целая – только на регистрах
Арифметика дробная – только на регистрах
r1 = r2 $ r3
Переходы
Безусловный прямой, r1 – не используется
r2 = xxx – тип перехода
001: прямой, IP = адрес (константа) в команде
011: прямой, IP = r3+адрес (константа) в команде
Безусловный относительный: команда формата-16: смещение = <r1r2r3>; IP = IP+смещение
Условный — то же самое, только проверяются флаги
Вызов подпрограммы — адрес возврата запоминается в r1
Возврат – безусловный прямой переход

13. Виртуальная машина RISC – Н. Вирт
Вирт Н. Построение компиляторов. – М.: ДМК Пресс, 2010. – 192 с.
Глава 9. RISC-архитектура как цель. – с. 75.

14. Виртуальная машина MMIX – Д.Кнут
Кнут Д. Искусство программирования, том 1, выпуск 1. MMIX – RISC- компьютер нового тысячелетия. – М.: ООО «И.Д. Вильямс», 2007. – 160 с.

15. Виртуальная машина – Ч. Уэзерелл
Уэзерелл Ч. Этюды для программистов. – М.: Мир, 1982. – 282 с.
Глава 25. Уча – учимся, или Моделирование большого компьютера. – с. 159.