А.П.Гармашов, программист

О текстах подпрограмм в кодах для БЕЙСИКа БК 0010

Загрузку программ в машинных кодах при работе с БЕЙСИКом на ПЭВМ БК-0010 обычно выполняют либо командой Бейсик-системы BLOAD, либо помещают тексты машинных кодов в операторы DATA, а оттуда - по нужным адресам. Перевод текста программы в кодах в операторы DATA для Бейсик-программы выполняется вручную.

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

Для пояснения работы программы сначала рассмотрим особенности интерпретатора ПЭВМ БК-0010 - интерпретатора "компилирующего типа", хранящего во время выполнения программы исходный текст и исполняемый модуль. Исходный текст начинается с адреса &O3052, причём строки программы хранятся без номеров и не всегда в порядке их следования в программе. Сначала расположена наиболее "старая" строка с учётом исправлений текста, а последней - последняя введённая или изменённая строка. В начало строки добавляется символ с кодом 0, если только она не начинается с зарезервированного слова БЕЙСИКа. В этом случае код 0 не добавляется, а слово заменяется внутренним кодом БЕЙСИКа. Например, для оператора DATA код &O100 (символ В конец строки всегда добавляется признак конца строки - символ с кодом &O12. Номера строк хранятся отдельно в виде упорядоченного по возрастанию номеров списка, начиная с адреса &O36754 в направлении уменьшения адресов. Для каждой строки программы выделено три слова. В слове со старшим адресом записан номер строки, затем адрес начала "тела" строки и адрес внутри исполняемого модуля (если программа уже транслировалась), иначе в третье слово записан 0. Отметим, что для Бейсик-системы важна информация в слове по адресу &O2024.

Там хранится текущее значение указателя на конец списка строк (адрес последнего занятого слова в списке). До ввода текста программы это &O36756.

Теперь можно рассмотреть непосредственно текст программы.

5 CLEAR 240
10 ? CHR$(140)+CHR$(140);
20 DATA &O12501, &O11502, &O13703, &O352, &O112223, &O77102, &O10337, &O352, &O207
30 DATA &O11505, &O4737, &O100536, &O207
40 DEF FNC$(X%)=MID$(STR$(X%),2%,LEN(STR$(X%))-2%)
50 DEF USR1=&O400
60 DEF USR2=&O422
70 FOR I%=0 ТО 12
80 READ J%
90 POKE &O400+2%*I%,J%
100 NEXT
110 B$=CHR$(159)
120 ? B$+"ГЕНЕРАТОР USR П/П ДЛЯ БЕЙСИКА"
130 ? "РЕЗУЛЬТАТЫ: "+B$+"1-DEC, 2-ОСТ, 3-HEX ?";
140 T$=INKEY$
150 IF T$<"1" OR T$> "3" THEN 140
160 ? T$
170 ? "ЗАГРУЗКА П/П В КОДАХ"
180 A%=USR2(&O42000)
190 CN%=0
200 РОКЕ &O352,&O3052
210 TB%=&O36754
220 JJ%=&O42000+PEEK(&O266)
230 J%=0
240 IF J% MOD 10%<>0% THEN 300
250 A$=""+"@"
260 CN%=CN%+10%
270 POKE TB%,CN%
280 POKE TB%-2%,PEEK(&O352)
290 TB%=TB%-6%
300 AD%=&O42000+2%*J%
310 R%=PEEK(AD%)
320 IF T$="1" TH B$=""+FNC$(R%)
330 IF R%<0% THEN B$=""+"-"+B$
340 IF T%="2" THEN IF R%<8% AND R%>=0% THEN B$=""+FNC$(R%) ELSE B$=""+"&O"+OCT$(R%)
350 IF T%="3" THEN IF R% < 10% AND R% >=0% THEN B$=""+FNC$(R%) ELSE B$=""+"&H"+HEX$(R%)
360 A$=""+A$+B$
370 IF(J%+1%) MOD 10%<>0% AND JJ%-AD%>=0% THEN 420
380 A$=""+A$+CHR$(10%)
390 P$=USR1(A$)
400 A$=""
410 IF JJ%-AD%>=0% THEN 430 ELSE 450
420 A$=""+A$+","
430 J%=J%+1%
440 GOTO 240
450 POKE &O2024,TB%+2%
460 CLS

Строка 10 - начальная установка экрана. Начало служебной строки после этого всегда имеет адрес &O40000. В строках 20 и 30 - 2 функции в кодах. Они определены в строках 60, 70. Функция USR1 копирует содержимое символьной переменной (параметра), помещая копию с адреса, записанного в &O352. После этого &O352 указывает на первый свободный байт за копией. Функция USR2 вызывает программу монитора чтения с магнитофона. Параметр подпрограммы типа INTEGER указывает на начальный адрес загрузки.

После запроса имени загружаемой программы в кодах в строке 180 указан начальный адрес &O42000 (в качестве буфера используем экран). Переменная CN% - счётчик строк генерируемого текста. Он изменяется через 10. В строке 200 для функции USR1 задаётся начальный адрес, куда будут помещаться строки программы (без номеров). С адреса TB% = &O36754 в сторону уменьшения адресов формируется список вида: номер строки, её адрес, затем пропускаем одно слово, номер следующей строки и т.д. В строках 240-440 в цикле считываются коды из буфера (экрана), формируется строка с оператором DATA и текстом кодов через запятую. Размер исходной программы в кодах читается из &O266.

При формировании строки вместо DATA записывается символ '@', а в конце строки добавляется символ с кодом &O12. В зависимости от выбора основания системы счисления (10,8,16) в строках 310-360 получается текст считанного в строке 310 машинного слова. Определённая в 40 функция FNC$ удаляет пробелы в начале и конце строки символов, получаемых функцией STR$. Но при отрицательном аргументе символ '-' будет потерян. Строка 330 добавляет '-' для этого случая. После накопления десяти команд в DATA либо окончания обработки всего буфера в строках 370-410 готовые строки по USR1 записываются, причём &O352 всегда указывает на следующий свободный байт. В строках 290-300 эта информация заносится в список строк Бейсик- программы. По завершении генерации управление передаётся в строку 450 для записи адреса конца списка строк в &O2024.

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

10 AA$ = "12345..."

В этой строке форматируется символьная переменная, которая будет использована для хранения подпрограммы. Длина переменной - не меньше длины программы в кодах. Этой записи с адреса &O3052 будут соответствовать коды: 0, потом текст AA$ = ", содержимое переменной, " и код 12. Содержимое переменной AA$ записано с адреса &O3060 (имя состоит из двух символов и взято для того, чтобы этот адрес был чётным, т.е. границей слова). С этого адреса можно загружать программу в кодах, например, с помощью USR2, описанной выше, или просто операторами POKE. В результате строка 10 будет содержать необходимую информацию, а функцию пользователя определяем с адреса &O3060. Изображение текста строки на экране имеет своеобразный вид. Теперь эту строку можно использовать в Бейсик-программах. Существенными ограничениями для такого способа размещения программы являются:

Таким образом, несмотря на компактность, этот способ может иметь ограниченное применение в основном для коротких программ. Любопытными могут быть побочные эффекты при отображении на экране текста программы с такой строкой. Например, при размещении кодов из строки 30 в символьной переменной соответствующая строка видна на экране в виде двух символов, а если разместить слово &O112414, то на экране по команде LIST вообще будет только графический курсор.

Программа - генератор текстов операторов DATA, описанная в статье, имеет ограничение: длина программы в кодах (исходные данные для генератора) не должна быть более &O212. Опыт работы показал, что при больших размерах начинаются сбои при формировании переменной A$.

Кроме того, привожу краткое описание ещё одной программы, на этот раз в кодах.

Печать строк при выполнении программы на БЕЙСИКе БК 0010.

Команда LIST БК 0010 не реализована при работе в программном режиме. Предлагается программа в кодах для вывода на экран строк Бейсик-программы во время выполнения. Программа оформляется как функция пользователя USR и может загружаться с любого адреса.

Параметр функции - номер вводимой строки (целое число).

013701 002026 024115 001405 020137 002024 003420 024141
000771 014103 105723 001407 012702 133400 153102 011201
012702 020337 104020 010301 012702 005377 104020 000207

 

Performed by © gid, 2012-2022.