📂 Документ: lang-basic-v410-03_clean.html


 

Обработка файлов данных Basic V4.10 Орион-128 Пушкова, основы программирования, уроки языка

Как научиться писать программы в Basic V4.10 для Ориона-128 и Ориона-ПРО.

31.03.2023 обновление информации

Basic для Ориона 128 Пушкова v4.10 распределение памяти

Распределение памяти при работе в системе BASIC V4.10

 Обработка файлов данных Basic V4.10 Орион-128

Файлы данных в BASIC "ORION" являются последовательными и имеют текстовый формат, в котором каждая строка заканчивается символом ВК (код 0DH), а в конце текста стоит байт 0FFH. Данные в последовательном (текстовом) файле размещаются в той последовательности, в которой поступают в файл. При чтении такого файла данные становятся доступными в том порядке, в котором они были записаны.
Файл может находиться в одном из трех состояний: закрыт, открыт на чтение, открыт на запись. Интерпретатор допускает открытие одновременно до двух файлов: одного на чтение и одного на запись.

Открытие последовательного файла осуществляется оператором OPEN, имеющим следующий синтаксис:

OPEN "имя",I - открытие файла на чтение;
OPEN "имя",O - открытие файла на запись.

Оператор CLOSE закрывает последовательный файл (файлы). Синтаксис:

CLOSE

10.1. Создание последовательного файла

Для создания последовательного файла необходимо выполнить следующие операции:

- открытие файла для последовательного вывода с помощью оператора OPEN в режиме "O";
- запись данных в файл с помощью оператора PRINT# ;
- закрытие файла оператором CLOSE .

Если файл уже существует, выполнение операции OPEN приведет к возникновению ошибки с кодом 58. Для предотвращения такой ошибки файл необходимо сначала удалить с помощью оператора KILL.

После открытия текстового файла на запись до его закрытия запрещается использовать любые файловые операции, кроме CLOSE, PRINT# (а также INPUT# и LINE INPUT#, если имеется файл, открытый на чтение). Попытка использовать операторы LOAD, MERGE, SAVE, KILL, GET, PUT, FILES, RUN "имя", OPEN, LLIST, LPRINT и
функции EXIST, INP(имя), LOF вызовет ошибку с кодом 55. Такая защита необходима для того, чтобы не нарушить работу подпрограммы OFILE (см. описание ORDOS), с помощью которой производится запись на диск.

Оператор PRINT# может быть использован только в том случае, если файл был открыт на запись. В противном случае возникает ошибка с кодом 54.

Синтаксис оператора PRINT# полностью совпадает с синтаксисом оператора PRINT. Данные записываются в текстовый файл также, как и на экран, за исключением управляющих символов. Символы с кодами, меньшими 0DH, игнорируются, а символ с кодом 0FFH служит признаком конца файла и записывается автоматически при выполнении оператора CLOSE (если в файл был выведен хотя бы один символ).

Если данные впоследствии будут считываться оператором INPUT#, то для их разделения необходимо записывать в файл запятые или символы ВК, а если оператором LINE INPUT# - то только ВК.

При переполнении диска, а также в случае любой другой ошибки или остановке программы с выходом в непосредственный режим автоматически выполняется оператор CLOSE.

Рассмотрим пример программы записи данных в последовательный файл с использованием функции LOF для контроля переполнения диска:

100 PRINT "*** ЗАПИСЬ В ФАЙЛ С КОНТРОЛЕМ ПЕРЕПОЛНЕНИЯ ***"
110 PRINT: F$="PROBA.TX": REM ЗДЕСЬ МОЖНО ЗАДАТЬ ИМЯ ДИСКА
120 IF EXIST(F$) THEN KILL F$
130 REM -- ОПРЕДЕЛЕНИЕ ЗАДАННОГО ВЫХОДНОГО ДИСКА --
140 REM ПОСЛЕ ЛЮБОЙ ФАЙЛОВОЙ ОПЕРАЦИИ УСТАНАВЛИВАЕТСЯ ДИСК,
150 REM УКАЗАННЫЙ В ИМЕНИ ФАЙЛА, ИЛИ ТЕКУЩИЙ ПО УМОЛЧАНИЮ :
160 D$=CHR$(USR(&BFD9))+":" :REM ФУНКЦИЯ ORDOS "RND"
170 IF D$="A:" THEN PRINT "DISK A: - R/O": END
180 REM -- ОПРЕДЕЛЕНИЕ СВОБОДНОГО ОБ'ЕМА ДИСКА --
190 H=&BFFF: IF D$<>"B:" THEN H=&EFFF: REM ГРАНИЦА ДИСКА
200 M=LOF(D$): REM ГРАНИЦА ФАЙЛОВ
210 V=H-M: IF V<0 THEN V=V+65536: REM СВОБОДНО НА ДИСКЕ
220 V=V-16: REM УЧЕТ РЕЗЕРВА ДЛЯ ОГЛАВЛЕНИЯ ФАЙЛА
230 V=V-16: REM УЧЕТ РЕЗЕРВА ДЛЯ СТОП-БАЙТА ДИСКА
240 V=V -1: REM УЧЕТ РЕЗЕРВА ДЛЯ БАЙТА КОНЦА ТЕКСТА
250 REM -- ОТКРЫТИЕ ФАЙЛА НА ЗАПИСЬ --
260 OPEN F$,O: I=0: REM СЧЕТЧИК ВЫВОДИМЫХ СИМВОЛОВ
270 S$="КОНТРОЛЬ ПЕРЕПОЛНЕНИЯ ДИСКА "+D$: REM СТРОКА
280 I=I+LEN(S$)+1: REM СУММАРНАЯ ДЛИНА С УЧЕТОМ <ВК>
290 IF I>V THEN 320: REM ДИСК БУДЕТ ЗАПОЛНЕН
300 PRINT# S$: REM ЗАПИСЬ ОЧЕРЕДНОЙ СТРОКИ С <ВК> В КОНЦЕ
310 PRINT "."; : GOTO 280: REM ОТОБРАЖЕНИЕ ХОДА ЗАПИСИ
320 CLOSE: PRINT
330 PRINT "ПЕРЕПОЛНЕНИЕ ДИСКА ";D$;" НА";I-V;"БАЙТ !"
340 END

Пример программы, создающей последовательный файл на основании данных, вводимых с клавиатуры:

100 REM -- СОЗДАНИЕ ПОСЛЕДОВАТЕЛЬНОГО ФАЙЛА --
110 FO$="LIST.DT": IF EXIST(FO$) THEN KILL FO$
120 OPEN FO$,O: CLS: I=1
130 PRINT "ВВЕДИТЕ ДАННЫЕ О";I;CHR$(8);"-М СОТРУДНИКЕ"
140 LINE INPUT "ФАМИЛИЯ, ИМЯ, ОТЧЕСТВО: ",N$
150 IF LEN(N$)=0 THEN 200: REM ОТКАЗ ОТ ВВОДА
160 LINE INPUT "ДОЛЖНОСТЬ: ",J$
170 INPUT "ВОЗРАСТ, СТАЖ РАБОТЫ: ",A,B
180 PRINT# N$: PRINT# J$: PRINT# A;",";B
190 PRINT: I=I+1: GOTO 130
200 CLOSE

10.2. Обработка последовательного файла

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

- открытие файла для последовательного ввода с помощью оператора OPEN в режиме "I";
- чтение данных из файла с помощью операторов INPUT# и LINE INPUT# ;
- закрытие файла оператором CLOSE .

Если при выполнении оператора OPEN файл с указанным именем не будет найден, возникнет ошибка с кодом 53.

После открытия файла на чтение допускаются все файловые операции, кроме KILL. Закрытие файла с помощью CLOSE необязательно. Если необходима работа одновременно с двумя файлами, то сначала необходимо открыть файл на чтение, а потом на запись.
Оператор CLOSE в конце записи закроет оба файла.

Как правило, при обработке последовательного файла необходимо предусмотреть проверку конца файла. Такая проверка выполняется с помощью функции EOF. Попытка прочесть данные после возникновения ситуации "конец файла" приведет к ошибке с кодом 62.

Синтаксис:

EOF(1)

Для ввода данных из файла предусмотрены операторы INPUT# и LINE INPUT#.
Синтаксис:

INPUT# переменная [,переменная]...
LINE INPUT# переменная [,переменная]...

Оператор INPUT# воспринимает данные так же, как и оператор INPUT. Тип вводимых данных должен соответствовать типу переменной. Элементы данных должны располагаться в файле в такой же последовательности, в какой они появлялись бы в случае ввода с клавиатуры. При вводе числовых данных все пробелы игнорируются, а концом числа считается запятая или символ ВК. Если интерпретатор считывает строку символов, и ее первым символом являются кавычки ("), то в состав строки входят все символы до следующих кавычек. Если первый символ строки отличен от кавычек, то строка будет заканчиваться с появлением запятой, двоеточия, символа ВК или признака конца файла 0FFH, а также если будет прочитано 253 символа.

Оператор LINE INPUT# предназначен для чтения из файла строки символов аналогично оператору LINE INPUT. Он выполняет чтение данных до тех пор, пока не будет встречен символ ВК, конец файла, или длина строки не достигнет 253 символов. Не допускается использовать операторы INPUT#, LINE INPUT# и функцию EOF, если файл не открыт на чтение. Невыполнение этого условия приведет к ошибке с кодом 54.

Пример программы обработки последовательного файла, созданного предыдущей программой:

300 REM -- ОБРАБОТКА ПОСЛЕДОВАТЕЛЬНОГО ФАЙЛА --
310 FI$="LIST.DT": IF NOT EXIST(FI$) THEN END
320 OPEN FI$,I: CLS: I=1
330 PRINT "-- ДАННЫЕ О";I;CHR$(8);"-М СОТРУДНИКЕ --"
340 IF EOF(1) THEN 400
350 LINE INPUT# N$,J$: INPUT# A,B
360 PRINT "ФАМИЛИЯ, ИМЯ, ОТЧЕСТВО: ";N$
370 PRINT "ДОЛЖНОСТЬ: ";J$
380 PRINT "ВОЗРАСТ: ";A;" СТАЖ РАБОТЫ: ";B
390 PRINT: I=I+1: GOTO 330
400 CLOSE

Таким образом, имеется возможность создания простых баз данных и обмена данными между программами.

11. Связь с печатающим устройством

Вывод на принтер осуществляется при наличии на диске B: или A: драйвера печатающего устройства под именем LPT. Ему выделяется область памяти, начиная с адреса 0A800H. Соглашения для драйвера LPT стандартные: адрес подпрограммы печати символа из регистра (C) совпадает с адресом начала драйвера, а адрес подпрограммы опроса готовности принтера - на 3 байта больше. Признак "NZ", возвращаемый последней подпрограммой, свидетельствует о том, что принтер готов.
Для нормального вывода символов в операторах LLIST и LPRINT драйвер LPT должен работать в кодировке КОИ-7 (отсекать старший разряд кода символа). Однако, следует учитывать, что для возможности печати оператором LPRINT в графическом режиме (со старшим битом) необходимо сменить драйвер LPT или использовать универсальный, позволяющий программно (с помощью комбинаций АР2) переходить от одной кодировки к другой.

При вызове команд LLIST, LPRINT и функции INP(-1) интерпретатор проверяет признак загрузки файла LPT.
Если файл LPT не загружен, то при обращении к печатающему устройству он считывается с диска B: или A:, и интерпретатор устанавливает признак его загрузки. После этого на принтер выдается строка инициализации, и выполняется обращение к драйверу LPT, размещенному в ОЗУ. Повторная загрузка файла LPT и инициализация принтера произойдет при очередном обращении к драйверу, если признак его загрузки окажется сброшенным. Признак загрузки файла LPT сбрасывается при выполнении команды LOAD для файла с произвольным типом, а также при запуске одной из оверлейных программ (ERMBS$ или MNUBS$).

Обычно в интерпретаторах для указания ширины печати используется оператор WIDTH LPRINT "ширина", а для определения позиции печатающей головки - функция LPOS. В описываемой версии Бейсика тоже есть такие средства, но выглядят они по-другому. Ширина печати (0..255 символов) задается в ячейке с адресом 0007H с помощью оператора POKE 7,"ширина". При значении 0 печать происходит без ограничения ширины (этому случаю соответствует оператор WIDTH LPRINT 255).
Текущая позиция печатающей головки отслеживается функцией POS(-1) и находится в пределах 0.."ширина"-1.

При печати символа 08H (шаг влево) положительное значение POS(-1) уменьшается, а при печати символа 0DH (ВК) - обнуляется. Прочие управляющие символы величину POS(-1) не меняют, а символы с кодами, большими 1FH - увеличивают. После достижения POS(-1) последней заданной позиции в печатаемую строку вставляются символы ВК,ПС.  Необходимо помнить, что использование ESC-последовательностей для управления принтером может внести несоответствие между POS(-1) и позицией печатающей головки. Кроме того, при переводе принтера в режим графики принятое понятие ширины печати теряет смысл. В этом случае для исключения вставки в строку ненужных символов ВК,ПС в ячейку 0007H надо записать значение 0. Имя файла LPT и строка инициализации принтера могут быть изменены при настройке интерпретатора.

12. Размещение данных в памяти

Функция VARPTR возвращает адрес размещения указанной переменной.
Синтаксис:

VARPTR(переменная)

Значения адресов, больших 32767 (&7FFFH), представляются в дополнительном коде. Результаты функции VARPTR могут использоваться для копирования и преобразования данных программой на Бейсике или подпрограммами в машинных кодах.

Рассмотрим особенности размещения данных в памяти.

Переменные располагаются сразу за текстом программы в виде двух таблиц: таблицы неиндексированных переменных (назовем ее таблицей идентификаторов) и следующей за ней таблицы массивов. На каждую переменную в таблице идентификаторов выделяется по 6 байт: 2 байта для хранения ее имени и 4 байта - для значения,
а на каждый элемент массива - по 4 байта дла хранения значения. Значения числовых переменных (массивов) представляются в двоичном формате с плавающей запятой:

1 байт - младший байт мантиссы
2 байт - средний байт мантиссы
3 байт - старший байт мантиссы со знаковым разрядом
4 байт - смещенный порядок числа

и определяются следующим образом:

0.мантисса * 2 ^ (смещенный порядок-80H)

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

Число представляется в нормализованной форме, т.е. старший бит мантиссы всегда равен 1. Это обстоятельство используется для хранения знака числа - он записывается вместо старшего бита мантиссы, причем 0 соответствует знаку плюс, 1 - знаку минус.

Примеры плавающего формата некоторых чисел:

0 00 00 00 00
0.5 00 00 00 80
1 00 00 00 81
2 00 00 00 82
0.25 00 00 00 7F
-1 00 00 80 81
0.1 CD CC 4C 7D

Для каждой строковой переменной (элемента массива) в таблице также выделяется 6 байт, но там хранится указатель строки:

1 байт - длина строки
2 байт - 00H
3 байт - младший байт адреса начала строки
4 байт - старший байт адреса начала строки

Выделение места в таблице идентификаторов (массивов) для переменной происходит при первом обращении к ней. Если значение переменной еще не определено, то в таблицу заносится 4 нулевых байта как для числовых, так и для строковых переменных.

При выполнении операции присваивания значения строковой переменной адрес строки определяется следующим образом. Если строка находится в тексте программы (например 10 A$="СТРОКА" ), то в указатель строки заносится адрес, соответствующий ее началу тексте. Если же строка вводится с клавиатуры или вычисляется в процессе выполнения программы (например A$=A$+"*"), то предварительно для нее выделяется место в буфере символьных строк, где она и размещается. В этом случае в указатель строки записывается ее адрес в буфере.

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

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

Для строковой переменной VARPTR возвращает действительный адрес начала строки в памяти, а не адрес ее указателя в таблице. При этом, если строковая переменная в таблице отсутствует, то происходит выдача сообщения об ошибке, так как адрес начала строки не определен.

Ниже приводится пример программы, осуществляющей одновременно чтение и запись для преобразования текстового файла из альтернативной кодировки в КОИ-7. Для определения адреса строки, считанной из файла, с целью ее посимвольной обработки используется функция VARPTR.

10 CLS: PRINT "*** ПЕРЕКОДИРОВКА ТЕКСТА ALT -> КОИ-7 ***"
20 PRINT "WAIT!";: REM ФОРМИРОВАНИЕ МАССИВА ПЕРЕКОДИРОВКИ
30 DIM T(255): RESTORE 120: FOR I=0 TO 255
40 IF I>&AF AND I<&E0 OR I>&EF THEN T(I)=&20: GOTO 110
50 IF I=&A0 THEN RESTORE 120: GOTO 100
60 IF I=&E0 THEN RESTORE 140: GOTO 100
70 IF I<&60 THEN T(I)=I: GOTO 110
80 IF I=&60 THEN T(I)=&27: GOTO 110
90 IF I<&80 THEN T(I)=I-&20: GOTO 110
100 READ T(I)
110 NEXT: PRINT CHR$(13);" "
120 DATA &61, &62, &77, &67, &64, &65, &76, &7A
130 DATA &69, &6A, &6B, &6C, &6D, &6E, &6F, &70
140 DATA &72, &73, &74, &75, &66, &68, &63, &7E
150 DATA &7B, &7D, &27, &79, &78, &7C, &60, &71
160 REM -- ВЫБОР ИМЕН ФАЙЛОВ --
170 LINE INPUT "ВВЕДИТЕ ИМЯ ИСХОДНОГО ФАЙЛА: ",FI$
180 IF LEN(FI$)_=0 THEN END:ELSE IF LEN(FI$)>10 THEN 170
190 IF EXIST(FI$) THEN 210
200 PRINT "ФАЙЛ ";FI$;" НЕ НАЙДЕН !": GOTO 170
210 LINE INPUT "ВВЕДИТЕ ИМЯ ВЫХОДНОГО ФАЙЛА: ",FO$
220 IF LEN(FO$)=0 THEN END:ELSE IF LEN(FO$)>10 THEN 210
230 IF NOT EXIST(FO$) THEN 280
240 PRINT "ФАЙЛ ";FO$;" СУЩЕСТВУЕТ! ПЕРЕПИСАТЬ ? (Y/N): ";
250 A=INP(0): IF A<>&59 AND A<>&79 THEN PRINT "N": GOTO 210
260 PRINT "Y": KILL FO$
270 REM -- ОТКРЫТИЕ ФАЙЛОВ --
280 OPEN FI$,I: OPEN FO$,O: CLS
290 REM -- ЧТЕНИЕ СТРОКИ ИСХОДНОГО ФАЙЛА --
300 IF EOF(1) THEN 380: ELSE LINE INPUT# S$
310 IF LEN(S$)=0 THEN 370
320 REM -- ПЕРЕКОДИРОВКА СТРОКИ --
330 A=VARPTR(S$): REM АДРЕС НАЧАЛА СТРОКИ
340 FOR I=A TO A+LEN(S$)-1
350 POKE I,T(PEEK(I)): NEXT
360 REM -- ЗАПИСЬ СТРОКИ В ВЫХОДНОЙ ФАЙЛ --
370 PRINT# S$: PRINT S$: GOTO 300
380 CLOSE: END

13. Обработка ошибок

При возникновении ошибки в программном режиме интерпретатор прерывает выполнение программы и выводит код ошибки с номером соответствующей строки. В непосредственном режиме выводится только код ошибки.
Коды ошибок соответствуют стандарту BASIC IBM PC [3]. Перечень ошибок, выдаваемых данной версией интерпретатора, приведен здесь. Чтобы избавить пользователя от необходимости запоминать коды ошибок или каждый раз заглядывать в таблицу, в интерпретаторе предусмотрена возможность внешней подзагрузки текстов полных сообщений об ошибках.

В случае ошибки Бейсик ищет на дисках B: и A: файл с именем ERMBS$ (от ERror Messages - сообщения об ошибках), и, если он найден, производится его запуск, в противном случае - обычная выдача кода ошибки.
Программа ERMBS$ получает внутренний код ошибки в регистре микропроцессора (E) в пределах 0FFH,00..1AH и выводит на экран требуемое сообщение.
Имя файла ERMBS$ может быть изменено при настройке интерпретатора. Адрес "посадки" равен 0A800H. В конце имени файла обязательно должен быть символ "$".

14. Настройка интерпретатора

По следующим адресам интерпретатора находятся настроечные константы, которые можно изменять по усмотрению пользователя:

0007: DB 40H ; Ширина печати 0..255

0045: DB 0,0 ; Позиция курсора X, Y для
; вывода номера строки в ре-
; жиме трассировки (TRON).
; Для нормального вывода но-
; мера позиция X не должна
; превышать 3AH (58), Y -
; 18H (24).

0047: DB 0FH ; Начальный цвет экрана
0048: DB 'ERMBS$ ' ; Имя файла ошибок
0050: DB 'LPT ' ; Имя драйвера LPT
0058: DB 18H,1BH,40H,0,0,0,0,0;Строка инициализации принтера. Не должна содержать ; кодов, больших 7FH. Признак конца строки - байт 0.
0060: DB 'MNUBS$ ' ; Имя файла Меню

Для внесения изменений можно воспользоваться программой M128.

Текст подготовил Пушков

 

Программирование микропроцессорных комплектов i8080, 580вм80, z80, i8085, 1810, 1824

Орион-128 описание команд микропроцессора к580вм80 (Орион-Софт)

Язык Ассемблера для Ориона

Язык Си для Ориона

Язык Паскаль для Ориона

Язык Форт для Ориона

 

 

 

Полезные и интересные статьи

На предыдущую страницу  На главную страницу  На следующую страницу