1.9. П р и м е р ы и с п о л ь з о в а н и я в х о д н ы х т о ч е к с и с т е м ы BDOS Предложенные примеры позволят Вам подробнее разобраться в использова- нии входных точек системы BDOS, но для этого вначале необходимо ознако- миться с разделом IX.3.1 и особенно внимательно просмотреть приведенную там таблицу контрольного буфера файла (FCB) и таблицу спецификации файла. Кроме этого, для полного понимания работы программы примера 4 необходимо ознакомиться с картой памяти компьютера и работой со слотами и портами, а именно с портом номер A8h, который позволяет кодировать первичные номера слотов. П р и м е р 1. Считывание содержимого с е к т о р а . ───────────── 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 ; П р и м е р 2. Программа, позволяющая пользователю, находящемуся в опе- ───────────── рационной системе, удалить файл, находящийся на диске. 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$" П р и м е р 3. Программа, позволяющая из операционной системы переи- ────────────── меновать файл, находящийся на дискете. 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$" П р и м е р 4. Программа, позволяющая создать файл на диске с данными, ────────────── которые требуется сохранить. OPEN.DBS-имя нового файла. 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; Данные. П р и м е р 5. Программа, позволяющая грузить и запускать, не выходя ────────────── из операционной системы, игровые программы или програм- мы, написанные в кодах, начальные адреса и адреса старта которых лежат в пределах от 8000h до EFFFh. Отметим, что первые 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 ; П р и м е р 6. Программа позволяет выводить каталог диска на экран. ───────────── 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 ; П р и м е р 7. Программа, позволяющая просмотреть содержимое тексто- ────────────── вого файла, находящегося на диске. 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 ;Адрес передачи П р и м е р 8. Еще одна программа,позволяющая просмотреть содержимое ────────────── текстового файла, находящегося на диске (авторы алго- ритма: J.Suzuki и T.Patterson). Программа "вырезана" А.Никитиным из файла COMMAND.COM; она написана на макроассемблере. 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$" П р и м е р 9. Эта программа позволяет копировать файлы. ───────────── 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