Комментарии 24
:) хм... Хотел бы иметь подобный фортель на vba Excel
Не знаю, чем вызван такой интерес, но это повсеместно встречалось в 90х. Даже в литературе по ZX-Spectrum Медноногов и Родионов описывали подобное.
Ага. И usr(0), где 0 — чисто на экране, а на самом деле там переход сильно в другое место... Причём, так делалось по двум разным причинам:
прикрыть реальный адрес перехода от просмотра (любопытствующие не откажутся хотя бы от LIST)
сэкономить память, требуемую загрузчиком на бейсике (чтобы можно было сдвинуть RAMTOP как можно ниже и загрузить в верхнюю часть уже код для z80)
По второй причине когда-то сам делал, но это было давно и мои извращения далеко не разошлись.
Можно хранить полезный код в видеопамяти и прикрыть его черным цветом. Мы так делали когда писать свой упаковщик.
Вот. Вы, стало быть, понимаете, что за история с этим нулем в качестве аргумента USR. Поясните, пожалуйста. Я из статьи не понял. А из вашего комментария понял, что из статьи я понял еще меньше.
Не нужно пояснять. Справился. Запись значений перед вызовом USR и есть прописывание адреса вызова для USR в зарезервированные для этого байты.
Ещё был интересный хак с управляющими символами. Можно было за счёт смещения каретки вправо скрывать в комментариях коды:
8 (0x08) — курсор влево (возврат на один символ назад)
9 (0x09) — курсор вправо
10 (0x0A) — курсор вниз
11 (0x0B) — курсор вверх
1 -- Нет. Трюк был общеизвестен, так что "любопытствующих", которые реально понимают, куда лезут, он бы не смутил, а от полных чайников скрывать адрес запуска загрузчика смысла ноль, они и так ничего не поймут.
2 -- Да. Сэкономить память. но не ради рамтоп, а просто чтоб ускорить загрузку загрузчика на несколько миллисекунд. Ну и просто "стандарт качества": НЕ использовать такие трюки было просто немодно.Ниже объясню, почему рамтоп неважен.
Короч, на спектруме каждая константа хранилась в тексте программы одновременно в двух форматах: в человеко-читаемом аски, как коды символов цифр, и, сразу после аски, в невидимом для пользователя пятибайтовом двоичном формате. Не касалось это только буфера редактирования строк, там строка хранилась без бинарников. Они добавлялись при сохранении строки и удалялись из копии строки, вызванной на редактирование и скопированной в буфер. При исполнении кода аски-запись игнорировалась, интерпретатор сразу брал готовое бинарное значение.
Таким образом, число, являющееся адресом любой ячейки озу, занимало в тексте бейсик-программы десять байтов: пять на текстовую запись (от "16384" до "65535" -- пять цифр). Байты можно было сэкономить двумя путями: четыре байта экономилось, если вместо настоящего пятизначного числа написать однозначное (0-9), а в бинарный блок прописать настоящее значение. Или же можно было сэкономить лишь два байта, зато сохранить читабельность кода: для этого достаточно было заключить константу в функцию VAL. RANDOMIZE USR VAL "3e4", например. При такой записи предварительный пересчёт константы в бинарный формат не производится, и вся строка хранится в памяти ровно так, как видится.
Если какая-то константа использовалась в коде больше двух раз, её было выгодно заменить на переменную с однобуквенным (или двух, если констант больше 26) именем. Не помню сейчас, сколько байтов занимала в памяти переменная, но использованная больше двух раз, она давала по +9 байтов экономии на каждом следующем использовании, если мы говорим о пятизначных числах. Причём заметьте, в коде загрузчика тратить место на её явное присвоение не нужно: код программы сохранялся и загружался вместе со всеми переменными, присутствующими в памяти.
Вообще, идеальный лоадер мог состоять из всего одной строчки: 0 PRINT USR 0, с машинным кодом, засунутым в область переменных.
Сорри, отвлёкся. Так вот, о RAMTOP. Он используется только интерпретатором бейсика, так что загрузчику он не нужен. Нормальный загрузчик -- односторонний, выхода из него обратно в бейсик не предусмотрено, только через сброс, так что он может совершенно спокойно скопировать себя в область памяти, скажем, с 65е3, и грузить полезный код начиная хоть с 23297 (т.е. сразу после блока видеопамяти), затирая и блок служебных данных интерпретатора, и код своего бейсик-загрузчика.
когда экономили память, то использовали команду val "15616", она не записывали невидимые 5 байт числа с плавающей точкой.
а так, да, загрузчик с дискеты в rem строке - обычная практика
Для молодых разрабов прямая запись байтов в память Бейсика выглядит как черная магия, отсюда и интерес
не столько чёрная магия, сколько шаманские ритуалы, прямо запрещённые современной конвенцией по использованию памяти (W XOR X). Поэтому их проходят, если проходят, как исторический казус, не вдаваясь в подробности. А так - и таблицу прерываний под ДОСом бывалоче переписывали на горячую, и оно ещё и работало потом, или клавиатурный буфер, чтобы не пищало, и те же ZXовые патчи кода на бесконечные жизни, и более ранние хаки - много что было.
Мне было лет 14 когда я этим занимался. Уж куда моложе-тооооо.
А процессору Z80 в этом году исполнилось 50 лет! И его вроде ещё выпускают.
А что вообще происходит? Почему 2 одинаковых на 99% поста появились?
раз https://habr.com/ru/articles/1062204/
два https://habr.com/ru/companies/cloud4y/articles/1062236/
Где модератор?
Затратить полсотни часов реверса чтобы выяснить, что дед сорок лет назад просто хотел нормальный рандом в игре 🤌🏻
Хранение ассемблерного кода в программе на Бейсике это стандартный способ сделать нестандартный загрузчик с ленты или с диска. Все вот эти загрузчики со счетчиками, загрузчики картинки по квадратам, а не по линиям и т.д.
Поэтому программа загрузчика выглядела примерно как-то так:
10 RANDOMIZE USR 23872 : REM дальше нечитаемая белиберда.
Можно было использовать не RANDOMIZE, а другую команду с числовым параметром.
Что касается рандома, то все юзали регистр R, это опять-таки было стандартной практикой, хоть это и вообще ни разу не рандом.
На закате эпохи Speccy регистр R ещё использовался для защиты программ от копирования и взлома, включая методы динамической дешифрации, привязки к таймингам и сокрытия кода. Например в IS-DOS от Iskra Soft.

Загадочный комментарий в древней игре на BASIC