Жариков Л.Н.

Программа для программатора ППЗУ и её оптимизация

Многие читатели заинтересовались опубликованной в выпуске № 2 за этот год программой Р. Барташюса для программатора ППЗУ и предлагают свои изменения. Вызвало нарекания большое количество опечаток - неизменных спутников любой сложной публикации.

Вашему вниманию предлагается обзор предложений. Свой вклад в программу внесли: В.Г. Бендаринов из г. Горького, Г. Мухамедов из г. Ташкента, Д.Ю. Усенков из Москвы, знакомый вам по публикации в том же выпуске, и автор данной статьи.

Сначала ответы на некоторые вопросы. Многих читателей удивило, что в строках 5050, 5060 исходного текста вычисления не выполнены самим автором программы. Очевидно, эти строки специально публиковались Р. Барташюсом в исходном виде для того, чтобы подчеркнуть аддитивные составляющие передаваемых в порт данных, а сложение двух чисел он доверил выполнить читателям.

Вызвало недоумение пользователей и наличие пустых операторов PRINT. Ведь разместить выводимую на экран информацию в Бейсике легко с помощью инструкций АТ, указывающих позицию. Думается, что это было сделано автором для большей простоты и наглядности текста.

Теперь об исправлениях программы, которые предлагаются с целью улучшения её пользовательских качеств и стиля программирования. Нужно сказать, что указанные читателями изменения и дополнения касаются только отдельных сторон её оптимизации и не дают максимального эффекта, который хотелось бы получить.

Если же действительно говорить о существенной оптимизации программ, то это достигается применением сочетания достаточно стандартных способов.

Вот некоторые из способов оптимизации:

Способы приведены приблизительно в той последовательности, в которой их следует применять. Как знают опытные программисты, на практике применение этих способов обычно начинается в обратном порядке, приводя к значительным затратам усилий для достижения того же эффекта, который даёт правильная последовательность.

На примере вызвавшей специфический интерес к программе для программатора ППЗУ, используя некоторые предложения читателей, покажем, как применять приведённые выше приёмы. Будем пользоваться текстом программы Р. Барташюса, приведённым во втором выпуске ВТ.

Первый в перечне способ ни у кого не вызывает сомнений, если это связано с достаточно солидной программой. Имея перед глазами работоспособную версию, метод и саму структуру алгоритма, будем считать пока правильными, как это делают сначала все программисты, и используем второй метод.

Во второй строке исходной программы описан массив D(63,15), no умолчанию являющийся массивом двойной точности. Каждый элемент такого массива занимает в памяти 8 байтов. Если мы вспомним, что данный массив служит для хранения прошиваемых в ППЗУ или загружаемых из ППЗУ байтов, то восьмикратный излишек занимаемой этими данными памяти вызовет некоторое удивление. Для хранения байта, обычно достаточно одного байта памяти!

К сожалению, в Бейсике нет типа данных 'byte', как, например, в языке Турбо-Паскаль. Но нас вполне может устроить описание целочисленного массива D%(63,15), говорящее о том, что каждому элементу будет выделено два байта памяти. С этим можно пока смириться. Всё-таки высвобождается 6 Кбайт памяти! Правда, этот выигрыш несколько уменьшится за счёт хранения в исходном тексте знаков '%'.

Достичь ещё большего выигрыша памяти можно, введя вместо массива D%(63,15) массив символьных строк D$(15) и упаковывая в процессе расчётов байты данных в соответствующие символы одной из шестнадцати строк. Но мы этим пока заниматься не будем. Анализ также показывает, что вообще необходимости в числовых переменных нецелого типа в этой программе нет. Поэтому все переменные заменим на переменные целого типа, добавив к ним символ '%'. Этим действием будет сэкономлена память и увеличено быстродействие, так как операции с целыми числами выполняются существенно быстрее.

Точно таким же образом можно заменить и все числовые константы на константы целого типа, проявляя, однако, известную осторожность, так как диапазон целых чисел в Бейсике достаточно узок [-32768, 32767].

Вследствие этого написать в строках 4040, 5050 и 5060 выражение типа

...,N%-32768%... 

вам не удастся. Нужно будет вводить, например, так:

...,N%-32767%-1%... ,

или так

...,N% + &0100000... ,

или так

...,N% + &H8000... .

Ко второму методу оптимизации относится и удаление лишних переменных. Посмотрев на программу несколько внимательнее, можно заметить, что переменная 'B%' в строках 4110, 4120, 4160, 7000, 7050, 7060 используется только для передачи данных подпрограмме в строке 2000. Если от этой весьма короткой подпрограммы избавиться (тоже способ!) и попутно заменить операторы PRINT на знаки вопроса, то соответствующие места будут выглядеть короче:

...
4110-4130 - удалить
4140 ? "ошибка по адресу"; HEX$(I%+KF%)
...
4150-4170 - удалить
4180 ? HEX$(J%); "H"
...
7000-7010 - удалить
7020 ? AT(0%,5%); HEX$(I%)
...
7050-7070 - удалить
7080 ? AT(J%*3% + 6%,5%);HEX$(D%(I%-KF%) AND &HFF)
...

Вычислим и преобразуем теперь, где это возможно, числовые выражения. Таких мест два: строки 4030, 4040 и 5040-5080. Так как эти участки находятся внутри циклов, то это связано и с оптимизацией циклов. Первый цикл после вынесения из него вычислений, не связанных с переменными цикла I% и J%, будет выглядеть так:

...
4000 ? "Ждите..."
4005 K% = KF%*16% + &H8000
4010 FOR I%=0% ТО 63%
4015 L% = I%*16% + K%
4020 FOR J%=0% ТО 15%
4030 N% = L% + J%
4040 РОКЕ -52%,N%
4050 IF CO% = 1% GOTO 4100
4060 D%(I%,J%) = PEEK(-52%)
4070 NEXT J%,I%
4080 – удалить
...

Второй цикл изменится аналогично:

...
5000 ? "ЖДИТЕ..."
5010 K% = KF%*16% + 2048%
5020 FOR I% = 0% ТО 63%
5025 L% = I%*16% + K%
5030 FOR J% = 0% ТО 15%
5040 N% = L% + J%
5045 FOR W% = 0% ТО 5%
5050 РОКЕ -52%, -30720%
5060 РОКЕ -52%, N% + &H8000
5070 РОКЕ -52%, N%
5080 РОКЕ -52%, D%(I%,J%) + 30720%
5090 FOR T = 0 ТО 50
5100 NEXT T,W%,J%,I%
5110-5130 - удалить
...

Заметьте, цикл по W% внесён внутрь циклов по I% и J%. Этим достигается уменьшение количества вычислений вспомогательных переменных K% и L%.

В результате циклы будут выполняться быстрее. Чтобы дополнительно сэкономить ещё, в операторах РОКЕ и РЕЕК можно заменить целочисленные константы на шестнадцатеричные или восьмеричные. Для перевода в другую систему счисления можно воспользоваться функциями OCT$ и HEX$, введенными в непосредственном режиме, например,

? OCT$(-52)
177714
Ok

или

? HEX$(-52)
FFCC
Ok.

Запустив исправленную таким образом программу на исполнение командой RUN, убедимся, что в результате оптимизации цикл чтения из ППЗУ сократился до 3-4 с, а цикл записи почти не изменился. Попутно отметим, что для проверки совсем не обязательно иметь аппаратную часть программатора ППЗУ, достаточно вставить блок нагрузок в разъём параллельного порта при выключенном питании БК. Это обеспечит чтение упорядоченных данных в массив D% в режиме ввода из ППЗУ и режиму контроля будет что проверять. Записать данные в блок нагрузок, естественно, не удастся.

Дальнейшая надежда уменьшения времени выполнения записи в ППЗУ связана с самим внутренним циклом в строке 5090. К сожалению, сокращение времени исполнения этого пустого цикла, введённого для организации определённой задержки, связано с риском увеличения вероятности возникновения ошибок прошивки ППЗУ. Не зная технических параметров схемы программатора ППЗУ, уменьшать это время не стоит.

К сведению любопытных читателей сообщим, что цикл 5010-5130 без операторов 5050-5080 выполняется 8 мин 05 с, а изменённый цикл 5010-5100 вместе с операторами РОКЕ - 8 мин 21 с. Таким образом, дальнейшая оптимизация рассматриваемого участка практически нецелесообразна.

Чтобы ещё более сократить количество строк, заменим вызовы подпрограммы в строках 3340, 3360, 6110, 7030 на сам оператор ?CHR$(155%), переключающий дисплей в режим 64 или 32 символов в строке. В результате строку 7030 можно удалить, а строка 7020 примет вид

...
7020 ? AT(0%,5%);HEX$(I%);CHR$(155%)
...

Окинем взглядом всю программу целиком (см. в конце статьи). Можно заметить, что выделяются несколько в чём-то однородных участков программы: 70-220, 240-290, 1080-1130, 3080-3130.

Попробуем несколько сократить эти участки, используя специфические особенности реализации Бейсика на БК0010.01 и выбирая формы операторов, обеспечивающие наиболее лаконичное исполнение программой возложенных на неё функций. При этом надо помнить, что включение в текст уникальных возможностей версии языка, равно как и подпрограмм в машинных кодах, ограничивает диапазон компьютеров, на которых программа будет работать без переделки.

Первый из рассматриваемых участков написан нерационально, но очень нагляден. Можно его сжать, если указать строки и колонки, с которых начинать вывод меню, инструкциями АТ и LOCATE.

Введение операторов выбора ON ... GOSUB [GOTO] ... позволяет сократить строки 240-290 второго участка. В результате текст будет выглядеть следующим образом:

...
70 IF KF% = 0% THEN ? "К573РФ1 (IРФ2)" ELSE ? "К573РФ2(II)"
80, 90, 110, 130, 150, 170, 190, 210, 220 - удалить
100 ?AT(0%,3%);"1 ввод с клавиатуры"
120 ?AT(0%,5%);"2 ввод из ППЗУ"
140 ?AT(0%,7%);"3 вывод в ППЗУ"
160 ?AT(0%,9%);"4 корректировка"
180 ?AT(0%,11%);"5 РФ1(IРФ2) или IIРФ2"
200 ?AT(0%,13%);"6 контроль"
230 INPUT T$
240 ON VAL(T$) GOSUB 6000,4000,5000,3000
250 ON VAL(T$)-4% GOTO 310,330
260-290 - удалить
...

Третий участок 1080-1130, предназначенный для распознавания цифр шестнадцатеричного двухзначного числа, можно сжать, получая значения кодов вводимых символов с помощью функции ASC:

...
1080 IF ASC(Y$)>70 OR U%<>0% OR Y$ = "0" GOTO 1140
1090 C% = ASC(Y$)-55%
1010-1130,1160 - удалить

Четвёртый участок программы 3060-3130 после анализа может быть сокращён за счёт введения распознавания некоторых подмножеств значений переменной R% и объединения условных операторов. Например,

3080 IF FIX(SQR(R%)) = 5% THEN ON R%-24% GOTO 3210,3170,3190
3090 IF R%=81% THEN 3360 ELSE IF R%=67% THEN 3140 ELSE IF R%=8% THEN 3270 ELSE 3060
3100-3130 - удалить
...

Пытливые читатели могут поупражняться в поиске самого лаконичного способа ветвления алгоритма для данных значений R% (25,26,27,81,67,8). Заметьте, что в результате вместо шести программных строк осталось две, но структурность программы не нарушилась.

Теперь можно заняться и сервисом. Правда, при наличии свободной памяти жертвовать мы им пока не собираемся.

Читатель В.Г. Бендаринов (г. Горький) предложил набросок начального участка программы для несколько другой организации меню. Перемещение по меню вверх-вниз осуществляется с помощью клавиш управления курсором, а выбор темы - нажатием клавиши <ввод>. Работа с таким меню более комфортна.

С некоторыми исправлениями в предлагаемом наброске начальный участок программы будет выглядеть следующим образом:

20 DIM D%(63%,15%)
30 SI%=0%
35 Y%=43% 'Вертикальная координата строки меню
40 CLS
50 CO%=0%
60 KF%=SI%*64%
70 IF KF%=0% THEN ? "К573РФ1(IРФ2)" ELSE ? "К573РФ2(II)"
90 LOCATE 5%,5%,0% 'убрать курсор
100 ?"Ввод с клавиатуры"
120 ?AT(5%,7%); "Ввод из ППЗУ"
140 ?AT(5%,9%); "Вывод в ППЗУ"
160 ?AT(5%,11%); "Корректировка"
180 ?AT(5%,13%); "РФ1(IРФ2) или IIРФ2"
200 ?AT(5%,15%); "Контроль"
210 ?AT(5%,17%); "Выход"
220 Y1%=Y%
221 LINE(30%,Y%)-(200%,Y%+20%),1%,B 'Нарисовать рамку темы меню
222 C$=INKEY$
223 IF C$="" THEN 222 ELSE T%=ASC(C$) 'Между кавычками нет пробела
224 IF T%=26% THEN IF Y%>43% THEN Y%=Y%-20% ELSE Y%=163%
225 IF T%=27% THEN IF Y%<163% THEN Y%=Y%+20% ELSE Y%=43%
226 IF T%=10% THEN IF Y%=163% THEN STOP ELSE 230
227 IF Y%<>Y1% THEN LINE(30%,Y1%)-(200%,Y1%+20%),0%,B 'Стереть рамку темы меню
228 GOTO 220
230 LOCATE 1%,1%,1% 'Восстановить курсор
240 ON (Y%-23%)/20% GOSUB 6000,4000,5000,3000
250 IF Y%=123% THEN 310 ELSE IF Y%<>143% GOTO 40
260 CO%=1%
270 GOSUB 4000
280 ?,,"Для возврата в меню - «ввод»" 'Обратите внимание на запятые
290 IF INKEY$="" THEN 290 ELSE 40 'Между кавычками нет пробела
310 IF KF%=0% THEN SI%=1% ELSE SI%=0%
320 GOTO 40
1000 T%=1%
...

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

Можно заметить, что в режимах ввода с клавиатуры и редактирования над вводимой строкой отсутствует нумерация вводимых байтов, облегчающая установку нужной позиции. Такую нумерацию сделать просто. Для этого нужно ввести строку

7075 ? AT (J%*3%+6%,3%); HEX$(J%)

а в строках 3320, 7020, 7080, 7110, 8000, 8020 номер строки экрана заменить на 5%. Работать станет удобнее.

Заметим, что наша оптимизация рассматриваемой программы не была всеобъемлющей: мы не применяли самый эффективный, но и самый сложный способ оптимизации, касающейся уточнения метода и алгоритма. Часто этот приём приводит к проектированию программ заново, поэтому имея уже работоспособную программу, все программисты прибегают к нему в крайнем случае. В начале нашего совместного пути по программе мы приняли авторскую структуру программы и предложенное им разделение на режимы работы. Теперь выделим читателям для проработки несколько идей.

Во-первых, имеется возможность объединения режимов ввода с клавиатуры и корректировки таблицы прошивки в один экранный режим редактирования. Диапазон адресов в микросхеме ППЗУ можно задавать явно.

Во-вторых, контроль правильности хотелось бы выполнять не только в отдельном режиме, но и непосредственно в цикле прошивки. В этом случае циклическое повторение прошивки необходимо только при обнаружении ошибки. Такое решение позволит сэкономить много времени и обеспечить адаптацию программы к особенностям конкретного корпуса микросхем ППЗУ. Дополнительно при неверной прошивке можно программно увеличивать длительность задержки.

Указанные два момента могут существенно повлиять на работу всей программы, как это обычно и случается при использовании первого способа оптимизации.

Одним из последних штрихов является выбор правильного шага перенумерации. На этом тоже можно сэкономить память БК. В начале работы опытные пользователи выбирают шаг перенумерации строк обычно равным 10, чтобы легко вставлять новые строки. Полуотлаженный вариант программы, особенно при недостатке памяти, можно нумеровать и с шагом 5. В публикациях обычно используют шаг 10.

В заключение нашей работы вставим в начало комментарии с наименованием программы автором и участвовавшими в её совершенствовании читателями. Нумерацию строк программы оставим авторскую, так как при желании команда Бейсик-системы

RENUM 10,1,10

быстро выполнит нумерацию с шагом 10, а авторская нумерация позволяет легче выполнять исправления в исходной программе.

Окончательную версию программы записываем на магнитофон командой CSAVE "PPZU".

Подведём итоги нашей короткой экскурсии в мир оптимизации программ. Благодаря настойчивому труду исходный текст программы для программатора ППЗУ стал существенно короче, разнообразие палитры операторов языка шире, более 5 Кбайт памяти осталось для дальнейшего совершенствования программы, сама работа программы значительно быстрее, а диалог - удобнее и понятнее. К сожалению, таких результатов достичь удаётся далеко не всегда.

Терпеливые читатели, добравшиеся до конца и оптимизировавшие программу вместе с нами, получили достаточное количество информации, чтобы самим оптимизировать собственные разработки. При этом они споткнутся о множество подводных камней, которые мы старательно обходили при первом достаточно поверхностном знакомстве с оптимизацией программ. Хочется надеяться, что их труд не пропадёт даром и программы, публикуемые в выпусках серии, будут гораздо рациональнее.

Прощаясь с внимательным читателем, обладающим чувством юмора, приведём несколько советов.

Полезные советы

  1. Не берите лишнего в памяти! И вообще ничего лишнего не берите! Как мы видели, основной выигрыш по объёму памяти и времени выполнения программы дал в нашем примере правильный выбор типа данных. Ключевой массив D%(63,15) стал целого типа и сэкономил сразу 6 Кбайт памяти. Когда экономия памяти не является главным элементом оптимизации, можно пользоваться принципом умолчания.
  2. Делайте ваш выбор! Выбирайте тщательнее, но быстрее! Языковая структура типа "выбор" (в Бейсике, оператор ON) может сэкономить много операторов IF. Вложенные операторы IF тоже экономят память.
  3. Чем меньше переменных, тем лучше! Введение лишних переменных не только расходует оперативную память, затуманивает алгоритм, но обычно уменьшает и скорость работы программы.
  4. Выносите всё, что можно! Не забудьте только внести обратно главное! Оптимизируя по времени выполнения программу, оптимизируйте тела циклов, вынося из них независимые от переменной цикла выражения.
  5. Не полагайтесь на компьютер - вычисляйте сами всё, что можно вычислить! Подставляйте результаты в программу. Для ясности программы в публикациях этого можно не придерживаться. Закручивайте формулы как можно круче!
  6. Пользуйтесь при необходимости не только десятичными константами! Шестнадцатеричные, восьмеричные и двоичные константы часто экономят память и ускоряют процесс вычисления, делая программу ещё более совершенной.
  7. Оптимизируйте только отлаженные, часто публикуемые и используемые программы, другие сразу после использования бросайте в мусорную корзину! Оптимизация ненужных и неотлаженных программ нужна только для тренировки ваших навыков.
  8. Подбирайте шаг нумерации строк программы. Помните, "шире шаг" - не для Бейсика БК0010.01.
  9. Внимайте тщательно! Оптимизация требует внимания и времени. Тестируйте программу при любых самых незначительных изменениях! Самые очевидные вещи в программировании оказываются при ближайшем рассмотрении очевидно неверными. При первом же случайно выполнившемся прогоне программы считайте её отлаженной и сдавайте заказчику.
  10. Чем больше нетривиальных подсказок в диалоге, тем меньше вопросов у пользователя и оптимальнее интерфейс программы.
  11. Создавая программу для БК0010, примите все меры к тому, чтобы она не прошла на IBM PC/XT/AT. Для этого вставляйте в программу только те операторы языка, которых нет в других диалектах. В крайнем случае врежьте в программу кусок в машинных кодах. Это положит любого пользователя на лопатки, наверняка обеспечит непереносимость программы на другие ЭВМ и минимальное её использование.
  12. Публикуйте оптимальные программы, не проверяя на компьютере. Это избавит вас от сомнений. Читатели заодно и проверят!
1 REM Программа для программатора ППЗУ
2 REM *** БК0010.01 ***
3 REM Автор:
4 REM Р.Барташюс
5 REM Модификация:
6 REM В.Г.Бендаринов
7 REM Л.Н.Жариков
8 REM Г.Мухамедов
9 REM Д.Ю.Усенков 10 REM 1990г.
20 DIM D%(63%,15%)
30 SI%=0%
35 Y%=43% 'Вертикальная координата строки меню
40 CLS
50 CO%=0%
60 KF%=SI%*64%
70 IF KF%=0% THEN ? "К573РФ1(IРФ2)" ELSE ? "К573РФ2(II)"
80 LOCATE 5%,5%,0% 'Убрать курсор
100 ? "Ввод с клавиатуры"
120 ?AT(5%,7%); "Ввод из ППЗУ"
140 ?AT(5%,9%); "Вывод в ППЗУ"
160 ?AT(5%,11%); "Корректировка"
180 ?AT(5%,13%); "РФ1(IРФ2) или IIРФ2"
200 ?АТ(5%,15%); "Контроль"
210 ?AT(5%,17%); "Выход"
220 Y1%=Y%
221 LINE (30%,Y%)-(200%,Y%+20%),1%,B 'Нарисовать рамку темы меню
222 C$=INKEY$
223 IF C$="" THEN 222 ELSE T%=ASC(C$) 'Между кавычками нет пробела
224 IF T%=26% THEN IF Y%>43% THEN Y%=Y%-20% ELSE Y%=163%
225 IF T%=27% THEN IF Y%<163% THEN Y%=Y%+20% ELSE Y%=43%
226 IF T%=10% THEN IF Y%=163% THEN STOP ELSE 230
227 IF Y%<>Y1% THEN LINE (30%,Y1%)-(200%,Y1%+20%),0%,B 'Стереть рамку темы меню
228 GOTO 220
230 LOCATE 1%,1%,1% 'Восстановить курсор
240 ON (Y%-23%)/20% GOSUB 6000,4000,5000,3000
250 IF Y%=123% THEN 310 ELSE IF Y%<>143% GOTO 40
260 CO%=1%
270 GOSUB 4000
280 ?,, "Для возврата в меню-<ввод>" 'Обратите внимание на запятые
290 IF INKEY$="" THEN 290 ELSE 40 'Между кавычками нет пробела
310 IF KF%=0% THEN SI%=1% ELSE SI%=0%
320 GOTO 40
1000 T%=1%
1010 E%=0%
1020 W%=0%
1030 IF LEN(A$)-1% GOTO 1200
1040 Y$=""+MID$(A$,T%,1%)+" " 'В первых кавычках пробела нет
1050 U%=VAL(Y$)
1060 C%=0%
1070 IF U%<>0% THEN C%=U%
1080 IF ASC(Y$)>70 OR U%<>0% OR Y$="О" GOTO 1140
1090 C%=ASC(Y$)-55%
1140 IF T%>1% GOTO 1190
1150 W%=C%
1170 T%=2%
1180 GOTO 1040
1190 E%=W%*16%+C%
1200 RETURN
3000 I%=KF%
3010 CLS
3020 ? "Перемещение:←,→,↓,↑; Замена: С Выход: Q"
3040 GOSUB 7000
3050 X%=0%
3060 K$=INKEY$
3070 IF K$="" THEN 3060 ELSE R%=ASC(K$) 'Между кавычками пробела нет
3080 IF FIX(SQR(R%))=5% THEN ON R%-24% GOTO 3210,3170,3190
3090 IF R%=81% THEN 3360 ELSE IF R%=67% THEN 3140 ELSE IF R%=8% THEN 3270 ELSE 3060
3140 GOSUB 8000
3150 D%(I%-KF%,X%)=E%
3160 GOTO 3340
3170 I%=I%-1%
3180 IF I%<KF% THEN I%=KF% ELSE 3340
3185 GOTO 3060
3190 I%=I%+1%
3200 IF I%>KF%+63% THEN I%=KF%+63% ELSE 3340
3205 GOTO 3060
3210 J%=J%+3%
3220 X%=X%+1%
3230 IF J%<= 51% THEN 3260
3240 J%=51%
3250 X%=15%
3260 GOTO 3320
3270 J%=J%-3%
3280 X%=X%-1%
3290 IF J%>=6% THEN 3320
3300 J%=6%
3310 X%=0%
3320 LOCATE J%,5%
3330 GOTO 3060
3340 ? CHR$(155%)
3350 GOTO 3010
3360 ? CHR$(155%)
3370 RETURN
4000 CLS
4005 ? "ЖДИТЕ..."
4007 K%=KF%*16%+&H8000
4010 FOR I%=0% TO 63%
4015 L%=I%*16%+K%
4020 FOR J%=0% TO 15%
4030 N%=L%+J%
4040 POKE &HFFCC,N%
4050 IF CO%=1% GOTO 4100
4060 D%(I%,J%)=PEEK(&HFFCC)
4070 NEXT J%,I%
4090 RETURN
4100 IF D%(I%,J%)=PEEK(&HFFCC) GOTO 4070
4140 ? "ОШИБКА ПО АДРЕСУ ";HEX$(I%+KF%);HEX$(J%);"H" 'После "у" пробел
4160 GOTO 4070
5000 ? "ЖДИТЕ..."
5005 K%=KF%*16%+2048%
5010 FOR I%=0% ТО 63%
5015 L%=I%*16%+K%
5020 FOR J%=0% ТО 15%
5030 N%=L%+J%
5040 FOR W%=0% ТО 5%
5050 POKE &HFFCC,&H8800
5060 POKE &HFFCC,N%+&H8000
5070 PORE &HFFCC,N%
5080 POKE &HFFCC,D%(I%,J%)+30720%
5090 FOR T=0 TO 50
5100 NEXT T,W%,J%,I%
5110 BEEP
5120 RETURN
6000 FOR I%=KF% TO 63%+KF%
6010 CLS
6020 ? "ВЫХОД: Q"
6030 GOSUB 7000
6050 GOSUB 8000
6070 IF A$="Q" GOTO 3360
6075 GOSUB 1000
6077 IF LEN(A$)=1% GOTO 6090
6080 D%(I%-KF%,(J%-6%)/3%)=E%
6090 J%=J%+3%
6100 IF J%>51% THEN 6110 ELSE 6050
6110 ? CHR$(155%)
6130 NEXT I%
6135 J%=6%
6140 RETURN
7000 ? AT(0%,5%);HEX$(I%);CHR$(155%)
7010 FOR J%=0% TO 15%
7020 ? AT(J%*3%+6%,3%);HEX$(J%) 'Номер байта
7030 ? AT(J%*3%+6%,5%);HEX$(D%(I%-KF%) AND &HFF)
7040 NEXT J%
7050 J%=6%
7060 LOCATE 6%,5%,1%
7070 RETURN
8000 LOCATE J%-1%,5%
8010 INPUT A$
8020 ? AT(J%-1%,5%); " " 'Между кавычками пробел
8030 GOSUB 1000
8040 RETURN

Performed by © gid, 2012-2022.