Форматы хранения файлов
Форматы хранения бейсик-программы и кодового файла не отлича-
ются от аналогичных для магнитофона. Бейсик-программа и переменные
хранятся в едином бейсик-файле. Отделить текст программы и выделить
переменные позволяют соответствующие параметры из элемента каталога.
Несколько необычно хранится номер строки автостарта бейсик-программы.
В конец каждого бейсик-файла TR-DOS дописывает 4 байта (они не входят
в общую длину бейсик-программы и переменных). Первые два байта фик-
сированы: #80 и #АА, вторые — собственно номер строки автостарта
(сначала хранится младший байт, затем старший). Номер строки автостарта
выводится при распечатке каталога командой LIST под словом Line.
Для числовых и строчных массивов в TR-DOS выделен один и тот же
тип файла (<D>), и каких-нибудь специальных отличий, позволяющих
определить тип массива, не предусмотрено. Формат файла (рис. 26 и 27)
определяется типом записываемого массива.
| Количество | измерений |
Первая размерность |
Вторая размерность |
|
Последняя размерность |
Элементь^массива
t 1 > 1 1 |
1 байт |
2 байта |
2 байта |
По 2 байта |
2 байта |
По 5 байтов на элемент |
|
|
Рис. 26. Числовой массив. |
|
("Количество | измерений |
Первая
размерность |
Вторая размерность |
> $ |
Последняя размерность |
1 1 > 1 1 Эл ементьб массива
1 1 > i 1 |
1 байт |
2 байта |
2 байта |
По 2 байта |
2 байта |
По 1 байту на элемент |
Рис. 27. Символьный массив,
Рис. 27. Символьный массив,
Для получения осмысленного результата необходимо, чтобы тип пе-
ременной массива при считывании его из файла совпадал с типом, установ-
ленным при записи.
Для файлов прямого и последовательного доступа также не предус-
мотрено отличий для определения типа. Предполагается, что программист
будет сам следить за правильностью использования файлов.
Как уже было сказано, первоначальный размер файлов составляет
4К. Если объем записей превысит размер файла последовательного доступа,
то автоматически будет создан файл с тем же именем (и типом), со следую-
щим порядковым номером (первоначальный номер 0).
Для файлов прямого доступа очередные файлы создаются по мере
поступления записей, и номера файлов не обязательно будут последователь-
ными.
Данные, записанные в файл последовательного доступа хранятся как
простые стринги, разделителем между которыми служит код #0D. Данные
в файлах прямого доступа хранятся также простыми стрингами, заканчива-
ющимися символом #0D. Адрес начала конкретной записи вычисляется по
формуле
Номер записи X Размер записи
Результат целочисленно делиться на 4096, остаток определяет адрес в
файле, а частное — номер файла.
Использование TR-DOS из прикладных программ
Наиболее просто работать с TR-DOS из Бейсика. Но для некоторых
применений ОС в этом способе существуют непреодолимые ограничения.
Скажем, не вполне корректная обработка ошибок (например, останов про-
граммы при физической ошибке чтения/записи) не позволяет сделать про-
граммы на Бейсике автономно работающими. Как показал опыт более чем
трехлетней работы с ОС TR-DOS, реальных успехов можно добиться исклю-
чительно, программируя на ассемблере. Существует три способа взаимодей-
ствия с системой TR-DOS из машинных кодов.
Во-первых, можно использовать команды самой ОС, вызывая интер-
претатор команд так же, как из Бейсика. Этот способ имеет смысл применять
для действий, которые отсутствуют или трудновыполнимы другими метода-
ми. Например, реализация команды ОС MOVE требует достаточно сложной
программы.
Во-вторых, можно использовать интерпретатор командных функций.
Этот способ наиболее популярен, так как предоставляемые интерпретаторе ч
функции охватывают практически все возможные методы доступа к диеж>,
как на физическом уровне (чтение/запись отдельных секторов), так к на
уровне файловой системы (чтение/запись файлов).
Третий способ — напрямую программировать микроконтроллер —
наиболее универсален, так как позволяет получить прямой доступ к дискете,
но и наиболее трудоемок, так как требует больших программных затрат.
В этой части будет рассказано о первых двух способах, третий же
требует знания аппаратных особенностей, и будет описан в соответствующем
разделе.
Командный процессор
Вызов командного процессора TR-DOS из ассемблера практически
ничем не отличается от выполнения команд системы из Бейсика Сначала в
памяти необходимо подготовить тексг команды. Он записывается так же, как
если бы он был набран в редакторе (с клавиатуры). В системную переменную
Бейсика CH_ADD (23645/46) помещается указатель на подготовленную коман-
ду. После этого вызывается командный процессор TR-DOS. Для того, чтобы
можно было вернуться в Бейсик, необходимо сохранить старое значение
переменной CKLADD, а по окончании операции восстановить его. Есть одна
тонкость в том, где нужно расположить текст команды. В процессе работы
TR-DOS использует рабочую область бейсик-системы, при открытии которой
корректируются значения ряда системных переменных, в том числе и
CH_ADD. Для того, чтобы избежать связанных с этим неприятностей, проще
всего помещать команды в области хранения текста бейсик-программы, в
специально зарезервированной строке.
При возникновении ошибок в работе командного процессора TR-DOS
управление будет передано на программу обработки ошибок бейсик-систе-
мы. Указатель на адрес этой программы хранится в системной переменной
ERR_SP (23613/14). Во избежание нежелательного выхода в Бейсик можно
также изменить и этот указатель, записав в него адрес своей собственной
подпрограммы обработки ошибок.
В приведенном ниже примере на дискете создается файл CATALOG,
содержащий текст, выводимый командой CAT. Этот файл можно впоследст-
вии загрузить и обработать в каком-нибудь текстовом редакторе, например
в TLW2m. Перед тем как выполнить эту программу, в Бейсике необходимо
создать рабочую строку с номером 9999, содержащую не менее 32 символов,
например
9999 REM This string allocated 32 bytes of memory
Для начала создадим несколько меток для используемых в программе
системных переменных и внешних процедур.
10 ; (С) 1992 МОА
20 LINEAD EQU #196Е «'подпрограмма поиска бейсик-строки
30 TR_DOS EQU 15619 ; командный процессор TR-DOS
40 CH_ADD EQU 23645 ;указатель на выполняемый оператор
50 CHANS EQU 23631 указатель на область каналов
60 ERR_SP EQU 23613 «-указатель на п/п обработки ошибок
70 ERRDOS EQU 23823 ;код ошибки TR-DOS
Определим метки для токенов ZX Spectrum, которые будем использовать
в командах интерпретатору.
80 REM EQU 234
90 CAT EQU 207
100 ERASE EQU 210
110 SAVE EQU 248
120 CODE EQU 175
130 ENTER EQU 13
Теперь начинается собственно программа, опишем ее заголовок.
140 ORG 40000 ;адрес размещения кодов
150 ENT $
Для корректной работы Бейсика необходимо, чтобы в подпрограммах
пользователя сохранялась пара регистров HL'. Если этого не сделать, то
при возврате в Бейсик может возникнуть неустранимая ошибка, которая
приведет к краху системы.
160 START ЕХХ /установка альтернативных регистров
170 PUSH HL .-сохранение HL'
Переустановим адрес программы обработки ошибок бейсик-системы.
Теперь при возникновении ошибок, которые раньше возвращали управ-
ление в Бейсик (например, при незакрытой дверце дисковода) будет
вызываться подпрограмма DISKERR.
180 LD (ZX_SP),SP ,-сохранение адреса вершины стека
190 LD HL,(ERR_SP) (-сохранение указателя на п/п обработки ошибок
200 LD (ZX_ERR),HL
210 LD HL,DISKERR ,-запись в стек адреса новой п/п обработки
;ошибок
220 PUSH HL
230 LD (ERR_SP),SP ;SP указывает на адрес n/o DISKERR
240 LD HL,QUIT ;установка адреса выхода в случае ошибки
250 LD (AD_RET),HL
Чтобы Бейсик впоследствии не «заметил» подмены указатели на програм-
му, необходимо сохранить значение системной переменной CH_ADD.
260 LD HL,(CH_ADD)
270 LD (ZX_CH),HL
Каталог нельзя непосредственно записать в файл. Прежде его необходимо
построить в памяти и только затем записать эту область памяти на
дискету. Для этого сделаем очередную подмену — заменим п/п вывода
на принтер своей, помещающей выводимые символы в память.
280 LD BC,OUTBYTE ;адрес п/п записи символа в память
290 CALL CHANAL переустановка адреса п/п
300 LD (ZX_PR),DE сохранение прежнего значения адреса
Под область памяти для создания каталога выделим 15 К, расположенных
с адреса 50000. Текстовому редактору TLW2m необходимо, чтобы неис-
пользованный остаток файла содержал коды символа «пробел»,- для этого
заполним область памяти этим кодом.
310 LD HL,50000 ;адрес начала области
320 LD (АЬ_СОН),№;инициализацил указателя принятых бантов
330 LD (HL)," " ;запись кода символа «пробел»
340 LD E,L
350 LD D,H
360 INC DE ;в регистре DE адрес на единицу больший, чем
; в HL
370 LD ВС, 15000—1 ;счетчик байтов
380 LDIR «'заполнение области
Для создания каталога в области памяти воспользуемся командой TR-DOS
CAT #3. Эта команда выведет каталог на принтер, но так как адрес п/п
заменен, то для каждого выводимого байта будет вызываться наша п/п.
390 LD HL,ADCOM1 ;адрес команды CAT #3
400 LD BC,ADC„E1—ADCOM1
i вычисление длины команды
410 CALL EXECUTE ; выполнение комаеды
420 OR А ;если есть ошибки,
430 JR NZ,QUIT ;выйти из программы*
Запишем область памяти в файл. Для этого воспользуемся командой SAVE.
Начало области фиксировано (50000), длину можно рассчитать, зная
адрес последнего записанного в память символа. Но можно сделать
проще — записать всю область, а затем уже в редакторе удалить конечные
пробелы. Так и сделаем.
440 REPEAT LD HL,ADCOM2 ;адрес команды
; SAVE "CATALOG"CODE 50000Л 5000
450 LD BC,ADC_E2—ADCOM2
; вычисление длины команды
460 CALL EXECUTE ; выполнение команды
470 CP 2 ;еспи файл записан,
480 JR NZ,QUIT ;перейдем на QUIT
*) Здесь, по идее, должен быть расположен переход на п/п обработки этой
ошибхи.
Может оказаться так, что файл с именем CATALOG уже существует на
дискете. Тогда записи нового файла не произойдет, а интерпретатор
вернет код ошибки 2. В этом случае удалим старый файл, а затем
повторим попытку записи.
490 LD HL.ADCOM3 ,-адрес команды ERASE "CATALOG"CODE
500 LD BC,ADC_E3-ADCOM3
вычисление длины команды
510 CALL EXECUTE ; выполнение команды
520 OR А ;при успешном выполнении повторение записи
530 JR Z,REPEAT
Как уже было сказано, для успешного возврата в Бейсик нужно восста-
новить значения использованных системных переменных.
540 QUIT LD HL,(ZX„CH) ;восстановление указателя на программу
550 LD (CH_ADD),HL
560 LD BC,(ZX_PR)
570 CALL CHANAL ; восстановление п/п вывода на принтер
580 LD HL,(ZX_ERR) ;восстановление указателя на п/п обработки
; ©шибок
590 LD (ERR_SP),HL
600 LD SP,(ZX_SP) ; восстановление указателя стека
610 LD (!Y),-1 ;указатель на безошибочное завершение
;(код сообщения Бейсика O.K.)
620 POP HL ; восстановление HL'
630 EXX
640 RET ; возврат в Бейсик
Рассмотрим использованные подпрограммы.
Подпрограмма EXECUTE подготавливает в строке с номером 9999 команду
TR-DOS, а затем передает управление интерпретатору для ее выполне-
ния, П/п получает в регистровой паре HL адрес команды, а в ВС — ее
длину.
650 EXECUT
660 PUSH ВС «'сохранение адреса и длимы команды
670 PUSH HL
Поиск адреса строки с номером 9999, адрес возвращается в регистровой
паре HL
680 LD HL,9999
690 CALL LINEAD ;пропуск байтов номера и длинны строки
700 LD ВС,4
710 ADD HL,BC
720 LD (CH_ADD),HL ;запись адреса строки а указатель
730 EX DE.HL
740 POP HL ;восстановление адреса и длины команды
750 POP ВС
760 LDIR ;копирование команды в строку 9999
770 CALL TR_DOS ; вызов интерпретатора
780 LD A,(ERRDOS) ,'взять код ошибки интерпретатора
790 RET ;возврат в программу
Подпрограмма DISKERR будет получать управление вместо программы
обработки ошибок бейсик-системы.
800 DISKER
810 LD HL,DISKERR .'восстановление адреса п/л DISKERR, снятогс
;со стека бейсик-системы
820 PUSH HL
830 LD (ERR_SP),SP
840 LD HL,(AD_RET) ;переход на обработку ошибки
850 iP (HL)
Подпрограмма OUTBYTE принимает байт, выводимый на принтер, и поме-
щает его по адресу указателя AD_CON.
860 OUTBYT
870 LD HL,(AD_CON) ;адрес указателя
880 LD (HL),A ;запись байта а память
890 INC HL ;запись в указатель следующего адреса
900 LD (AD_CON),HL
910 RET ; возврат в программу
Подпрограмма CHANAL служит для переустановки программы вывода на
принтер. В регистровой паре HL она получает адрес новой программы,
а в DE возвращает адрес старой.
^ 920 CHANAL LD HL,(CHANS) ; адрес начала области каналов
930 LD DE,15 ;смещение к адресу п/п вывода на принтер
940 ADD HL,DE
950 LD E,(HL) переустановка п/п
960 LD (HL),C
970 INC HL
980 LD D,(HL)
990 LD (HL),B
1000 RET ;воз&рат в программу
Команды интерпретатора TR-DOS всегда начинаются со стандартного
префикса REM :. Заметьте, что REM — это всегда токен Бейсика, тогда как
остальная часть команды может содержать как токены, так и символы
ASCII. Используемый командным процессором Конвертор 48 --> 128
(см. стр. 177) преобразует все ключевые слова, набранные по буквам, в
токены.
1010 ADCOM1 DEFB REM,":",CAT,"#","3",ENTER
1020 ADC.E1 EQU $
1030 ADCQM2 DEFB REM
1040 DEFM ' :SAVE"CATALOG"CODESOOOO, 15000'
1050 DEFB ENTER
1060 ADC__E2 EQU $
1070 ADCOM3 DEFB REM/':",ERASE
1080 DEFM '"CATALOG"'
1090 DEFB CODE,ENTER
1100 ADC_E3 EQU $
Выделим область для рабочих переменных.
1110 ZX_SP DEFS 2
1120 ZX.ERR DEFS 2
1130 ZX_CH DEFS 2
1140 AD_RET DEFS 2
1150 ZX_PR DEFS 2
1160 AD__CON DEFS 2
1170 ENDE
Запустить оттранслированную программу можно как из ассемблера
командой R, так и из Бейсика функцией USR 40000.