Приложение ТОЛЬКО для iPad, проверено на iPad2 и iPad3. Работает в горизонтальном положении, для чего блокирует ориентацию экрана.
Ссылка на Dropbox: https://www.dropbox.com/s/0bd99csb02hax ... 7.cod?dl=0
Процессор очень простой, четырёхразрядный. То есть адреса полубайтовые, всё адресное пространство — 16 ячеек. Элемент данных тоже полбайта, одна шестнадцатиричная цифра. Команд тоже 16, естественно. Все они показаны в табличке, которая постоянно видна в левой части экрана.
Есть два регистра общего назначения, R0 и R1. Есть указатель команд IP — без него никак, но кто не знает, как работает любой процессор, может на него внимания не обращать.
Подробнее о системе команд. Команды с кодами 0-7 имеют одинарную длину. Каждая занимает одну ячейку памяти, дополнительных аргументов не требует. Команды с кодами 8-F имеют двойную длину, и в следующей ячейке для них должен содержаться аргумент.
Сами команды.
0 — немедленный останов процессора. Обязательно должна присутствовать в программе, иначе та никогда не завершится.
1 и 2 — сложение и вычитание. Заменяют содержимое регистра R0 суммой R0+R1 и разностью R0-R1 соответственно.
3 и 4 — увеличивают на единицу регистры R0 и R1 соответственно.
5 и 6 — уменьшают на единицу эти же регистры.
7 — выдаёт звуковой сигнал. (Самая бесполезная команда. Было сильное желание заменить её чем-нибудь полезным, но отказался ради совместимости.)
8х — выдаёт на печать число х, хранящееся в следующей ячейке памяти. То есть, если нужно печатать какую-то переменную, её придётся помещать непосредственно следом за командой печати и там с ней работать.
9х и Ах — помещают в регистры R0 и R1 соответственно содержимое ячейки памяти по адресу (х).
Вх и Сх — наоборот, помещают содержимое регистров R0 и R1 соответственно в ячейку памяти по адресу (х).
Dx — безусловный переход по адресу х.
Ex — условный переход по адресу х, если содержимое R0 равно нулю.
Fx — условный переход по адресу х, если содержимое R0 не равно нулю.
Как ввести программу?
На панели „Memory“ представлена вся память с адресами от 0 до F. Рядом с каждым адресом есть кнопка. Нажимая её, вы заносите этот адрес в указатель команд IP, делая соответствующую адресу ячейку памяти активной. Эта активизация отображается как в поле регистра, так и индикатором-квадратиком на кнопке. Теперь можно нажать на основной клавиатуре (панель „Keyboard“) кнопку с нужным значением, и это значение будет занесено в активную ячейку. Последовательно пробегаем по ячейкам, заполняем их нужными значениями, и программа в памяти. Разумеется, сначала её нужно ещё составить на бумажке и перевести в коды. (:
Можно вводить код в память и более традиционным способом — заносить содержимое в ячейки с экранной или физической клавиатуры. Если первый символ ввода является цифрой 0-9 или буквой a-f/A-F, то это в память и заносится. Иначе заносится ноль.
Как выполнить программу?
Занести её в память и нажать кнопку „RUN program“. Кнопка на время выполнения превратится в „STOP program“ — на тот случай, если программу захочется остановить принудительно или она у вас зациклится. При выполнении все остальные управляющие элементы скрываются с экрана; содержимое памяти, регистров и „бумаги“ в принтере оперативно меняется. Внимание: перед началом выполнения все регистры обнуляются!
Как отладить программу?
На панели „Debug“ предусмотрены два переключателя. Первый, „Trace“, устанавливает режим трассировки. При выполнении на печать дополнительно выдаётся информация вида x:y; или x:yz; Каждый такой фрагмент печати означает, что в данный момент выполняется команда с кодом «y» или «yz», находящаяся по адресу «х». По завершении вся печать копируется в буфер обмена, откуда её можно „вставить“ в любом текстовом редакторе и там проанализировать. Второй переключатель, „Slow+Show“, устанавливает медленный режим выполнения, при котором на каждую команду делается примерно секундная задержка, а сами исполняемые команды в мнемонике показываются тут же на отладочной панели.
Как сохранить программу?
Нажмите кнопку „Clipboard“, и содержимое памяти скопируется в буфер обмена строкой из шестнадцати цифр, разделённых для наглядности на четыре группы по четыре цифры. (См. ниже, как это выглядит)
Кроме того, предусмотрена „внешняя память“, в которую можно сбросить копию основной памяти кнопкой „Save“. (Рекомендуется делать это перед первым запуском программы, так как память в ходе исполнения может модифицироваться.) Обратная загрузка в основную память — кнопкой „Load“, при этом всё что было там ранее, пропадает. Загружается и выгружается всегда ВСЯ память.
Перезапуск эмулятора стирает внешнюю память. После запуска там всегда содержится демонстрационная программка (см. ниже)
Сброс и выключение.
Последняя панель, подписанная „Attention!“ позволяет делать полный сброс эмулируемого компьютера (все регистры и вся память в ноль) и выключать его (то есть, просто завершать выполнение эмулятора). Кнопки „RESET device“ и „Power OFF“ соответственно. На пультах управления компьютерами первых поколений такие кнопки обычно закрывались защитными колпачками — а здесь они не будут срабатывать до тех пор, пока вы не переведёте „предохранитель“ в зелёное положение. Внешняя память при сбросе сохраняется.
Вообще, интерфейс намеренно сделан архаичным, с ностальгическими воспоминаниями о панели управления незабвенной IBM 360/370. (: Я всегда рассказываю школьникам, как работали программисты полвека назад, показываю перфокарты и перфоленты… Нынешних подростков впечатляет.
В общем, такая вот учебная программка, которую я надеюсь довести до самостоятельного приложения в AppStore. Примитивность эмулируемого процессора позволяет делать только самые простые вещи, но и на этих простых вещах можно кое-чему научиться.
Примеры программ
803B 1F00 0000 0000
Последовательно выдаёт на печать все цифры шестнадцатиричной системы от 0 до F. Это самая известная программа для 4917, и она включена в эмулятор как демо-пример. После запуска эмулятора она находится во „внешней памяти“ и может быть загружена в основную память кнопкой „Load“.
Code: Select all
0: 80 PRINT 0
2: 3 INC R0
3: B1 MOV (1),R0
5: F0 JMPNZ 0
7: 0 HALT
Для числа, хранящегося по адресу (F) — в примере это девятка, — находит остаток от его деления на два, и заносит этот остаток на место самого числа. Иными словами, определяет, является ли число нечётным. Результат „1“ означает „да“, результат „0“ — „нет“. Точно как в Smart Basic.
Code: Select all
0: 9F MOV R0,(F)
2: EC JMPZ C
4: 5 DEC R0
5: 4 INC R1
6: EC JMPZ C
8: 6 DEC R1
9: 5 DEC R0
A: D2 JMP 2
C: CF MOV (F),R1
E: 0 HALT
F: 9 ; variable
Выводит на печать десять первых чисел Фибоначчи (1,1,2,3,5,8 и т.д., каждое следующее равно сумме двух предыдущих). По модулю 16, естественно. Одиннадцатое число Фибоначчи кратно 16, и этот факт используется для останова программы.
Code: Select all
0: 3 INC R0
1: 4 INC R1
2: 81 PRINT 1
4: B3 MOV (3),R0
6: 1 ADD
7: A3 MOV R1,(3)
9: F2 JMPNZ 2
B: 0 HALT