│ 16 │ Функция FPOS │

├───────────┼─────────────────────────┤

│ 18 │ Символ поддержки │

└───────────└─────────────────────────┘

Табл.21.1. Запросы к устройству

TEXT - это указатель на текст программы на языке BASIC, если

эта BASIC-программа в картридже должна автоматически запускаться

при перезагрузке. В противном случае там хранится ноль. Размер

программы должен быть не более 16 К, по адресам с 8000h по BFFFh.

Интерпретатор языка BASIC проверяет содержимое поля TEXT

заголовка картриджа после инициализации (INIT) и после того как

стартует система. Если там не ноль, то по указателю TEXT

запускается BASIC-программа. Она должна храниться в промежуточном

коде и ее начало обозначается кодом ноль.

п.2. Создание CALL-подпрограмм пользователем

Приведем пример программы создания следующих подпрограмм

пользователя, вызываемых из MSX-BASIC оператором CALL:

CALL RUSON - включение русских букв;

CALL RUSOFF - выключение русских букв;

CALL CAPSON - включение прописных букв;

CALL CAPSOFF - выключение прописных букв.

НЕ нашли? Не то? Что вы ищете?

Эти операторы формируются в псевдо-ROM по адресу 4000h. Для

правильной трансляции ссылок используются директивы. PHASE и

.DEPHASE, которые описаны ниже.

Перед записью значений в ячейку управления вторичными слотами

(FFFFh) они должны инвертироваться. Это нужно помнить и при

запоминании текущего состояния слотов.

Хотя для трансляции мы воспользовались ассемблером M80 и

сборщиком L80, полученный файл реально имеет тип OBJ. Это

обеспечивают первые 7 байт текста программы.

┌──────────────────────────────

MSX. M-80 1.00 01-Apr-85

.Z80

9000 Load EQU 9000h ; адрес загрузки

4000 CallROM EQU 4000h ; адрес переписывания

FD02 RAMCF EQU 0FD02h ; страница 1 слот 3-2

FD89 IdCall EQU 0FD89h ; сюда BASIC записывает

; имя оператора CALL

0F1F RUSSWCH EQU 0F1Fh ; вкл/выкл. RUS

FCAB CAPST EQU 0FCABh ; статус CAPS

FCAC KANAST EQU 0FCACh ; статус RUS

0004 CallNmb EQU 4 ; количество наших CALL

0000' ASEG

0000 FE DB 0FEh ; Obj-файл

0001 9000 DW Load ; адрес загрузки

0003 90F2 DW Load+Length ; конечный адрес

0005 9000 DW Start ; стартовый адрес

; ========================================

.PHASE Load

9000 F3 Start: DI

; === Установка вторичного слота

9001 3A FFFF LD A,(0FFFFh) ; текущее полож. слотов

9004 2F CPL ; инверсия

9005 F5 PUSH AF ; запись в стек

9006 CB DF SET 3,A ; страница 1, втор. сл. 2

9008 CB 97 RES 2,A

900A 32 FFFF LD (0FFFFh),A

; === Установка первичного слота

900D DB A8 IN A,(0A8h) ; первичный слот

900F F5 PUSH AF

9010 F6 0C OR 00001100b ; стр. 1, слот 3

9012 D3 A8 OUT (0A8h),A

; === Заполняем псевдо-ROM

9014 21 902E LD HL, PrgEnd ; откуда

9017 11 4000 LD DE, CallROM ; куда

901A 01 00C4 LD BC, Length-(PrgEnd-Load) ; сколько

901D ED B0 LDIR ; пересылка

; === Восстановление конфигурации BASIC

901F F1 POP AF

9020 D3 A8 OUT (0A8h),A

9022 F1 POP AF

9023 32 FFFF LD (0FFFFh),A

9026 FB EI

; === Заполнение буфера SLTATR - FD02h, т. е.

; === Разрешение CALL для слота 3-2, первая страница (4000h)

9027 3E 20 LD A,32

9029 32 FD02 LD (RAMCF),A

902C 3F CCF

902D C9 RET ; возврат в BASIC

902E PrgEnd EQU $

.DEPHASE

; === Заголовок псевдо-ROM

.PHASE CallROM

4000 41 42 DB 'AB' ; ID картриджа

4002 0000 DW 0 ; адрес инициализации ROM

4004 4011 DW CallBeg ; адрес обработки CALL

4006 0000 DW 0 ; адрес обработки нестанд. I/O

4008 0000 DW 0 ; адрес текста BASIC в ROM

400A DS 7,0 ; резерв

; === Начало обработки оператора CALL

4011 CallBeg:

4011 37 SCF ; флаг "Syntax error"

4012 E5 PUSH HL ; сохраним HL

4013 06 04 LD B, CallNmb ; цикл сравнений

4015 21 4053 LD HL, IdBlock

4018 NewComp:

4018 E5 PUSH HL

4019 CD 4028 CALL CompBlock ; сравниваем имена

401C E1 POP HL

401D 30 1C JR NC, AddrBlock ; если нашли имя, переход

401F 11 0010 LD DE,010h ; на следующее имя, +16 байт

4022 19 ADD HL, DE ; увеличиваем адрес

4023 10 F3 DJNZ NewComp ; повторяем поиск

4025 E1 POP HL ; возврат, имени CALL нет

4026 37 SCF ; "Syntax error"

4027 C9 RET

; === Сравнение имен

4028 CompBlock:

4028 11 FD89 LD DE, IdCall ; адрес имени CALL

402B 1A NextS: LD A,(DE)

402C A7 AND A ; ноль?

402D 28 07 JR Z, EndNm

402F BE CP (HL) ; сравнить с псевдоROM

4030 37 SCF

4031 C0 RET NZ ; выход, не равны

4032 23 INC HL ; сравнить следующие символы

4033 13 INC DE

4034 18 F5 JR NextS

4036 BE EndNm: CP (HL) ; тоже ноль?

4037 37 SCF

4038 C0 RET NZ ; выход, если длиннее

4039 3F CCF ; имена совпали !

403A C9 RET

; === Выбираем адрес нашего CALL и переходим

403B AddrBlock:

403B 3E 04 LD A, CallNmb

403D 90 SUB B ; номер имени CALL

403E 21 404B LD HL, AddrCall

4041 87 ADD A, A ; смещение в табл. адресов

4042 16 00 LD D,0

4044 5F LD E, A

4045 19 ADD HL, DE ; адрес в таблице - в HL

4046 5E LD E,(HL) ; адрес подпр. CALL - в DE

4047 23 INC HL

4048 56 LD D,(HL)

4049 EB EX DE, HL ; адрес - в HL

404A E9 JP (HL) ; переход на наш CALL!

; === Таблица адресов подпрограмм CALL

404B AddrCall:

404B 4093 DW RUSON

404D 409D DW RUSOFF

404F 40A8 DW CAPSON

4051 40B7 DW CAPSOFF

; === Таблица имен операторов CALL, по 16 байт на имя

4053 IdBlock:

4053 52 55 53 4F DEFM 'RUSON'

4057 4E

4058 DEFS 11,0

4063 52 55 53 4F DEFM 'RUSOFF'

4067 46 46

4069 DEFS 10,0

4073 43 41 50 53 DEFM 'CAPSON'

4077 4F 4E

4079 DEFS 10,0

4083 43 41 50 53 DEFM 'CAPSOFF'

4087 4F 46 46

408A DEFS 9,0

; === Включить RUS

4093 AF RUSON: XOR A

4094 32 FCAC LD (KANAST),A

4097 F7 RST 30h

4098 00 DEFB 0

4099 0F1F DEFW RUSSWCH

409B E1 POP HL

409C C9 RET

; === Выключить RUS

RUSOFF:

409D 3E FF LD A,0FFh

409F 32 FCAC LD (KANAST),A

40A2 F7 RST 30h

40A3 00 DEFB 0

40A4 0F1F DEFW RUSSWCH

40A6 E1 POP HL

40A7 C9 RET

; === Включить CAPS

CAPSON:

40A8 3E FF LD A,0FFh

40AA 32 FCAB LD (CAPST),A

40AD F3 DI

40AE DB AA IN A,(0AAh)

40B0 E6 BF AND 0BFh

40B2 D3 AA OUT (0AAh),A

40B4 FB EI

40B5 E1 POP HL

40B6 C9 RET

; === Выключить CAPS

CAPSOFF:

40B7 AF XOR A

40B8 32 FCAB LD (CAPST),A

40BB F3 DI

40BC DB AA IN A,(0AAh)

40BE F6 40 OR 40h

40C0 D3 AA OUT (0AAh),A

40C2 FB EI

40C3 E1 POP HL

40C4 C9 RET

.DEPHASE

00F2 Length EQU $-1-7

END

└──────────────────────────────

22. Работа с файлами

При работе с внешними устройствами в традиционном

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

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

информации, размещаемую на внешних запоминающих устройствах и

устройствах ввода/вывода. Таким образом, набор данных имеет

физический смысл - информация, хранимая на ленте, диске, бумаге и

т. п.

Файл - это абстракция (структура, описание) набора данных в

программе на некотором языке программирования. Программист

описывает файл и выполняет операции ввода/вывода над файлом,

возможно, не зная точно, какой конкретно набор данных будет

сопоставлен файлу. Связь файла с набором данных обычно

осуществляет оператор открытия файла.

В последнее время понятие "файл" часто используется вместо

понятия "набор данных". Файл становится и логическим, и физическим

понятием.

С файлами (наборами данных) можно работать на двух уровнях -

"низком" и "высоком". В первой главе была описана организация

хранения информации на диске. Хорошо разобравшись в структуре

директория, DPB, FAT, FCB, можно написать программу, которая ищет

файл в директории, затем в FAT, читает или пишет информацию в

соответствующие сектора диска и затем обновляет директорий и FAT.

Это и есть "низкий" уровень, требующий очень кропотливой и

аккуратной работы.

На "высоком" уровне программист берет на себя минимум забот -

задает FCB и буфер ввода/вывода, а всю остальную работу выполняют

системные функции BDOS MSX-DOS. Такая работа более надежна, но

предоставляет меньше возможностей.

п.1. Абсолютное чтение/запись

Под абсолютным чтением/записью здесь понимается чтение/запись

логических секторов диска, в том числе BOOT-сектора, секторов

директория, таблиц FAT, секторов данных.

Для выполнения таких действий можно использовать системные

функции BDOS 1Ah ( установка адреса буфера), 1Bh ( получение

информации о драйвере), 2Fh ( абсолютное чтение секторов), 30h

( абсолютная запись секторов диска) и другие.

В качестве примера приведем программу восстановления

директория, если были случайно уничтожены несколько файлов. Как Вы

помните, при этом в первом байте соответствующей записи директория

появляется код E5h.

Программа находит такие записи в директории и ждет ввода

программистом первой литеры стертого файла. В конце работы

восстановленный директорий записывается назад на диск. Обратите

внимение, что программа не востанавливает FAT, записи которого при

уничтожении файла обнуляются.

┌──────────────

MSX. M-80 1.00 01-Apr-85 PAGE 1

.Z80

0005 BDOS EQU 5

0001 CONS_INP EQU 1

0002 CONS_OUT EQU 2

Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46