Курсовой проект по архитектуре ВМ на 2 курсе, язык C++20
-
Реализовать интерпретатор как консольное приложение.
-
Объектно-ориентированный подход.
- Процессор – отдельный класс, разделение на интерфейс и реализацию.
Выполнение команд – вызов функтора (не использовать оператор-переключатель!).
Память – динамический массив, поле-указатель в классе. - Команды процессора – иерархия классов-функторов.
Базовый класс – абстрактный класс Command с перегруженной операцией operator()
- Процессор – отдельный класс, разделение на интерфейс и реализацию.
-
Разработать и описать в пояснительной записке:
- коды команд
- методы адресации операндов
- множество флагов-результатов
- форматы команд переходов (если не определены)
Обязательно должны быть реализованы команды:
- Пересылки (по необходимости)
- Арифметика (целые и дробные)
- Сравнения (целые и дробные)
- Ввод-вывод (целые и дробные)
- Переходы:
- безусловный
- условный
- к подпрограмме
- возврат из подпрограммы
-
Загрузчик программы для виртуальной машины – независимая функция, вызываемая главной программой интерпретатора. 3.1 Код программы для виртуальной машины должен быть записан в текстовом файле. 3.2 Формат представления кода программы в файле должен быть разработан и описан в пояснительной записке. 3.3 Загрузчик должен быть способен загружать код программы по любому адресу памяти 3.3 Главная программа должна получать имя файла как параметр командной строки, и передавать загрузчику как параметр при вызове.
PSW = IP + Flags, 16+16 = 32 бит.
Память – байтовая, объединяются в 2 и 4 байта. Размер адреса – 16 бит. Данные:
- Короткие целые знаковые, беззнаковые – 2 байта
- Длинные целые знаковые, беззнаковые – 4 байта
- Дробные – 4 байта
РОН – 8 штук, 16 бит; содержимое – короткое целое со знаком, короткое целое без знака (адрес).
Они же – 4 регистра для длинных целых по 32 бита, номера – четные.
Они же – 4 регистра с плавающей точкой по 32 бита, номера – четные.
Структура команд: 2 байта, 4 байта; результат по первому
- 16 бит: l - 1 бит, КОП – 6 бит, s – 1 бит, r1 – 4 бита, r2 – 4 бита
- 32 бита: l - 1 бит, КОП – 6 бит, s – 1 бит, r1 – 4 бита, r2 – 4 бита, offset – 16 бит
- l - длина команды
- l = 0 - 2 байта
- l = 1 - 4 байта
- s – размер целого операнда
- s = 0 – 2 байта
- s = 1 – 4 байта
Адрес = регистр + смещение (если регистр используется).
Адрес = смещение (если регистр не используется).
Смещение = адрес = константа. Особые случаи: s=1, номер регистра – нечетный.
Это формат пересылок, арифметики целой, арифметики дробной; Пересылка:
- Регистр-регистр
- Регистр-память
- Память-регистр
- арифметика дробная, арифметика целая – то же самое
Переходы:
- безусловный (использование битов s), r1 – не используется
- s = 0: прямой, IP = адрес
- s = 1: относительный, IP = IP + адрес.
- условный — то же самое, только проверяются флаги
- вызов подпрограммы: адрес возврата запоминается в регистре – первый операнд
- возврат – безусловный прямой переход
- Если регистр в команде не используется, то на месте номера регистра стоит 1xxx;
- Можно использовать для дополнительных кодов операций!
PSW - Program State Word
- IP - 16 байт
- Флаги:
0. CF - carry flag (флаг переноса)
- ZF - zero flag
- SF - sign flag
- OF - overflow flag
- reserved
- OF имеет значение для знаковых чисел. Равен старшему биту числа (например, для 16-битных чисел проверяется 16 бит, для 64-битных - 64 бит)
- CF имеет значение для беззнаковых чисел. Выставляется при переносе стершего бита в следующий за ним (например, для 16-битных - 17 бит, для 64-битных - 65 бит)
Числа
- short int, short uint - 2 байта
- long int, long uint - 4 байта
- float - 4 байта
РОН - Регистры Общего Назначения
- 8 штук, по 16 бит каждый
- R0 short
- R1 short
- R2 short
- R3 short
- R4 short
- R5 short
- R6 short
- R7 short
или - R0 long, float
- R2 long, float
- R4 long, float
- R6 long, float
Результат команды по первому регистру.
Арифметика выполняется только на регистрах.
Команды процессора двух типов: короткая (16 бит) и длинная (32 бит).
- 16 бит: l - 1 бит, КОП – 6 бит, s – 1 бит, r1 – 4 бита, r2 – 4 бита
- 32 бита: l - 1 бит, КОП – 6 бит, s – 1 бит, r1 – 4 бита, r2 – 4 бита, offset – 16 бит
- l - размер команды
- l = 0 - 2 байта
- l = 1 - 4 байта
- s – размер целого операнда
- s = 0 – 2 байта
- s = 1 – 4 байта
- если регистр не используется, на его месте стоит "15"
- add - целочисленное сложение
- adc - целочисленное сложение с учетом CF
- inc - инкремент числа
- radd - вещественное сложение
- sub - целочисленное вычитание
- sbb - целочисленное вычитание с учетом CF
- dec - декремент числа
- rsub - вещественное вычитание
- mul - беззнаковое умножение
- imul - знаковое умножение
- rmul - вещественное умножение
- div - беззнаковое деление
- idiv - знаковое деление
- rdiv - вещественное деление
- mov - пересылка регистр-регистр
- load - пересылка память-регистр
- store - пересылка регистр-память
- fill - заполнение регистра числом из offset'а команды
- in - ввод с клавиатуры беззнакового числа
- iin - ввод с клавиатуры знакового числа
- rin - ввод с клавиатуры вещественного числа
- out - вывод в консоль беззнакового числа
- iout - вывод в консоль знакового числа
- rout - вывод в консоль вещественного числа
- cmp - целочисленное сравнение
- rcmp - вещественное сравнение
-
безусловные:
- jmp - безусловный прямой
- call - вызов процедуры
- ret - возврат из процедуры
-
условные:
- je - jump equal
- jne - jump not equal
-
знаковые:
- jg - jump greater
- jge - jump greater \ equal
- jl - jump lower
- jle - jump lower \ equal
- jo - jump overflow
-
беззнаковые:
- ja - jump above
- jae - jump above \ equal
- jb - jump below
- jbe - jump below \ equal
- jc - jump carry
Размер адреса - 16 бит => размер оперативной памяти = 65536 байт = 64 кБ.
Память представлена динамическим массивом типа byte (unsigned char или uint8_t).
Адресация памяти - байтовая, байты объединяются в слова (word) по 2 байта и в двойные слова (dword) по 4 байта.
Биты команд в памяти располагаются в обратном порядке
Формат файла - текстовый
Длина строки не более 256 символов (включая пробельные символы)
В одной строке записывается одна команда в формате: p opcode s r1 r2 [offset], где:
p - префикс,
opcode - код операции (десятичное число),
s - размер операнда (0 или 1),
r1 - номер первого регистра,
r2 - номер второго регистра (15, если не используется),
offset - смещение (не пишется в случае короткой команды)
Префиксы строки:
-
e - execute
-
; (точка с запятой) - комментарий, до конца строки
-
числа:
- a - address
- s - short (2 байта)
- l - long (4 байта)
- r - real
-
команды:
- t - tiny (2 байта)
- b - big (4 байта)