[<>]
~~TOC wide~~
====== 1.9. Примеры использования входных точек системы BDOS ======
Предложенные примеры позволят Вам подробнее разобраться в использовании входных точек системы [[msx:bdos|BDOS]], но для этого вначале необходимо ознакомиться с [[009#n931|разделом IX.3.1]] и особенно внимательно просмотреть приведенную там таблицу контрольного буфера файла (FCB) и таблицу спецификации файла.
Кроме этого, для полного понимания работы программы примера 4 необходимо ознакомиться с картой памяти компьютера и работой со слотами и портами, а именно с портом номер A8h, который позволяет кодировать первичные номера слотов.
{{anchor:e1090-01}} __//Пример 1//__. Считывание содержимого //сектора//.\\ {{.examples:1090-01.asm|}}
LD C,1AH ;Установка нового адреса передачи
LD DE,0500H ;В регистре DE - адрес передачи
CALL 0005H ;
LD DE,0001H ;Чтение H секторов, начиная с сектора
LD H,03H ;с номером 01, находящимся в регистре DE
LD L,00H ;В регистре L - номер дисковода
LD C,2FH ;Функция чтения
JP 0005H ;
{{anchor:e1090-02}} __//Пример 2//__. Программа, позволяющая пользователю, находящемуся в операционной системе, удалить файл, находящийся на диске.\\ {{.examples:1090-02.asm|}}
BDOS EQU 0005H ;Точка BDOS для MSX-DOS.
LD DE,005CH ;Адрес FCB
LD C,13H ;Функция BDOS, которая позволяет удалять
CALL BDOS ;файл, определяемый FCB, начальный адрес
OR A ;которого находитя в DE (DE = 005Ch).
RET Z ;Если Файл на диске отсутствует, то выдаем
LD DE,MESS ;сообщение об этом.
LD C,9 ;Эта функция выводит на экран строку символов,
JP 0005H ;пока не встретит символ "$".
MESS: DEFM "File not found$"
{{anchor:e1090-03}} __//Пример 3//__. Программа, позволяющая из операционной системы переименовать файл, находящийся на дискете.\\ {{.examples:1090-03.asm|}}
BDOS EQU 0005H ;Точка BDOS для MSX-DOS.
LD DE,005CH ;По этому адресу в операционной системе
;хранятся:
; номер устройства (0-текущий дисковод);
; имя файла и его расширение.
;Всего 12 байтов.Еще через 4 байта хранится то
;же самое для имени второго файла в командной
;строке. Таким образом,в DE+16 хранится первый
;байт блока FCB второго файла.
LD C,17H ;Функция BDOS для переименования.
CALL BDOS ;
OR A ;Если функция выполнилась, то - выход,
RET Z ;иначе печать сообщения о том, что файл
LD DE,MESS ;отсутствует.
LD C,9 ;
JP 0005H ;
MESS: DEFM "File not found$"
{{anchor:e1090-04}} __//Пример 4//__. Программа, позволяющая создать файл на диске с данными, которые требуется сохранить. ''OPEN.DBS''–имя нового файла.\\ {{.examples:1090-04.asm|}}
BDOS EQU 0005H ;Точка BDOS для MSX-DOS.
LD DE,File ;Функция BDOS, которая позволяет открыть
LD C,16H ;новый файл на диске. Старый файл с этим
CALL BDOS ;именем уничтожается.
LD HL,0006H ;Пусть текущий размер записи будет равен
LD (File+14),HL ; 6 (запишем только 6 байтов).
LD HL,0000H ;Номер записи для файла последовательного
LD (File+33),HL ;доступа устанавливаем равным нулю.
LD (File+35),HL ;Тот же номер записи - и для файла прямого
;доступа. Все 4 байта заполняем 00h.
LD DE,Data ;Установка адреса передачи ("откуда").
LD C,1AH ;
CALL BDOS ;
;
LD DE,File ;Осуществляем одну запись размером в 6 байтов.
LD HL,0001H ;
LD C,26H ;Функция BDOS для посылки записи в файл.
CALL BDOS ;
;
LD DE,File ;При закрытии файла на диск дозаписывается
LD C,10H ;все до последнего байта данных, временно
JP BDOS ;расположившихся в оперативной памяти (в
;буфере файла). Эта операция необходима
;всегда при записи на диск.
File: NOP ;
DEFM "OPEN DBS" ;Имя нового файла.
DEFS 25 ;
Data: DEFB 0AH,0BH,0CH,0DH,0EH,0FH; Данные.
{{anchor:e1090-05}} __//Пример 5//__. Программа, позволяющая грузить и запускать, не выходя из операционной системы, игровые программы или программы, написанные в кодах, начальные адреса и адреса старта которых лежат в пределах от 8000h до EFFFh.
\\ {{.examples:1090-05.asm|}} \\
Отметим, что первые 7 байтов таких программ определяют параметры файла: тип файла, адрес начала программы, адрес конца программы,адрес старта программы. По данным 7 байтам определяют адрес памяти,в которой программа должна работать, т.е. ее место в RAM. Можно по адресу начала загрузить программу как файл прямого доступа,"отрезав" первые 7 байтов, но всегда проще
работать с файлами последовательного доступа, поэтому можно загрузить программу полностью начиная с адреса, равного
//адрес начала// - 7
и сделать обращение по адресу старта.
BDOS EQU #0005 ;Точка BDOS для MSX-DOS.
;
LD DE,#005C ;С этих адресов в операционной системе
CALL START ;хранятся первые 12 необходимых байтов спе-
LD DE,#006C ;цификации файлов, имена которых вводят-
CALL START ;ся в командной строке (2 и 3-е слово
RET ;строки соответственно).
;
START: PUSH DE ;HL:= REGION, DE:= 005Ch
LD HL,REGION ;Операциями в стеке меняем содержимое ре-
PUSH HL ;гистров HL и DE (можно проще: EX DE,HL).
POP DE ;DE:= REGION, HL:= 005Ch
POP HL ;Это пересылка номера драйвера и имени
LD BC,#000C ;файла с расширением в отведенную опера-
LDIR ;тивную область для дальнейшей работы с
;файлом.
OPEN: LD DE,REGION ;Открытие файла,определяемого блоком FCB
LD C,#0F ;(блоком управления файлами), начальный
CALL BDOS ;адрес которого находится в регистре DE.
;
PERES: LD DE,#0500 ;Перед считыванием записи из файла уста-
LD HL,#0007 ;навливаем адрес пересылки = 0500h,a так-
CALL BLOAD ;же размер записи = 7 байтам и считываем
;запись.
LD HL,(#0505) ;По адресу метки ADRES положим адрес
LD (ADRES),HL ;старта считываемой программы с расшире-
LD HL,(#0501) ;нием OBJ или BLO. Напомним, что первые
;7 байтов такой программы определяют по
;порядку:
; код ASCII буквы "Ч",
; адрес н а ч а л а программы,
; адрес к о н ц а программы,
; адрес с т а р т а программы
;
LD BC,#0007 ;Уменьшаем на 7 адрес начала программы и
SBC HL,BC ;таким образом устанавливаем новый адрес
EX DE,HL ;передачи записи при считывании из файла,
;только размер записи теперь устанавлива-
LD HL,(REGION+16) ;ем равным размеру файла в байтах и вы-
CALL BLOAD ;полняем полное считывание файла. Таким
;образом, первые 7 байтов файла, опреде-
;ляющие параметры и тип файла, "отрезают-
;ся".
;
LD HL,JUMP ;В рабочую область для оператора CIRCLE
LD DE,#F931 ;пересылается программа запуска загружен-
PUSH DE ;ного файла. Начальный адрес рабочей об-
LD BC,13 ;ласти остается в стеке и, таким образом,
LDIR ;область памяти с этим адресом опрашива-
RET ;ется при встрече команды RET.
;
JUMP: LD A,11110000B ;┌──────────────────────────────────────────┐
OUT (#A8),A ;│ Подключим ROM BASIC: │
RST #30 ;│ в адресах 0000h÷7FFFh - ROM, слот 0-2; │
DEFB #00 ;│ в адресах 8000h÷FFFFh - RAM, слот 3-2 │
;│ │
ADRES: NOP ;│Здесь хранится адрес старта. │
NOP ;│ │
LD A,11110011B ;│Для загрузки второго файла (если он │
OUT (#A8),A ;│есть) к слоту 3-2 (в котором находимся) │
RET ;│подключаем страницу с адресами 0000h÷ │
;│3FFFh(в области, в которой работали раньше)
;└──────────────────────────────────────────┘
;
BLOAD: LD (REGION+14),HL ;Установка текущего размера записи
LD HL,#0000 ;(см.таблицу "Спецификация файла").
LD (REGION+33),HL ;Номер записи всегда равен нулю,т.е.
LD (REGION+35),HL ;считываем файл с самого начала.
;
LD C,#1A ;┌────────────────────────────────────────┐
CALL BDOS ;│Установка адреса передачи (BDOS) │
;│ │
LD HL,#0001 ;├────────────────────────────────────────┤
LD DE,REGION ;│Считывание одной записи из файла,опреде-│
LD C,#27 ;│ляемого блоком FCB, начальный адрес ко-│
JP BDOS ;│торого находится в регистре DE │
;└────────────────────────────────────────┘
REGION:DEFS 36 ;Обнуление последующих 36 байтов. Освобожде-
;ние области для работы со спецификацией
;файла
KONEC: RET ;
{{anchor:e1090-06}} __//Пример 6//__. Программа позволяет выводить каталог диска на экран.\\ {{.examples:1090-06.asm|}}
BDOS EQU 0005H
LD DE,0500H ;Установка адреса передачи
LD C,1AH ;
CALL BDOS ;
LD C,11H ;Поиск первого появления файлов
LD DE,File ;В имени файла используется специальный
CALL 0005H ;символ "?"
OR A ;
RET NZ ;
START: CALL Consol ;Если файл еще есть, то выводим имя.
LD C,12H ;Поиск следующего появления файлов.
LD DE,File ;
CALL 0005H ;
OR A ;
RET NZ ;Когда поиск прекратится,
JR START ;подпрограмма завершается
Consol:LD HL,0A0DH ;Перевод строки в конце слова
LD (050CH),HL ;
LD A,24H ;Символ окончания строки "$"
LD (050EH),A ;
LD DE,0501H ;Первый байт - номер дисковода: его
LD C,9 ;не стоит выводить.
JP 0005H ;
File: ;
NOP ;
DEFM "???????????" ;
DEFS 30 ;
{{anchor:e1090-07}} __//Пример 7//__. Программа, позволяющая просмотреть содержимое текстового файла, находящегося на диске.\\ {{.examples:1090-07.asm|}}
BDOS EQU 0005H ;
LD HL,005CH ;Пересылка номера устройства (драйвера)
LD DE,Konec ;и имени файла в отведенную область для
LD BC,0CH ;дальнейшей работы с блоком FCB
LDIR ;
LD DE,Konec ;Открытие файла
LD C,0FH ;
CALL BDOS ;
LD DE,Adres ;Установление адреса передачи для загрузки
LD C,1AH ;файла с диска
CALL BDOS ;
LD HL,(Konec+16) ;Устанавливаем размер записи для считывания
LD (Konec+14),HL ;равный объему файла.
LD HL,0000H ;Номер записи для файла прямого и последо-
LD (Konec+33),HL ;вательного доступа обнуляем, т. е. чита-
LD (Konec+35),HL ;ем файл с самого начала
LD HL,1 ;Производим считывание одной записи = размеру
LD DE,Konec ;файла по адресу передачи
LD C,27H ;
CALL BDOS ;
LD HL,Adres ;┌───────────────────────────────────────┐
LABL_1:LD A,(HL) ;│ Программа распечатки ASCII кодов. │
CP 1AH ;│ Вывод символов из текстового файла │
JP Z,LABL_2 ;│ будет осуществляться до тех пор,пока │
INC HL ;│ не встретится символ файла с кодом: │
RST 30H ;│ 1Аh. Этот символ обозначает конец │
DEFB 00H ;│ текстового файла (по стандарту ASCII).│
DEFW 00A2H ;└───────────────────────────────────────┘
JP LABL_1 ;
LABL_2:RST 00H ;Выход в MSX-DOS (рестарт).
;
Konec: DEFS 38 ;Обнуление 38 байтов для блока FCB
Adres: DEFS 25 ;Адрес передачи
{{anchor:e1090-08}} __//Пример 8//__. Еще одна программа,позволяющая просмотреть содержимое текстового файла, находящегося на диске (авторы алгоритма: J.Suzuki и T.Patterson).
\\ Программа "вырезана" А.Никитиным из файла COMMAND.COM; она написана на макроассемблере.
\\ {{.examples:1090-08.asm|}}
CALL N_DRIVE ; Проверка существования устройства
LD DE,0100H ; Установка адреса обмена
LD C,1AH ;
CALL 5 ;
LD DE,005CH ; Открытие файла, FCB которого
LD C,0FH ; находится по адресу 5CH.
CALL 5 ; Это - стандарт для MSXDOS.SYS
OR A ;
LD DE,FILE_NO ; Если файл отсутствует, то сообщение
JP NZ,E_EXIT ; и выход.
LD HL,0 ;
LD (007DH),HL ; Подготовка FCB для считывания
LD (007FH),HL ; записей из файла.
INC HL ;
LD (006AH),HL ;
LBL2: LD DE,005CH ; Считывание происходит по 1,5 Кб
LD HL,0600H ; пока не кончится файл,
LD C,27H ; и печать на экран дисплея
CALL 5 ; содержимого файла
LD A,L ;
OR H ;
JP Z,EXIT ;
LD DE,0100H ; Программа печати на консоль
LBL1: LD A,(DE) ;
INC DE ;
CP 1AH ; 1АH - код конца файла
JP Z,EXIT ;
CALL PEN ;
DEC HL ;
LD A,L ;
OR H ;
JR NZ,LBL1 ;
JR LBL2 ;
;
N_DRIVE: ;
LD A,(005CH) ; Подпрограмма проверки существования
INC A ; устройства. Если устройство указано
RET NZ ; неверно, то выход с сообщением
POP DE ;
LD DE,SPECIF ;
JP E_EXIT ;
PEN: PUSH HL ; Подпрограмма вывода символа на консоль
PUSH DE ;
PUSH BC ;
PUSH AF ;
LD E,A ;
LD C,2 ;
CALL 5 ;
POP AF ;
POP BC ;
POP DE ;
POP HL ;
RET ;
EXIT: RET ;
E_EXIT: LD C,9 ;
JP 5 ;
FILE_NO:DEFM "File not found$"
SPECIF: DEFM "Invalid drive specification$"
{{anchor:e1090-09}} __//Пример 9//__. Эта программа позволяет копировать файлы.\\ {{.examples:1090-09.asm|}}
FILEIN EQU #5C ; Системные адреса хранения
FILEOUT EQU #6C ; слов командной строки
BDOS EQU #5 ; Адрес вызова BDOS
;Некоторые макроопределения:
READ MACRO
LD HL,#4000 ;Копирование по 16кБ
LD DE,FIN ;
LD C,#27 ;Функция считывания с диска
CALL BDOS ;
LD (VAL),HL ;
RET ;
ENDM ;
WRITE MACRO ;
LD DE,FOUT ;
LD C,#26 ;Функция записи на диск
LD HL,(VAL) ;
CALL BDOS ;
RET ;
ENDM ;
CLOSE MACRO ;
LD DE,FOUT ;
LD C,#10 ;Функция закрытия файла
CALL BDOS ;
RET ;
ENDM ;
ADRES MACRO ;
LD DE,#0800 ;
LD C,#1A ;Установка адреса передачи
CALL BDOS ;
RET ;
ENDM ;
;Н а ч а л о самой программы
START: LD A,#C9 ;Для скоростной работы дисковода
LD (#38),A ;прерывания по таймеру отключили
DI ;
LD HL,FILEIN ;
LD DE,FIN ;Первое слово командной строки -
LD BC,#0C ;и есть первый файл
LDIR ;
LD HL,FILEOUT+1 ;
LD A,#20 ;
CP (HL) ;
JR NZ,OTHER ;
EX DE,HL ;
LD HL,FILEIN+1 ;
LD BC,#0B ;Если второго слова нет, то
LDIR ;имя файла(2) =: имя файла(1)
OTHER: LD HL,FILEOUT ;
LD DE,FOUT ;
LD BC,#0C ;
LDIR ;
EI ;
LD DE,FIN ;
LD C,#0F ;Открытие для считывания файла(1)
CALL BDOS ;
RЕТ NZ ;
LD DE,FOUT ;
LD C,#16 ;Открытие для записи файла(2)
CALL BDOS ;
LD HL,0 ;
LD (FIN+33),HL ;
LD (FIN+35),HL ;Считываем и записываем с 0-й записи
LD (FOUT+33),HL ;
LD (FOUT+35),HL ;
INC HL ;
LD (FIN+14),HL ;
LD (FOUT+14),HL ;Размер записей = 1
SNOWA: CALL LDIRADRES ;
CALL DISKIN ;
LD A,H ;Пока на выходе при считывании в HL
OR L ;не будет 0, записываем количество
JR Z,ENDCOPY ;считанных записей, иначе закрываем
CALL LDIRADRES ;файл(2)
CALL DISKOUT ;
JR SNOWA ;
ENDCOPY:CALL DISKCLOSE ;
LD DE,STROKA ;Сообщение о выполнении
LD C,#9 ;
CALL BDOS ;
LD A,#C3 ;Восстановление прерываний по таймеру
LD (#38),A ;и выход в систему
RST 0 ;
;Подпрограммы работы с дисководом, FCB, сообщение, переменные.
DISKIN: READ
DISKOUT: WRITE
DISKCLOSE: CLOSE
LDIRADRES: ADRES
STROKA: DEFB #0D,#0A
DEFM "COPY COMPLETE$"
VAL: DEFS 2
FIN: DEFS 40
FOUT: DEFS 40
KONEC: NOP
----
[<>]
{{tag>msxbdpl}}