«MK-61s»: самомодифицирующиеся программы
У меня была давно идея попробовать сделать самомодифицирующуюся программу на программируемом калькуляторе «Электроника
Своей цели я ещё не достиг, хоть и продолжаю пытаться, а пока экспериментирую с командами доступа в область Ms — это недоделанные команды, которые я разблокировал в ретроконсоли «
Там всего две команды — одна обменивает Ms с содержимым памяти, вторая с регистрами. Таким образом вырисовывается путь — меняем
Выглядит просто, но есть особенности — калькулятор хранит числа в особом формате и при переносе в программную память этот формат создаёт проблемы. Байтами команд становятся не только цифры числа, но и его знак и порядок. Поэтому записать в регистр
Например, число 690050,68 после такого переноса даёт последовательность кодов 68 50 00 69 50 00. Для калькулятора это уже программа: прочитать регистр 8, остановиться, ввести ноль, прочитать регистр 9, снова остановиться и ввести ноль. Кроме этих шести байтов у каждого блока есть ещё один служебный байт, который команда обмена с регистрами не меняет. Его можно заранее заполнить нужной командой.
Теперь самое интересное: если вычесть из этого число 10000,01, получим 680050,67, а в памяти — 67 50 00 68 50 00. Команды остались прежними, но оба номера регистров уменьшились на единицу. Продолжая вычитать ту же константу, можно получить целую серию похожих участков программы.
Я решил попробовать использовать это для программы, которая не просто сама себя модифицирует, а, в идеале, сама себя распаковывает, то есть занимает меньше команд при вводе, чем в памяти.
Для этого я взял игру «The Land of Psycho Lamers» и переставил её код так, чтобы повторяющиеся участки укладывались в вышеупомянутый шаблон. Получился распаковщик длиной всего двадцать байт: он берёт начальное число и шаг, заполняет девять регистров, а затем двумя обменами переносит результат в программную память. Так восстанавливаются 63 байта команд.
Правда, тут надо честно посчитать всё остальное: исходные числа, заранее расставленные служебные байты и код подготовки. С учётом этого выигрыш получился скромным — 75 загружаемых байт против 80 у исходной игры. Это если в обоих случаях не загружать нули. Сам текстовый файл стал даже больше, да и занимаемый диапазон программной памяти вырос. Так что до практичного архиватора далеко, но работающая игра, которая сама собирает часть своего кода из чисел, уже получилась.
Ниже можно пройти распаковку по шагам. Хорошо видно, как сначала исходные данные уходят в Ms, затем из чисел строятся будущие команды, а в конце они одним обменом появляются в основной памяти.