Представляю вашему внимание эмулятор машинного кода. Интерфейс построен на ncurses. Цель эмулятора - развить мышление. Эмулятор простой. Инструкций всего 16. Далее будет описана история возникновение идеи создания этого эмулятора, а потом объяснение что в нём есть.
Я сейчас читаю книгу "Техника отладка программ без исходных кодов". Там была история о том, как зарождался хакинг. Люди в 60-е и 70-е годи писали машинными командами, я хотел хоть чуть-чуть испытать это ощущение что значит писать машинным языком. Вот и родилось это детище, теперь думаю как его на телефон и планшет перенести, чтобы залипать в свободное время.
Инструкция находится в старшем полубайте, вот все доступные инструкции.
Код:
* 0x00 0000 ADD - Команда сложения
* 0x10 0001 SUB - вычитание
* 0x20 0010 AND - битовое И
* 0x30 0011 OR - битовое ИЛИ
* 0x40 0100 XOR - ксор регистров или числа
* 0x50 0101 SHL - сдвиг влево
* 0x60 0110 SHR - сдвиг вправо
* 0x70 0111 LD - запись в регистр аккумулятор
* 0x80 1000 IN - входящие данные по порту
* 0x90 1001 NOP - нет команды
* 0xa0 1010 OUT - исходящие данные по порту
* 0xb0 1011 PUSH - пуш байта
* 0xc0 1100 POP - поп байта
* 0xd0 1101 TEST - вычитание без записи в регистр A
* 0xe0 1110 JC - условный переход
* 0xf0 1111 HALT - останова программы
В младшем полубайте мы можем разместить отношение [регистр <-> память], Всего имеется три регистра данных, которые доступны для работы и один регистр адреса.
Код:
* A - 0b00
* X - 0b01
* Y - 0b10
* число/адрес - 0b11
Например, если мы хотим записать в регистр X число, то указываем в младшем полубайте так 01 11, То-есть 0x07. Но не всё можно указать таким образом, например инструкция LD (load) может загрузить в память из числа, или в регистр из памяти.
То-есть получается вот такие варианты.
Код:
LD [0x8], 0x10
LD A, [0x8]
Адресация к данным остается только 8-битной, так что если хотите писать большое приложение, то лучше делать прыжок на 256 смещение в файле и первые 254 байта оставить под данные. Максимальный размер программы 0xffff, но надо учитывать что тут также работает стек, да и врядли кто-то осмелиться написать столь большую программу.
Также стоит учитывать, что например, если мы попытаемся загрузить из адреса в адрес вот таким опкодом, 0x7f, то он загрузить всё же число в память. Полезная документация, это исходный код программы. Также я подготовил видео, чтобы показать что сейчас реализовано.
Ссылка скрыта от гостей
Здесь даже есть отладчик и возможность в игре нажимать на клавиши и стрелки, стрелки, это клавиши перемещения как в vim 'hjkl'. Клавиши кнопок всего тоже четыре, 'wesd'. Во время отладки, отладчик показывает сколько байт занимает текущая инструкция.
Регистр стека недоступен для работы и на его работу наверное можно повлиять только если стек вывернуть с помощью POP на начальные адреса, тогда появиться доступ к стеку как к локальным переменным.
В репозитории есть тестовый файл, называется buffer, он выводит hello, его можно изучить, программа занимает всего 32 байта.
Код:
У JMP:
0000 JC
0001 JS
0010 JZ
0011 JMP
Код:
флаги:
Z - флаг нуля, то-есть если делается тест, вычитается значение, если результат равно нулю, то устанавливается этот флаг
S - флаг отрицательного числа, если в результате стало равно меньше нуля, или то-есть установлен 0x80 бит.
C - флаг переполнения
Код:
Адреса:
0x00 in, out - таймер, можно задать время обновления в миллисекундах
0x01 in, out - экран, 80x25. Значение заноситься из регистров. В регистре A находится символ, в регистре X координата по x, в регистре Y координата по y. Например [IN 0x01]; [1000 0000 0000 0001]; 0x80 0x01
0x02 out - чтение в регистр A значения стрелок. Четыре стороны, 0b1000 - это только влево. 0b1100 - это влево и вверх. Как в vim [jkl;]
0x03 out - чтение в регистр A нажатой клавиши, например будут две клавиши игры, одна клавиша RESET, другая клавиша ПАУЗА
ссылка на github
Буду рад общение насчет данной программы. Интересно посмотреть кто что сможет создать на нём.