А.В. Алексеев (г. Ленинград)
О ТЕКСТАХ ПОДПРОГРАММ В КОДАХ
Меня заинтересовала статья А.П. Гармашова "О текстах подпрограмм в кодах для БЕЙСИКа БК 0010.01". Однако, как подметил автор статьи, программа имеет ряд недостатков: длина исходной подпрограммы в машинных кодах должна быть не более &O212, а также программа генерации теряется. Все эти недостатки можно устранить, применив другой принцип для построения программы, как мне кажется, более простой и очевидный. Применив этот принцип, я разработал две программы, отличающиеся друг от друга лишь степенью сервиса (вторая программа имеет более удобный интерфейс к пользователю). Из программы автора статьи я позаимствовал лишь подпрограмму USR2 - вызова процедуры монитора чтения файла с магнитной ленты и идею буферизации подпрограммы в кодах в экранной области ОЗУ.
Теперь более подробно о принципе, который положен в основу моей программы. Как известно из руководства по языку БЕЙСИК (1986.07.24), файлы данных записываются на магнитную ленту в формате кодов ASCII, так же, как и текстовые файлы программ, записанные командой SAVE. Из этого можно сделать следующий вывод: Бейсик-программы можно создавать средствами символьных функций Бейсик-программы, накапливая строки создаваемой программы в символьном массиве (каждый элемент массива - строка создаваемой программы). Затем можно с помощью операторов работы с файлами данных записать этот массив на магнитную ленту. Соответствующий фрагмент программы будет выглядеть следующим образом:
OPEN R$+'.ASC' FOR OUTPUT FOR I%=1% TO V% ? # A$(I%) NEXT I% CLOSE
где R$ - символьная переменная, содержащая имя файла; V% - размер символьного массива; A$(N) - символьный массив, содержащий строки создаваемой программы.
Далее записанную программы можно считать с магнитной ленты командой LOAD, дополнить её необходимыми операторами и скомпилировать подпрограмму в кодах, как в программе автора статьи.
Мною были написаны две программы: одна максимально минимизированная и позволяющая генерировать большие программы, другая - предоставляющая пользователю ряд удобств в работе с ней и занимающая больше места в памяти, хотя я предпринял все меры по сокращению памяти, занимаемой программой генерации.
Теперь рассмотрим более подробно каждую из программ. Разбор начнём с первой, короткой программы. Операторы в строках 10 и 20 устанавливают размер памяти, выделяемой под хранение строк генерируемой программы. В строках 30 - 70 загружается и определяется программа в машинных кодах, вызывающая процедуру чтения файла с магнитной ленты. Затем производится очистка экранной памяти, загрузка упаковываемой подпрограммы в машинных кодах в экранное ОЗУ с адреса &O42000. Далее в строках 130 - 230 происходит формирование очередной строки генерируемой программы. Причём каждая строка содержит: номер, оператор DATA и восемь чисел. Оператор в строке 240 удаляет последнюю запятую в последней неполной строке. Если строка полная, то после последнего числа нет запятой (см. строку 200). Потом полученный символьный массив записывается на магнитную ленту в файле с расширением .ASC'. В конце программа запрашивает пользователя о дальнейших действиях. Вторая программа содержит первую в качестве одной из подпрограмм. Выбор требуемой функции осуществляется с помощью меню. Курсор перемещается вверх и вниз с помощью двух клавиш 'курсор вверх' и 'курсор вниз' и устанавливается на необходимую строку. По нажатии клавиши 'ВВОД'(ВК) осуществляется переход на необходимую подпрограмму. С помощью второй программы можно кроме упаковки подпрограмм в кодах распечатать сгенерированную программу на экран или принтер записать программу на магнитную ленту.
Обе программы были мною проверены на подпрограмме, реализующей команду MERGE (ВТ и её применение. - № 4. - 1990.), которой я пользовался до создания моих программ. Я решил добиться аналогичного результата с помощью программы генерации. Последовательность действий при проверке была такая:
- С помощью отладочного монитора я записал в память подпрограмму с адреса &O1000 и директивой М3 вывел её на магнитную ленту.
- Отключив блок МСТД, запустил БЕЙСИК и загрузил свою программу генерации.
- Загрузил подпрограмму в кодах, которая моей программой была упакована в операторы DATA.
- Вывел сгенерированную программу на магнитную ленту.
- Считал сгенерированную программу командой LOAD, дополнил её необходимыми операторами и скомпилировал.
Подпрограмма оказалась полностью работоспособной. Я думаю, что эти две программы генерации окажутся полезными пользователям БК, использующим подпрограммы в машинных кодах.
Программа 1
10 CLEAR 2000 'Выделение памяти под массив 20 DIM А$(30) 'Объявление массива 30 РОКЕ &O400,&O11505 'Загрузка 40 РОКЕ &O402,&O4737 'подпрограммы 50 РОКЕ &O404,&O100536 'вызова п/п 60 РОКЕ &O406,&O207 'загрузки файла 70 DEF USR=&O400 'её определение 80 ? CHR$(140)+CHR$(140); 'Очистка ОЗУ экрана 90 А%=USR(&O42000) 'Вызов п/п загрузки 100 DL%=&O42000+PEEK(&O266) 'Нач.адр. считывания+длина файла 110 С%=&O42000 'Адрес первого упаковываемого маш. слова 120 I%=10% 'Номер первой строки генерир.программы 130 V%=I%\10% 'Индекс элемента символьного массива 140 A$(V%)="" 'Очистка очередного элемента массива 150 A$(V%)=""+MID$(STR$(I%),2%,LEN(STR$(I%)))+"DATA " 160 FOR J% =1% TO 8% 'Цикл формирования очередной строки 170 A$(V%)=""A$(V%)+"&O"+OCT$(PEEK(C%)) 'генерируемой 180 IF J%<8% THEN A$(V%)=""+A$(V%)+"'" 'программы 190 C%=C%+&O2 'Адрес следующего машинного слова 200 IF С%>DL% THEN 240 'Если все слова прочитаны то на выход 210 NEXT J% 220 I%=I%+10%" 'Номер следующей строки 230 GOTO 130 'Идти на формирование новой строки 240 IF J%<8 THEN A$(V%)=""+MID$(A$(V%),1%,LEN(A$(V%))-1) 250 CLS 260 R$="" 270 INPUT "ИМЯ ФАЙЛА";R$ 280 ? "ВКЛЮЧИ МАГНИТОФОН." 290 IF INKEY$="" THEN 290 300 OPEN R$+".ASC" FOR OUTPUT 'Запись 310 FOR J%=1 TO V% 'Массива 320 PRINT # A$(J%) 'на 330 NEXT J% 'магнитную ленту 340 CLOSE 350 INPUT "БУДЕТЕ ПРОДОЛЖАТЬ",U$ 'Запрос о дальнейших действиях 360 IF U$="D" OR U$="Д" THEN 80 370 CLS 380 END
Программа 2
10 REM ПРОГРАММА УПАКОВКИ П/П В КОДАХ В ОПЕРАТОРЫ 'DATA' 20 REM АЛЕКСЕЕВ А.В. 1.10.1990. БЕЙСИК-БК 30 CLEAR 2000 40 DIM А$(30) 50 РОКЕ &O400,&O11505 60 РОКЕ &O402,&O4737 70 РОКЕ &O404,&O100536 80 РОКЕ &O406,&O207 90 DEF USR=&O400 100 CLS 110 ? АТ(0,6)"ЗАГРУЗКА И УПАКОВКА П/П <=/*" 'Печать меню 120 ? АТ(0,8)"РАСПЕЧАТКА НА ЭКРАН <=/*" 130 ? АТ(0,10)"РАСПЕЧАТКА НА ПРИНТЕР <=/*" 140 ? АТ(0,12)"ЗАПИСЬ НА МАГНИТОФОН <=/*" 150 ? АТ(0,14)"ВЫХОД <=/ *" 160 LINE (0,50)-(245,157),3,B 'Рамка меню 170 Y%=6% 180 LOCATE 29%,Y%,1% 'Высвечивание курсора 190 Т$=INKEY$ 'Считывание символа с клавиатуры 200 IF Т$="" THEN 190 210 Т%=ASC(T$) 'Определение кода символа 220 LOCATE 29%,Y%,0% 'Гашение курсора 230 IF Т%=26% THEN 270 'Переход на 240 IF Т%=27% THEN 310 'соответствующую программу в 250 IF Т%=10% THEN 350 'зависимости от нажатой клавиши 260 GOTO 180 270 Y%=Y%-2% 'П/п движения курсора вверх 280 IF Y%=4% THEN BEEP ELSE 300 290 Y%=6% 300 GOTO 180 310 Y%=Y%+2% 'П/п движения курсора вниз 320 IF Y%=16% THEN BEEP ELSE 340 330 Y%=14% 340 GOTO 180 350 ON Y%\2%-2% GOTO 360,660,750,800,920 'П/п перехода на требуемую функцию 360 CLS 'П/п упаковки п/п в машинных кодах 370 ? АТ(8,0)"ФОРМАТ УПАКОВКИ" 380 ? АТ(13,2)"1-ОСТ" 390 ? АТ(13,3)"2-НЕХ" 400 ? AT(13,4)"3-DEC" 410 В$=INKEY $ 420 IF В$=""THEN 410 430 IF B$<"1" OR B$>"3" THEN 360 440 ? CHR$(140)+CHR$(140); 450 LOCATE 0%,10% 460 A%=USR(&O42000) 470 DL%=&O42000+PEEK(&O266) 480 C% = &O42000 490 I%=10% 500 V%=I%\10% 510 A$(V%)="" 520 A$(V%)=""+MID$(STR$(I%),2%,LEN(STR$(I%)))+"DATA " 530 FOR J%=1% TO 8% 540 D%=PEEK(C%) 550 IF B$="1" THEN A$(V%)=""+A$(V%)+"&O"+OST$(D%) 560 IF B$="2" THEN A$(V%)=""+A$(V%)+"&H"+HEX$(D%) 570 IF B$="3" THEN IF D% <0% THEN A$(V%)=""+A$(V%)+MID$(STR$(D%),1%,LEN(STR$(D%))-1)+"%" ELSE A$(V%)=""+A$(V%)+MID$(STR$(D%),2%,LEN(STR$(D%))-2)+"%" 580 IF J%<8% THEN A$(V%)=""+A$(V%)+"," 590 C%=C%+&O2 600 IF C%>DL% THEN 640 610 NEXT J% 620 I%=I%+10% 630 GOTO 500 640 IF J%<8% THEN A$(V%)=""+MID$(A$(V%),1%,LEN(A$(V%))-1) 650 GOTO 100 660 CLS ' П/п печати сгенерированной программы на экран 670 FOR J%=1% ТО V% 680 ? A$(J%) 690 IF CSRLIN<22 THEN 720 700 IF INKEY$="" THEN 690 710 CLS 720 NEXT J% 730 IF INKEY$="" THEN 730 740 GOTO 100 750 CLS 'П/n печати сгенерированной программы на принтер 760 FOR J%=1% ТО V% 770 LPRINT A$(J%) 780 NEXT J% 790 GOTO 100 800 CLS 'Запись сгенерированной программы на магнитную ленту 810 R$="" 820 LOCATE 0%,10% 830 INPUT "ВВЕДИТЕ ИМЯ ФАЙЛА";R$ 840 ? "ВКЛЮЧИТЕ МАГНИТОФОН И НАЖМИТЕ ЛЮБУЮ КЛАВИШУ" 850 IF INKEY$="" THEN 850 860 OPEN R$+".ASC" FOR OUTPUT 870 FOR J%=1% TO V% 880 PRINT # A$(J%) 890 NEXT J% 900 CLOSE 910 GOTO 100 920 CLS 'Очистка экрана 930 END 'и выход из программы