Эмулятор МК-61

## PocketMK – эмулятор калькулятора МК-61

T: |
Z: |
Y: |
X: |

rad grad deg

Ввод программы

PocketMK – эмулятор семейства популярнейших советских программируемых калькуляторов БЗ-34...МК-61. Основное отличие эмулятора состоит в использовании незадействованных адресов команд, позволивших добавить еще один регистр `F`, команды для специальных функций (`x!, sinh, cosh, tanh, asinh, acosh, atanh, erf, J0, J1, Y0, Y1`), команды добавления к регистру (`M+`) и команды вывода графики в растровое изображение размером 400×300 точек. Имеется два основных режима работы: режим калькулятора, режим редактирования программы (включается галочкой в панели "Программа").

PocketMK использует обратную польскую форму записи. Например, для вычисления выражения 2+3*(6+7) надо выполнить следующие действия: `2 B↑ 3 B↑ 6 B↑ 7 + * +` или более просто `6 B↑ 7 + 3 * 2 +`. Использование функций аналогично. Например, вычислим синус от угла 37 градусов 30 минут. Сначала превратим минуты в десятичную дробь: 37.5. Переключив PocketMK в режим deg (переключатель находится в верхнем левом углу в режиме калькулятора), вводим это число последовательным нажатием клавиш `3 7 . 5` и берем от него синус, нажав клавиши `F sin`. На индикаторе читаем значение синуса: 0.6087614290087207. Если нужно ввести большое число, можно воспользоваться командой ввода порядка `EE`. При этом для отрицательных порядков за ней следует ввести команду `±`. Например, `1 . 7 8 EE 5 3` дает 1.78e53, `2 . 5 6 EE ± 7` дает 2.56e-7, `3 ± EE 6` дает -3e6

### Внешний вид

PocketMK имеет два режима работы: режим калькулятора (по умолчанию) и режим ввода программы. В режиме калькулятора PocketMK работает в интерактивном режиме – любая нажатая клавиша сразу же выполняется. Вверху находятся кнопки переключения ввода углов, содержимое стека {X,Y,Z,T} и кнопки управления программой. В средней части располагается клавиатура, вид которой зависит от состояния функциональных клавиш «F» и «K». Внизу находятся кнопки панели инструментов и панель меню.

Кнопки переключения ввода углов имеют следующее значение: deg – углы считаются в градусах (период sin(x) равен 360), grad – углы считаются в градах (период sin(x) равен 400), rad – углы считаются в радианах (период sin(x) равен 2π).

Окно отображения стека расположено сверху посередине. «Главный» регистр X выделен цветом, поскольку именно с ним выполняются все основные операции – сложение, вычитание, умножение и деление, вычисление функций, запись и считывание регистров, операции условного перехода. Остальные регистры стека являются скорее «дополнительными» и выводятся серым цветом.

Кнопки управления выполнением программы позволяют выполнить программу пошагово (Step) и запустить программу на автоматическое выполнение с текущей программной позиции (Run). Для остановки программы (например, в случае зацикливания) служит кнопка Stop, заменяющая кнопку Run при запуске программы.

Клавиатура отображается в режиме калькулятора и в режиме редактирования программы. Ее вид зависит от нажатия функциональных клавиш «F» и «K», располагающихся в левой верхней части клавиатуры. Для удобства пользователя цвета кнопок изменяются вместе с изменением их функциональности. Кроме того, графические команды выделены зеленым цветом, а команды обращения к регистрам фиолетовым. Часть кнопок имеет смысл только при выполнении программы (команды перехода, остановки программы и т.д., выделенные желтым). Действие остальных команд одинаково «полезно» в любом режиме. Отличие состоит в том, что в режиме калькулятора команды выполняются сразу, а в режиме ввода программы они записываются в программную память.

### Регистры, стек и операции

PocketMK хранит числа в специальных переменных – регистрах. Каждый регистр памяти имеет свое обозначение в виде цифры или буквы. Шестнадцать из них обозначаются числами от 0 до 9 и начальными буквами латинского алфавита (A, B, C, D, E, F). По сути эти регистры являются обычными переменными, обращение к которым возможно произвольным образом. Еще четыре регистра образуют стек и обозначаются латинскими буквами (X, Y, Z, T). Прямой доступ возможен только к одному регистру из них – регистру X. Остальные регистры участвуют в вычислениях и доступны только с помощью команд работы со стеком. Последний из регистров (называемый B или X1) хранит информацию о предыдущем значении регистра X и может быть только прочитан с помощью команды `Bx`. Часто в описаниях программ перед регистром ставят букву R (например, RA – регистр А), чтобы отличать регистр от буквы. Регистры X, Y, Z, T отображаются на экране калькулятора. Регистры 0,1,...,F можно посмотреть в панели «Регистры».

При вводе в калькулятор число заносится в регистр X. Прочитать число в регистрах 0,1,...,F можно с помощью кнопки `MR` (от английского «memory read»). Например, команда `MRA` впишет число из регистра A в регистр Х. Аналогично команда `MSA` (от английского «memory save») запишет число из регистра Х в регистр А. Команда `M+A` прибавит число из регистра Х к числу, хранящемуся в регистре А. Команда `M+` отсутствовала в МК-61 и была введена для удобства работы и программирования различных статистических приложений.

Каждая операция калькулятором выполняется либо над одним числом, находящимся в регистре X (операция одноместная: `x2, sin, erf` и т.д.), либо над двумя числами, одно из которых находится в регистре X, а другое - в регистре Y. Отличительной особенностью этого калькулятора является то, что операция, которую следует производить с двумя числами, выполняется после ввода двух чисел – используется так называемая польская или постфиксная запись выражений.

Числа, над которыми нужно совершить ту или иную арифметическую операцию, должны находиться в двух регистрах – X и Y. В регистр Y можно попасть только из регистра X. Делается это нажатием клавиши `B↑`. При этом в регистре X остается копия числа. Затем в регистр X записывается второе число, причем первое число стирается. В случае вычитания уменьшаемое должно находиться в Y, а вычитаемое – в X. При делении в Y должно находиться делимое, в X – делитель. После ввода числа в оба регистра, можно нажать клавишу выбранной операции. Результат ее будет помещен в регистр X. То, что было прежде в регистре Y, не сохранится. Здесь следует обратить внимание на то, что если в регистре X находился результат операции, то ввод нового числа в регистр X автоматически передвигает старое содержимое регистра X в регистр Y. Исключением являются операции очистки регистра `Cx` и операция `B↑`.

Наконец, в таблице приведено состояние стека до и после применения различных операций:

Операция | Стек до | Стек после
--- | --- | ---
Ввод числа r из регистра или числа π | `b x y z t` | `b r x y z`
Ввод числа n после `Сх, B↑` | `b x y z t` | `b n y z t`
Ввод числа n после других операций | `b x y z t` | `b n x y z`
Команда `Cx` | `b x y z t` | `b 0 y z t`
Команда `B↑` | `b x y z t` | `b x x y z`
Команда `Bx` | `b x y z t` | `b b x y z`
Команда `↔` | `b x y z t` | `x y x z t`
Команда `↻` | `b x y z t` | `x y z t x`
Вычисление функции f(x) | `b x y z t` | `x f y z t`
Двуместная операция g | `b x y z t` | `x g z t t`
Команда `B↓` | `b x y z t` | `x y z t t`

### Программирование

Составим теперь простую программу вычисления площади круга. Формула для вычисления площади круга известна: S=πD2/4, где D – диаметр круга. Константа π уже есть в калькуляторе. Величину D необходимо вручную ввести с клавиатуры (оно будет помещено в регистр X). Пусть D = 3. Для ручного расчета нужно нажать клавиши: `x2 F pi * 4 /`. На индикаторе читаем результат: 7.0685834705770345. Те же клавиши и в той же последовательности нужно будет нажать, когда мы станем вводить в калькулятор программу для вычисления площади круга.

Программа располагается в калькуляторе в виде отдельных команд, каждая из которых занимает свою ячейку программной памяти (некоторые управляющие – две ячейки – команда и адрес). Всего таких ячеек 160. Им присвоены номера, называемые адресами – от #00 до #F9. В силу совместимости с МК-61 нумерация сделана так, что первая цифра шестнадцатеричная, а вторая всего лишь десятичная. Например, адрес `#F9 = 0xF*10+9 = 159`. Такая вот смесь ☺ !

Чтобы ввести программу в калькулятор, надо перевести его в состояние, называемое режимом редактирования программы. В режиме редактирования PocketMK нажатие клавиш приводит к вводу команды в программную память вместо ее непосредственного выполнения. Для перехода в режим редактирования программы следует раскрыть панель программа и поставить галочку напротив `Ввод программы`. Стрелки в этой панели перемещают курсор (текущий адрес), кнопки Ins и Del добавляют и удаляют текущую/последнюю ячейку программы. Адрес первой команды в строке указывается перед двоеточием. Текущая позиция курсора выделена голубым. Курсор не показывается если он находится за последней командой (калькулятор готов к добавлению новой команды).

Нажимаем `x2` и в программе появляется `x2`. Ее появление в таблице означает, что команда занесена в программную память. Одновременно прямоугольник сместился вправо – счетчик адресов увеличился на 1. Далее нажимаем `F π` и в программе появляется `π` (модификатор `F` в программе всегда опускается) и т.д. Таким образом вводятся все команды. Для останова работы калькулятора по программе необходимо ввести специальную команду: `stop` (клавиши `F stop`).

Чтобы проверить работу программы вернемся в режим калькулятора (сняв галочку), введем диаметр круга и запустим программу кнопкой Run. На мгновение мигнет индикатор Stop вместо Run и программа выдаст ответ. Кнопка Stop предназначена для останова программы (например, в бесконечном цикле). Для пошагового исполнения программы (в целях отладки или в качестве одного из способов ввода чисел) можно воспользоваться кнопкой Step. Ее действие полностью аналогично Run, но будет исполнена только текущая команда.

Следует отметить, что в отличие от калькулятора MK-61, переход в начало программы осуществляется автоматически, если курсор не виден (ожидается добавление новой команды). Кроме того, программа автоматически останавливается при достижении конца введенных команд (команда `stop` в конце программы не обязательна).

#### Команды перехода

Для безусловного перехода на адрес программы используется клавиша `go` (аналог команды `БП` – безусловный переход). После команды следует указать адрес перехода. Например, для того, чтобы перейти на адрес 60, надо нажать клавиши: `go 6 0`. Эта команда работает только в программном режиме и занимает две ячейки памяти: первая ячейка – код команды перехода, вторая – адрес перехода. Отмечу, что для совместимости с программами МК–61 пришлось ввести «странную» систему адресов. Всего ячеек 160 с адресами – от 00 до F9. При этом адрес состоит их двух цифр: первая цифра шестнадцатеричная, а вторая десятичная. Например, адрес `#F9 = 0xF*10+9 = 159`.

Чтобы вызвать подпрограмму, используется команда `sub` (аналог команды `ПП` – переход на подпрограмму). Так же, как и в команде безусловного перехода, необходимо указать адрес, с которого начинается подпрограмма. Команда возврата из подпрограммы – `ret` (аналог команды `В/О`). Подпрограммы могут вкладываться друг в друга.

Также есть специальные команды, которые изменяют порядок выполнения программы в зависимости от содержимого регистра X. Это команды `x<0, x≥0, x=0, x≠0`. Если условие выполняется, то управление передается на команду, следующую за командой условия (напомним, что команда условия занимает 2 ячейки – команда и адрес), в противном случае – управление передастся на указанный адрес. Например, с адреса 20 мы введем строку: `F x<0 25`, тогда если содержимое регистра X будет меньше нуля, то программа продолжится с адреса 22, а если ноль и больше, то с адреса 25.

Для организации циклов предусмотрены специальные команды `L0, L1, L2, L3`. После ввода этих команд также необходимо указать адрес перехода. Каждая команда ассоциирована с регистрами от 0 до 3, соответственно. После выполнения команды происходит вычитание единицы из этого регистра и сравнение результата с нулем. Если результат равен нулю, то программа продолжит свое выполнение со следующего адреса. Иначе – перейдет на указанный адрес перехода. Напишем программу вычисления факториала. Сначала перейдем в режим программирования с помощью меню или панели управления. Затем вводим программу: `MS0 1 MR0 * L0 02`. После ввода программы переходим в режим калькулятора, вводим число вводится с клавиатуры и нажимаем кнопку Run. В результате в регистре X появляется факториал числа. Можно проверить вычисленное значение нажав `↔ K x!`.

Все команды PocketMK имеют уникальный номер в диапазоне 0...255. Полный список команд с указанием их кодов можно найти в таблице. Здесь номер строки дает старший разряд, номер столбца – младший разряд номера команды. Например, команда `|x|` имеет номер 0x31.

| x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF
x00 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | . | ± | EE | Cx | B↑ | Bx
x10 | + | – | * | / | ↔ | 10x | ex | lg | ln | asin | acos | atan | sin | cos | tan | Y0
x20 | π | sqrt | x2 | 1/x | xy | ↻ | B↓ | sh | ch | th | erf | x! | asinh | acosh | atanh | Y1
x30 | col | |x| | sign | cls | [x] | {x} | max | and | or | xor | not | rnd | pnt | line | rect | arc
x40 | MS0 | MS1 | MS2 | MS3 | MS4 | MS5 | MS6 | MS7 | MS8 | MS9 | MSA | MSB | MSC | MSD | MSE | MSF
x50 | stop | go | ret | sub | nop | J0 | J1 | x≠0 | L2 | x≥0 | L3 | L1 | x<0 | L0 | x=0 | wait
x60 | MR0 | MR1 | MR2 | MR3 | MR4 | MR5 | MR6 | MR7 | MR8 | MR9 | MRA | MRB | MRC | MRD | MRE | MRF
x70 | Kx≠00 | Kx≠01 | Kx≠02 | Kx≠03 | Kx≠04 | Kx≠05 | Kx≠06 | Kx≠07 | Kx≠08 | Kx≠09 | Kx≠0A | Kx≠0B | Kx≠0C | Kx≠0D | Kx≠0E | Kx≠0F
x80 | Kgo0 | Kgo1 | Kgo2 | Kgo3 | Kgo4 | Kgo5 | Kgo6 | Kgo7 | Kgo8 | Kgo9 | KgoA | KgoB | KgoC | KgoD | KgoE | KgoF
x90 | Kx≥00 | Kx≥01 | Kx≥02 | Kx≥03 | Kx≥04 | Kx≥05 | Kx≥06 | Kx≥07 | Kx≥08 | Kx≥09 | Kx≥0A | Kx≥0B | Kx≥0C | Kx≥0D | Kx≥0E | Kx≥0F
xA0 | Ksub0 | Ksub1 | Ksub2 | Ksub3 | Ksub4 | Ksub5 | Ksub6 | Ksub7 | Ksub8 | Ksub9 | KsubA | KsubB | KsubC | KsubD | KsubE | KsubF
xB0 | KMS0 | KMS1 | KMS2 | KMS3 | KMS4 | KMS5 | KMS6 | KMS7 | KMS8 | KMS9 | KMSA | KMSB | KMSC | KMSD | KMSE | KMSF
xC0 | Kx<00 | Kx<01 | Kx<02 | Kx<03 | Kx<04 | Kx<05 | Kx<06 | Kx<07 | Kx<08 | Kx<09 | Kx<0A | Kx<0B | Kx<0C | Kx<0D | Kx<0E | Kx<0F
xD0 | KMR0 | KMR1 | KMR2 | KMR3 | KMR4 | KMR5 | KMR6 | KMR7 | KMR8 | KMR9 | KMRA | KMRB | KMRC | KMRD | KMRE | KMRF
xE0 | Kx=00 | Kx=01 | Kx=02 | Kx=03 | Kx=04 | Kx=05 | Kx=06 | Kx=07 | Kx=08 | Kx=09 | Kx=0A | Kx=0B | Kx=0C | Kx=0D | Kx=0E | Kx=0F
xF0 | M+0 | M+1 | M+2 | M+3 | M+4 | M+5 | M+6 | M+7 | M+8 | M+9 | M+A | M+B | M+C | M+D | M+E | M+F

В целом система команд основана на системе команд популярных советских микрокалькуляторов БЗ-34 или МК-61. Так что практически любая программа с МК-61 (не использующая недокументированные возможности) будет работать и на PocketMK. Однако, есть и несколько отличий. PocketMK использует фортрановские символьные обозначения функций: `asin` для арксинуса, `tan` вместо `tg` для тангенса и т.д. Кроме того, имеется различное начертание ряда команд с более устоявшимся англоязычным обозначением:

PocketMK | БЗ-34 | MK-61
--- | --- | ---
`MR` | `ИП` | `П→X`
`MS` | `П` | `Х→П`
`rnd` | `` | `КСЧ`
`sign` | `` | `КЗН`
`stop` | `С/П` | `С/П`
`ret` | `В/О` | `В/О`
`go` | `БП` | `БП`
`sub` | `ПП` | `ПП`

В PocketMK добавлен ряд команд (выделены цветом в таблице):

1. графических (`pnt, line, rect, arc, col, cls`) для рисования точки (х,у), линии в точку (х,у), прямоугольника из текущей до точки (х,у), дуги из текущей до точки (х,у), задания цвета (можно задавать и вручную выбором из палитры) и очистки экрана;
2. спец. функций (erf(x), sinh(x), cosh(x), tanh(x), asinh(x), atanh(x), x! = Г(x+1), j0(x), y0(x), j1(x), y1(x));
3. прибавления регистра Х к числу в указанном регистре (команда `М+`);
4. удаления числа из стека (команда `B↓`).

Удалены редко использующиеся (по крайней мере автором) команды по преобразованию углов в минуты, секунды и обратно. Операция `xy` теперь стала настоящей двуместной операцией (содержимое регистра Y не сохраняется).

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

### Ввод числа

Ввод числа осуществляется командами `0 1 2 3 4 5 6 7 8 9 . ± EE`. Команды `0 1 2 3 4 5 6 7 8 9 .` вводят непосредственно цифры мантиссы или порядка. Команда `±` меняет знак числа в регистре Х, если введена до команды `EE` или знак порядка, если после. Команда `EE` указывает, что дальнейший ввод относится к вводу порядка. Нажатие любой другой клавиши (кроме функциональных `F` или `K`) прерывает ввод числа. При вводе нового числа предыдущее значение регистра Х поднимается вверх по стеку, если перед этим не была выполнена одна из команд `Cx` или `B↑`.

Важно! Команда `EE` превращает 0 в 1 (при этом в стеке меняется только значение регистра Х, остальные регистры стека сохраняют свои значения). Эта недокументированная особенность советских калькуляторов часто использовалась в программах.

Совет! Команда `EE` изменяет порядок любого числа в регистре Х. Поэтому для быстрого умножения числа на 10n в программе можно воспользоваться кодом `EE n`, занимающим всего две ячейки памяти при n=1...9.

### Команды работы со стеком

К этой группе относятся команды `Cx B↑ ↔ Bx ↻ B↓`. Напомним, что PocketMK использует стек из 4х регистров (X,Y,Z,T) и регистр B для хранения предыдущего значения Х. Исходное значение стека будем считать равным `b x y z t`.

`Cx` | Обнуляет регистр Х. Ввод числа после этой команды не изменяет содержимое стека.
`B↑` | Поднимает число Х вверх. Стек изменяется следующим образом `b x x y z`. Ввод числа после этой команды не изменяет содержимое стека.
`↔` | Меняет содержимое регистров X и Y местами. Стек изменяется следующим образом `x y x z t`.
`Bx` | Возвращает значение регистра Вх в Х. Стек изменяется следующим образом `b b x y z`.
`↻` | Вращает содержимое стека. Стек изменяется следующим образом `x y z t x`.
`B↓` | Удаляет содержимое регистра Х со сдвигом стека вниз. Стек изменяется следующим образом `x y z t t`.

### Двуместные операции

Операции выполняются над числами в регистрах X и Y. При этом содержимое регистра Y теряется, а регистры Z и T смещаются вниз. Значение регистра Х заносится в регистр В. Стек `b x y z t` изменяется следующим образом `x g z t t`, где g – результат операции. Рассмотрим команды подробнее.

`+` | Сложение чисел X=Y + X.
`–` | Разность чисел X=Y – X.
`*` | Умножение чисел X=Y * X.
`/` | Деление чисел X=Y / X.
`xy` | Возведение в степень X=XY.
`and` | Побитовое И. Дробная часть чисел отбрасывается.
`or` | Побитовое ИЛИ. Дробная часть чисел отбрасывается.
`xor` | Побитовое Исключающее ИЛИ. Дробная часть чисел отбрасывается.
`max` | Максимальное из чисел X и Y.

### Математические функции

Вызов функции относится к одноместным операциям, не затрагивающим содержимое регистров Y, Z, T. Значение аргумента всегда заносится в регистр В. Результат действия функции помещается в регистр Х. Для обратных функций на советских калькуляторах использовались обозначения f(x)-1 (например, sin-1), в PocketMK они заменены на стандартные компьютерные обозначения с добавление буквы a перед именем функции (например, asin).

`10x` | Возведение в степень 10x = exp(x*log(10)).
`ex` | Экспонента ex = exp(x), где e = 2.718281828459.
`lg` | Десятичный логарифм lg(x)=ln(x)/ln(10), lg(10x)=x.
`ln` | Натуральный логарифм, ln(exp(x))=x.
`sin` | Синус sin(x), вычисляется в зависимости от выбора deg|grd|rad.
`cos` | Косинус cos(x), вычисляется в зависимости от выбора deg|grd|rad.
`tan` | Тангенс tan(x)=sin(x)/cos(x), вычисляется в зависимости от выбора deg|grd|rad.
`asin` | Арксинус asin(sin(x))=x, вычисляется в зависимости от выбора deg|grd|rad.
`acos` | Арккосинус acos(cos(x))=|x|, вычисляется в зависимости от выбора deg|grd|rad.
`atan` | Арктангенс atan(tan(x))=x, вычисляется в зависимости от выбора deg|grd|rad.
`sh` | Гиперболический синус sh(x) = (ex – e-x)/2.
`ch` | Гиперболический косинус ch(x)=(ex + e-x)/2.
`th` | Гиперболический тангенс th(x)=sh(x)/ch(x).
`ash` | Гиперболический арксинус ash(sh(x))=x.
`ach` | Гиперболический арккосинус ach(ch(x))=|x|.
`ath` | Гиперболический арктангенс ath(th(x))=x.
√x | Корень квадратный sqrt(x2) = |x|.
`x2` | Квадрат числа.
`1/x` |
`erf` | Интеграл вероятности erf(x) = ∫exp(-x2)dx.
`x!` | Факториал x!=Г(x+1), Г(x) – гамма функция.
`J0` | Функция Бесселя J0.
`J1` | Функция Бесселя J1.
`Y0` | Функция Бесселя Y0.
`Y1` | Функция Бесселя Y1.
`|x|` | Абсолютное значение |x| = {x для x≥0; –x для x<0}
`sign` | Знак числа: 1 для x>0, 0 для x=0, -1 для x<0.
`[x]` | Целая часть числа.
`{x}` | Дробная часть числа.
`rnd` | Случайное число. В отличии от МК-61 не зависит от числа X. Из соображений совместимости, случайное число не изменяет стек (как в случае с `π`).
`not` | Побитовое отрицание. Дробная часть чисел отбрасывается.

### Работа с регистрами

Для работы с регистрами предназначены три группы команд.

1. Команды `MS`N записывают значение регистра Х в регистр N. Значение регистра Х не изменяется.
2. Команды `M+`N прибавляют значение регистра Х к числу в регистре N и записывают результат в регистр N. Значение регистра Х не изменяется.
3. Команды `MR`N присваивают регистру X значение из регистра N. Стек `b x y z t` изменяется следующим образом `b n x y z`, где n – значение в регистре N.
4. Немножко в стороне стоит команда `π`. Ее действие полностью аналогично командам `MR`N, но в регистр Х записывается число π=3.141592653589793.

Каждая из команд присвоения регистру имеет отдельный уникальный номер. Это сделано для совместимости с программами для МК-61.

Совет! Ввод небольшого числа данных (до 16 чисел) в программу удобно выполнять с помощью заполнения регистров памяти перед запуском программы.

Совет! Ввод данных в программу можно выполнять с помощью кнопки Step. Кусок соответствующей программы будет выглядеть следующим образом: `MS1 MS2 MS3 ...`. Идея состоит в пошаговом исполнении программы, когда число в регистре Х меняется пользователем на каждом шаге.

Совет! Часто программы используют константы (или типичные начальные условия). Их можно сохранить вместе с программой если пометить соответствующие регистры при сохранении.

Совет! Иногда удобней (особенно в играх) загрузить программу с заполненными регистрами заново, чем вводить цифры вручную.

### Управление программой

Эта группа команд осуществляет управление выполнением программы. Как правило, команды из этой группы требуют 2 ячейки памяти: одна ячейка под саму команду, а вторая ячейка на адрес перехода для этой команды.

`stop` | Останавливает выполнение программы.
`wait` | Приостанавливает выполнение программы на 1 секунду. Удобно использовать в динамических играх.
`nop` | Не выполняет никаких действий.
`go` | Безусловный переход на адрес перехода.
`sub` | Вызов подпрограммы с адреса перехода.
`ret` | Возврат из подпрограммы. При пустом стеке возврата происходит возврат на нулевой адрес (начало программы).
`x≠0` | Если условие X≠0 выполнено, выполняется команда, следующая после адреса перехода, в противном случае производится переход по адресу перехода.
`x<0` | Если условие X<0 выполнено, выполняется команда, следующая после адреса перехода, в противном случае производится переход по адресу перехода.
`x=0` | Если условие X=0 выполнено, выполняется команда, следующая после адреса перехода, в противном случае производится переход по адресу перехода.
`x≥0` | Если условие X≥0 выполнено, выполняется команда, следующая после адреса перехода, в противном случае производится переход по адресу перехода.
`L0` | После выполнения команды происходит вычитание единицы из регистра 0. Если результат R0≤0, то продолжится выполнение со следующего адреса. Иначе – перейдет на указанный адрес перехода.
`L1` | После выполнения команды происходит вычитание единицы из регистра 1. Если результат R1≤0, то продолжится выполнение со следующего адреса. Иначе – перейдет на указанный адрес перехода.
`L2` | После выполнения команды происходит вычитание единицы из регистра 2. Если результат R2≤0, то продолжится выполнение со следующего адреса. Иначе – перейдет на указанный адрес перехода.
`L3` | После выполнения команды происходит вычитание единицы из регистра 3. Если результат R3≤0, то продолжится выполнение со следующего адреса. Иначе – перейдет на указанный адрес перехода.

Совет! Для быстрого возврата на нулевой адрес можно использовать команду `ret`. Это работает, если стек возвратов пустой (не выполняется подпрограмма в данный момент).

Совет! Использование команды `wait` и переключателя deg|grd|rad позволяет создавать динамические программы. Идея состоит в том, что функция `cos` выдает различные значения в зависимости от положения переключателя. Например, следующий код `wait MR9 cos sign` будет ожидать реакции пользователя 1 секунду и возвращать -1, 0, 1 для переключателя deg|grd|rad соответственно, если `R9=100`.

### Косвенная адресация

Команды косвенной адресации начинаются с нажатия кнопки K и всегда занимают одну ячейку памяти. После нажатия `K` вводится одна из команд `MS, MR, go, sub, x<0, x≥0, x=0, x≠0` и номер регистра. На клавиатуре команды косвенной адресации выделены фиолетовым цветом. При косвенной адресации (индексации) в командах `KMS` и `KMR` запись и считывание числа производится из регистра с номером равным остатку от деления на 16 числа в указанном регистре. Переход по адресу в командах `Kgo, Ksub, Kx<0, Kx≥0, Kx=0, Kx≠0` производится по остатку от деления содержимого регистра на 160.

Перед выполнением действия значение регистра модифицируется. Если номер регистра 0, 1, 2, 3, то его значение уменьшается на единицу. Если номер регистра равен 4, 5, 6, то значение регистра увеличивается на единицу. Остальные регистры не изменяются.

Например, команда `KMS0` поместит значение регистра X в регистр, номер которого указан в регистре 0, но меньший на 1. Команда `KMR4` поместит в регистр X значение регистра, указанного в регистре 4, но больший на 1. Команда `Kgo9` переведет работу программы на адрес, указанный в регистре 9. Аналогично переход на подпрограмму, адрес которой указан в регистре B, выполняется командой `KsubB`. Команда `Kx=0A` аналогична команде `x=0 XX`, но адрес перехода XX указывается в регистре A, и команда занимает одну ячейку памяти.

Следует обратить внимание, что если в регистр поместить дробное число, а затем к этому регистру применить команду косвенного вызова, то от помещенного числа будет отброшена дробная часть. Например, поместив число 12.34567 в регистр 9 и выполнив команду `KMR9`, в регистре 9 останется число 12. Эта «недокументированная» особенность в программах БЗ-34 часто использовалась для отделения целой части числа и была сохранена в PocketMK.

### Графические команды

В PocketMK добавлены 6 графических команд: `cls, col, pnt, line, rect, arc`. Графический вывод производится в растровую картинку размером 400*300 с началом координат в левом нижнем углу. Все точки вне этих границ игнорируются.

### Обработка ошибок

В ходе расчетов могут возникать ошибочные ситуации (например, деление на 0, извлечение корня из отрицательно числа и т.д.). В этом случае на экране показывается сообщение NaN или Infinity. Работа программы автоматически останавливается при возникновении ошибочной ситуации.

### Советы

- Команда `EE` изменяет порядок любого числа в регистре Х. Поэтому для быстрого умножения числа на 10n в программе можно воспользоваться кодом `EE n`, занимающим всего две ячейки памяти при n=1...9.
- Ввод небольшого числа данных (до 16 чисел) в программу удобно выполнять с помощью заполнения регистров памяти перед запуском программы.
- Ввод данных в программу можно выполнять с помощью кнопки Step. Кусок соответствующей программы будет выглядеть следующим образом: `MS1 MS2 MS3 ...`. Идея состоит в пошаговом исполнении программы, когда число в регистре Х меняется пользователем на каждом шаге.
- Часто программы используют константы (или типичные начальные условия). Их можно сохранить вместе с программой если пометить соответствующие регистры при сохранении.
- Иногда удобней (особенно в играх) загрузить программу с заполненными регистрами заново, чем вводить цифры вручную.
- Для быстрого возврата на нулевой адрес можно использовать команду `ret`. Это работает, если стек возвратов пустой (не выполняется подпрограмма в данный момент).
- Использование команды `wait` и переключателя deg|grd|rad позволяет создавать динамические программы. Идея состоит в том, что функция `cos` выдает различные значения в зависимости от положения переключателя. Например, следующий код `wait MR9 cos sign` будет ожидать реакции пользователя 1 секунду и возвращать -1, 0, 1 для переключателя deg|grd|rad соответственно, если `R9=100`.