ZX-Spectrum изнутри 1969 г.

Глава 2 - способ записи программ на ленте.


2. СПОСОБ ЗАПИСИ ПРОГРАММ НА ЛЕНТЕ.

Помните, что практически каждая программа имеет хотя бы процедуру
-загрузчик, написанную на БЕЙСИКе, а если ее не имеет, то вообще не
защищена,

Начнем со способа записи программ на ленте * припомним, что видно
и слышно бо время считывания какой-либо программы. В течении 1-2 се-
кунд на экране видны широкие 1фаоно-синие полосы, а также слышен дли-
тельный звук. Это так называемый пилот, который позволяет компьютеру
синхронизироваться с сигналом слейты, который он будет считывать.
Потом на момент появляются тонкие, мерцающие желто-фиолетовые полос-
ки, свидетельствующие о том, что компьютер считывает в память инфор-
мацию. Ее-17 байтов - это так называемый заголовок. Появляется над-
пись "BYTES", "PROGRAM:", "CHARACTER ARRAY;" или "NUMBER ARRAY:", a
потом, послесекундного перерыва, начинается второй пилот (более ко-
роткий), а после него Учитывается собственно программа. Займемся те-
перь заголовками, т.к. в них содержатся важнейшие данные о считывае-
мых программах.

Заголовок, как мы ухе вспомнили, содержит 17 байт. Пронумеруем их
от 0 до 16 (см. рис.3). Нулевой байт обозначает тип блока. Он равен
О, если это - программа на БЕЙСИКе; 3 * если это блок машинного кода
(записанный с помощью SAVE ".." СООЕ или SAVE ".." SCREEN*, который
обозначает точно то же, что и SAVE ".." СОК 1&ЗВ4,&912)< Е«ли же
этот заголовок предшествует набору, являющемуся массивом переменных
БЕЙСИКа (записанный с помощью SAVE ".." DATA ..), то он равен 1 для
числовых массивов или 2 для символьных.

Следующие 10 байт - это имя считываемого блока или текст, появля-
ющийся после загрузки заголовка за надписью "PROGRAM:", "BYTES:" или
другой.

Байты 11 и 12 содержат двухбайтовое число (первый байт младший),
определяющее длину блока данных, к которому относится заголовок,

В зависимости от типа считываемого блока байты с 13 по 16 интерп-
ретируются по-разному. Начнем с заголовков программ, написанных на
БЕЙСИКе. Байты 13 и 14 содержат номер строки старта программы, если
она была записана с помощью SAVE "./'LINE NR. Если программа была
записана без опции LINE и после считывания не стартует автоматически,
то значение этого числа больше 32767. Одним из способов нейтрализации
защиты самостартующих программ на БЕЙСИКе является замена этих деух
байтов в заголовке на число большее 32767.

Б$йты 15 и 16 содержат число, определяющее длину самой программы
на БЕЙСИКе (т.к. SAVE и..н или SAVE LINE записывает программу
вместе со всеми переменными, т.е. содержимое памяти от байта, указы-
ваемого системной переменной PROG, до байта, определенного переменной
E^LINE). Если от всей длины блока (байты 11 и 12) отнимем это число,
то узнаем, сколько байтов в этом блоке занимают переменные БЕЙСИКа.
Это все, если речь идет о заголовках программ на БЕЙСИКе.

в заголовках машинного кода ("BYTES'*) байты 15 и 16 не использу-
ются , зато 13 и 14 составляют двухбайтовое число, определяющее, по
какому адресу надо загрузить следующий за заголовком блбк.

В заголовках массивов из этих четырех байтов используется только
14-й байт, который представляет имя считываемого массива. Он записан
так же, как и имена всех временных БЕЙСИКа (в области $т VAAS до
E_LINE), т.е. 3 самых старших бита обозначают тип переменной (здеоц
это числовой или символьный массив), а 5 младших битов - имя этой пе-
ременной.

На листинге 1 представлена программа, реализующая процедуру, де-
лающую возможный чтение заголовков программ, записанных на ленте.
После точного ввода программы (внимательно проверьте количество про-
белов в строках с инструкциями DATA) запустите ее с помощью RUN и по-
дождите минуту. На экране появится информация 66 адресах начала и
конца процедуры, а также о ее длине, которая должна составлять 284
байта. Если это не так, проверьте, все ли строки программы введены
без ошибок. Если все данные были верны, то на Вашей ленте окажется
процедура "ЧТЕЦ", благодаря которой Вы сможете прочесть каждый заго-
ловок. После записи на ленту ее можно удалить из памяти.

Процедура "ЧТЕЦ" будет работать правильно, независимо от того, по
какому адресу она будет загружена. Можете считать ее с помощью

LOAD "CZYTACZ" CODE А/ 1С
и затем запустить (даже многократно) с помощью
RANDOMIZE USR АДРЕС

После запуска процедура считывает по адресу 23296 (в буфер прин-
тера^) первый встреченный заголовок. Если из-за подключенных внешних
устройств этот адрес Вас не устраивает, то его можно изменить. Для
этого в строке с номером 200 надо заменить число #005В шестнадцати-
ричным адресом, по которому Вы хотели бы считывать заголовки (две
первые Цифры - младший байт). Чтобы после замены избежать проверки
контрольной суммы в этой строке, в конце текста, взятого в кавычки,
вместо пробела и 4-х цифр контрольной суммы поместите литеру "S" с 4-
мя ведущими пробелами.

После считывания заголовка процедура читает заключенную в нем ин-
формацию и возвращается в БЕЙСИК, но считанного заголовка не уничто-
жает. Следовательно, если желаете просмотреть его дополнительно, мо-
жете сделать это с помощью функции РЕЕК.

Однако, чтения заголовка мало, чтобы смочь взломать блоки, запи-
санные на ленте. Необходимо еще знать, что надо сделать с этими бло-
ками, чтобы разместить их в памяти, не позволяя им при этом начать
работу.

В случае блоков типа "BYTES" достаточно обычно загрузить их по
адресу выше RAMT0P (т.е. выше ячейки памяти, указываемой системной
переменной RAMT0P), например с помощью

CLEAR 29999: LOAD "" CODE 3000

Этот метод работает, если только считываемый блок не очень длин-
ный (может иметь максимально до 40К). Более длинные блоки могут прос-
то не поместиться в память - тогда необходимо разделить их на нес-
колько более коротких частей. Скоро мы узнаем, как это делать.

Так хе и в случае массивов. Их загрузка не вызывает затруднений -
достаточно применить обычную в таких ситуациях инструкцию LOAD ""
DATA.

Хуже, однако, выглядит считывание программ на БЕЙСИКе. Они обычно
записываются с помощью SAVE ".." LINE ..., а в самом начале строки, с
которой они должны выполняться, размещены инструкции, защищающие
программы от останов*. Простейшим решением является загрузка програм-
мы не с помощью LOAD "", а с помощью MER6E "", но этот способ не
всегда дает результат. Из этой безнадежной ситуации существует два
принципиальных выхода: подменить заголовок программы или использовать
представленную ниже программу "LOAD/MERGE". Первый способ основан на
замене записанного не ленте заголовка на такой же, но не вызывающий
самозапуск программы. Можно с этой целью использовать программу
"COPYCOPY" - считать заголовок программы, нажать "BREAK", а затем ин-
струкцией LET заменить ее параметр START на число большее 32767 (т.е.
выполнить, например, LET I* 32768, если корректируемый заголовок был
считан как первый набор). Модифицированный таким образом заголовок
записываем где-нибудь на ленте. Убираем из памяти программу
"COPYCOPY" и вводим L0A0 "". Считываем только что сделанный заголо-
вок, но сразу же после его окончания останавливаем ленту. Теперь в
магнитофон вставляем кассету с программой так, чтобы считать только
текст программы без ее заголовка.

Другой способ намного выгоднее. Вводим в память (с клавиатуры или
с ленты) программу "LOAD/MERGE", приведенную на листинге 2. После за-
пуска она начинает ждать первую программу на БЕЙСИКе, которая нахо-
дится на ленте. Считывает ее совершенно так же, как инструкция LOAD
"", но после загрузки не позволяет программе запуститься - выводит
только сообщение "0 ОК" с информацией, с какой строки считанная прог-
рамма должна была стартовать.

На листинге 3 представлена процедура, которая образует эту прог-
рамму из РОКЕ-ов. Ее определяющей инструкцией яьляется CALL 1821. На-
чиная с адреса 1S41 в ROM находится процедура, интерпретирующая инс-
трукции SAVE, LOAD, VERIFY, MLR6E. CALL 3 821 прыгает прямо в середину
этой процедуры. Ее начальную часть (считывающую параметры этих инс-
трукций) обходим, заменяя это строками 40 - 50 нашей процедуры: сна-
чала с помощью RST 48 резервируем 34 байта в области W0RKSP. Первые
17 байт заполняются процедурой из ROM после считывания параметров вы-
полняемой инструкции БЕЙСИКа, а вторые - это место для считанного за-
головка. Оба этих заголовка затем сравниваются перед тем как прочесть
блок данных (проверяются соответствие имени и типа блока). Адрес сво-
бодного места переносим из регистра DE в IX; в строке 80 фиксируем
системные переменные: T_ADDR, указываем, что нам нужна процедура LOAD
(а не VERIFY, например); в первом байте заголовка для сравнений поме-
щаем значение 255, означающее, что долхен быть считан первый встре-
ченный блок (то ест& программа на БЕЙСИКе). Остальное берет на себя
процедура из ROM, действующая идентично LOAD "". Разница основана на
том, что после полного считывания программы вместо возврата по RET в
интерпретатор БЕЙСИКа мы переносим значение переменной NEVPCC (номер
строки, к которой должен быть переход) в РСС (номер последней выпол-
няемой строки), а также не допускаем самозапуска программы - выполня-
ем RST 8 с сообщением "0 ОК". Благодаря этому переносу в выведенном
сообщении будет информация о номере строки, с которой считанная прог-
рамма должна была запуститься.

2.1. ЛИСТИНГИ ПРОГРАММ.

Листинг 1
10 CLEAR 59999: LET POCZ-60000
20 LET A0R-P0CZ
30 RESTORE: READ A,B,C,D,E,F
40 DATA 10,11,12,13,14,15
50 LET NR-200: RESTORE NR
60 LET S«0: READ A$: IF A$«'" THEN 60 TO 130
70 FOR N*1 TO LEN A$-5 STEP 2
80 LET W*16*VAL A$(N)+VAL A$(N+1)
90 POKE A0R.W: LET ADR«ADR+1: LET S«S+V
100 NEXT N

110 IF VAL A$(N TO)<>S THEN PRINTMERR IH LINE";NR: STOP
120 LET NR-WR+10: 60 TO 60

130 PRINT"OK"''"BEG:и;POCZ'MEN0:";ADR-1'"LEN:";ADR-POCZ
140 SAVE "CZYTACZ" CODE POCZ,ADR-POCZ
150 REM

200 DATA "21920009E5DD21005BDDE51111 1246"
210 OATA "0QAF37CD5605DDE130F23E02CD 1531й
220 DATA "011611C009DD7EOOCDOAOCDDE5 1265"
230 DATA "D113010A00CD3C202A7E5CD1E5 1231"
240 DATA "D5ED537B5C010900CD3C20DD46 1346"
250 DATA "OCD04E08CD2B2DCDE32DE1DD7E 1664"
260 DATA "0ODD460FDD4EQDC5A7202BEB01 1292"
270 DATA "19O0CD3C20D5DD4610DD4E0FCD 1361"
280 DATA "2B20CDE32DD1C178E6C020SEC5 1848"
290 DATA "011300CD3C20C1CD2B2DCDE32D 1280"
300 DATA "185EFE03203601700009EB0111 836"
310 DATA "0018E60D449C75676F9D9B2073 1281"
320 DATA "616D65676F207Q726F6772616D 1313"
330 DATA "75200D4175746F737461727420 1161"
340 DATA "2D206C696E69612002EE1B0181 1239"
350 DATA "OO09EBO1O9OOCD3C2OC13E1FAO 997"
360 DATA "F660D7DD7E003D28033E24D73E 1383"
370 OATA "28D73E29D7E1227B5C3E0DD7C9 1538"
380 DATA "04081C2020201CQ00010181030 268"
390 DATA "100C0008103840380478000D41 430"
400 DATA "64726573209C61646F77616E69 1357"
410 DATA "61200D5461626C69636120 862"
420 DATA "."

Листинг 2

1 REM LOAD/MERGE TS&RD 1987

2 FOR N«60000 TO 60025: READ A: POKE N,A: NEXT N

3 RANDOMIZE USR 60000

4 DATA l,34f0r247f213,221r225f253,54r58,l,221,54,1.255,

205,29,7,42,66,92,34,69,92,207.255

Листинг 3

30 ORG ' 60000 ;LOAD/MERGE

40 LD ВС, 3.4

50 RST 48

60 PUSH DE

70 POP IX

80 LD (IY+58),1

90 LD (IX+1J.255

100 CALL 1821

110 LD HL,(23618)

120 LD (23621),HL

130 RST 8

140 DEFB 255




  Оставте Ваш отзыв:

  НИК/ИМЯ
  ПОЧТА (шифруется)
  КОД



Темы: Игры, Программное обеспечение, Пресса, Аппаратное обеспечение, Сеть, Демосцена, Люди, Программирование

Похожие статьи:
Вступление - От авторов.
В паутине - График работы городских серверов.
Вступление - содержание номера.
Психология - Все люди подвержены эмоциональным перегрузкам и стрессам, и с этим можно и нужно бороться.
Записки программиста - глюк монитора отладчика в ZS Scorpion 256.

В этот день...   19 апреля