┬II.2. Примеры использования точек BDOS, ┬относящихся к работе с диском Примеры, немногочисленные, лаконичные, приве╨ денные к месту, сообщают рассуждению блеск, глу╨ бину и убедительность, но оно становится невра╨ зумительным, если примеров и подробностей черес╨ чур много. Л.К.Вовенарг. Размышления и максимы Предложенные ниже примеры позволят Вам подробнее разобраться в ис╨ пользовании входных точек системы BDOS, но для этого вначале необходимо хорошенько ознакомиться со структурой Контрольного Буфера Файла (FCB) и таблицей спецификации файла. └Пример 1.─ Считывание содержимого сектора. LD C,1Ah ;Установка нового адреса передачи LD DE,500h ;В регистре DE - адрес передачи CALL 5 LD DE,1 ;Чтение H секторов начиная с сектора LD H,3 ;с номером 01, находящимся в регистре DE LD L,0 ;В регистре L - номер дисковода LD C,2Fh ;Функция чтения JP 5 └Пример 2.─ Программа, позволяющая пользователю, находящемуся в опе╨ рационной системе, удалить файл, находящийся на диске. BDOS EQU 5 ;Точка BDOS для MSX-DOS. LD DE,5Ch ;Адрес FCB LD C,13h ;Функция BDOS, которая позволяет удалять CALL BDOS ;файл, определяемый FCB, начальный адрес OR A ;которого находитя в DE (DE = 005Ch). RET Z ;Если Файл на диске отсутствует, то выдаем LD DE,MESS ;сообщение об этом. LD C,9 ;Функция 9 выводит на экран строку символов, JP 5 ;пока не встретит символ "$". MESS: DEFM "File not found$" └Пример 3.─ Программа, позволяющая из операционной системы переимено╨ вать файл, находящийся на дискете. BDOS EQU 5 ;Точка BDOS для MSX-DOS. LD DE,5Ch ; По этому адресу в операционной системе хранятся: ; номер устройства (0-текущий дисковод); ; имя файла и его расширение. ; Всего 12 байтов. Еще через 4 байта хранится то же самое для имени ; второго файла в командной строке. Таким образом, в DE+16 хранится ; первый байт блока FCB второго файла. LD C,17h ;Функция BDOS для переименования. CALL BDOS ; OR A ;Если функция выполнилась, то - выход, RET Z ;иначе печать сообщения о том, что файл LD DE,MESS ;отсутствует. LD C,9 ; JP 5 MESS: DEFM "File not found$" └Пример 4.─ Программа, позволяющая создать файл на диске с данными, которые требуется сохранить (OPEN.DBS-имя нового файла). BDOS EQU 5 ;Точка BDOS для MSX-DOS. LD DE,File ;Функция BDOS, которая позволяет открыть LD C,16h ;новый файл на диске. Старый файл с этим CALL BDOS ;именем уничтожается. LD HL,6 ;Пусть текущий размер записи будет равен LD (File+14),HL ; 6 (запишем только 6 байтов). LD HL,0 ;Номер записи для файла последовательного LD (File+33),HL ;доступа устанавливаем равным нулю. LD (File+35),HL ;Тот же номер записи - и для файла прямого ;доступа. Все 4 байта заполняем 00h. LD DE,Data ;Установка адреса передачи ("откуда"). LD C,1Ah CALL BDOS LD DE,File ;Осуществляем одну запись размером в 6 байт. LD HL,1 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.─ Программа позволяет выводить каталог диска на экран. LD DE,500h ; Установка адреса передачи LD C,1Ah CALL BDOS LD C,11h ; Поиск первого появления файлов LD DE,File ; В имени файла используется специальный START: CALL 5 ; символ "?" OR A RET NZ CALL Consol ; Если файл еще есть, то выводим имя. LD C,12h ; Поиск следующего появления файлов. JR START ; Когда поиск прекратится, ; подпрограмма завершается Consol:LD HL,0A0Dh ; Перевод строки в конце слова LD (050Ch),HL LD A,24h ; Символ окончания строки "$" LD (050Eh),A LD DE,0501h ; Первый байт - номер дисковода: его LD C,9 ; не стоит выводить. JP 5 File: DEFB 0,"???????????" ; Шаблон поиска └Пример 6.─ Программа, позволяющая просмотреть содержание текстового файла, находящегося на диске. BDOS EQU 5 LD HL,5Ch ;Пересылка номера устройства (драйвера) 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,0 ;Номер записи для файла прямого и последо╨ 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 0 ;┴ет конец любого текстового файла. ┴ DEFW 0A2h ;┴(по стандарту ASCII) ┴ JP LABL_1 ;┴ ┴ LABL_2:RST 0 ;┴Выход в MSX-DOS (рестарт). ┴ ;┌┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┐ Konec: DEFS 38 ;Обнуление 38 байтов для блока FCB Adres: DEFS 25 ;Адрес передачи └Пример 7.─ Программа, позволяющая копировать файлы. FILEIN EQU 5Ch ;Системные адреса хранения FILEOUT EQU 6Ch ;слов командной строки BDOS EQU 5 ;Адрес вызова BDOS ;Некоторые макро-определения: READ MACRO LD HL,4000h ;Копирование по 16 Kбайт LD DE,FIN LD C,27h ;Функция считывания с диска CALL BDOS LD (VAL),HL RET ENDM WRITE MACRO LD DE,FOUT LD C,26h ;Функция записи на диск LD HL,(VAL) CALL BDOS RET ENDM CLOSE MACRO LD DE,FOUT LD C,10h ;Функция закрытия файла CALL BDOS RET ENDM ADRES MACRO LD DE,800h LD C,1Ah ;Установка адреса передачи CALL BDOS RET ENDM ; ┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬ ; ┌Начало программы START: LD A,0C9h ;Для скоростной работы дисковода LD (38h),A ;прерывания по таймеру отключили DI LD HL,FILEIN LD DE,FIN ;Первое слово командной строки - LD BC,0Ch ;и есть первый файл. LDIR LD HL,FILEOUT+1 LD A,20h CP (HL) JR NZ,OTHER EX DE,HL LD HL,FILEIN+1 LD BC,0Bh ;Если второго слова нет, то LDIR ;имя файла(2) =: имя файла(1) OTHER: LD HL,FILEOUT LD DE,FOUT LD BC,0Ch LDIR EI LD DE,FIN LD C,0Fh ;Открытие для считывания файла(1) CALL BDOS RЕТ NZ LD DE,FOUT LD C,16h ;Открытие для записи файла(2) CALL BDOS LD HL,0 LD (FIN+33),HL LD (FIN+35),HL ;Считываем и записываем с нулевой 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,9h CALL BDOS LD A,0C3h ;Воостановление прерываний по таймеру LD (38h),A ;и выход в систему RST 0 ;Подпрограммы работы с дисководом, FCB, сообщения, переменные. DISKIN: READ DISKOUT: WRITE DISKCLOSE: CLOSE LDIRADRES: ADRES STROKA: DEFB 0Dh,0Ah DEFM "Copy complete$" VAL: DEFS 2 FIN: DEFS 40 FOUT: DEFS 40 └Пример 8.─ ; ; ─┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬│ ; ┴ Программа, позволяющая защитить диск от команд: ┴ ; ┴ DIR, COPY, DEL и т.д. ┴ ; ┴ Т.е. ото всех команд ОС, кроме команды FORMAT. ┴ ; ┌┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┐ ; .z80 ; StrPar EQU 82h ; По этому адресу расположена строка ; параметров Bdos MACRO asx ; Макрос вызова подпрограмм BDOS ld c,asx Call 5 ENDM ; Устaновка нового адреса передачи для считывания каталога диска ld de,NewDMA Bdos 1Ah ; Поиск имени дисковода и обработка результатов поиска ld hl,StrPar ld b,':' Call SearCHR cp 255 ; Обработка ошибки jr z,ErrStr dec hl ld a,(hl) ; Обработка имени дисковода and 0DFh sub 'A' ; Получаем информацию о диске (заметьте, что в BDOS #1Bh имя драйвера ; "А" эквивалентно 01h) push af ld e,a inc e Bdos 1Bh cp 255 ; Обработка ошибки jr nz,Next_Step ld de,Mess3 jr The_End ; Чтение каталога диска по адресу передачи Next_Step: pop af ld l,a ; Имя драйвера ld h,7 ; Максимальная длина каталога ld e,(ix+11h) ; Извлекаем номер первого ld d,(ix+12h) ; кластера каталога push de ; Сохраняем de и hl для push hl ; записи перед выходом Bdos 2Fh ; Читаем каталог в память ld b,(ix+0Bh) ; Число файлов, ld hl,NewDMA ; адрес начала каталога в памяти ; для последующей обработки ; Проверка ключей ld a,(StrPar) cp '-' jr z,Protect cp '+' jr z,ReSet ; Плохие ключи - сообщение и выход ErrStr: ld de,Mess0 The_End: Bdos 9 rst 0 ; ; Засекречивание каталога. Для предотвращения возможной записи на этот ; диск все элементы директории должны быть активными, поэтому свободные ; входные точки заполняются. Protect: ld a,(hl) cp 0 ; Если первый символ элемента каталога jr nz,F_0 ; равен 0, то установить его в "!" ld (hl),'!' F_0: cp 0E5h ; если же первый символ - "Е" русского jr nz,F_1 ; алфавита, то установить его в ":" ld (hl),':' F_1: ld de,11 add hl,de set 1,(hl) ; В байте атрибутов установить бит 1 в 1 ld de,21 add hl,de Djnz Protect ld bc,Mess1 jr Finish ; Рассекречивание каталога ReSet: ld a,(hl) cp '!' ; Если первый символ элемента каталога jr nz,I_0 ; равен "!", то установить его в 0 ld (hl),0 I_0: cp ':' ; Если первый символ элемента каталога jr nz,I_1 ; равен ":", то установить его в "Е" ld (hl),0E5h I_1: ld de,11 add hl,de res 1,(hl) ; Рассекретить файл ld de,21 add hl,de Djnz ReSet ld bc,Mess2 ; Перед выходом в систему - запись измененных секторов на диск Finish: pop hl pop de push bc Bdos 30h pop de ; Сообщение, jr The_End ; конец программы ; Подпрограмма SearCHR ; Поиск символа в строке параметров, начиная с некоторой позиции ; Вход: b - код символа ; hl - позиция в строке (абсолютный адрес) ; Выход: если в a - не 255, ; то в hl - абсолютный адрес символа; ; иначе в hl - адрес конца строки (образец не найден). SearCHR: ld a,(hl) cp 13 jr z,NoFound cp b ret z inc hl jr SearCHR NoFound: ld a,255 ret Mess0: db 'Ошибка в строке параметров !',13,10 db 'Вызов: A> undir <ключи> <дисковод>',13,10 db ' <ключи> : - (спрятать)',13,10 db ' + (рассекретить)',13,10,'$' Mess1: db 'Каталог засекречен !',13,10,'$' Mess2: db 'Каталог рассекречен !',13,10,'$' Mess3: db 'Плохое имя дисковода !',13,10,'$' NewDMA EQU $ END ▌Небольшое пояснение. Если Вы заметили, наша программа различает, с чего начинается пустая входная точка каталога - с нуля или с "Е". Это было специально сделано для того, чтобы после засекречивания-рассекречивания директории диска не оставалось никаких следов работы этой программы. Предыдущий вариант этой утилиты не имел такой особенности. После рассекречивания все пус╨ тые входные точки начинались с кода Е5h, из-за чего очень сильно увели╨ чивалось время прочтения каталога ┬┬ система прочитывала все 112 имен файлов. Но стоит системе встретить входную точку, начинающуюся с нуля, она сразу прекращает просмотр каталога. Учитывая эту особенность, при совершенствовании программы мы несколько усложнили ее, заставив разли╨ чать начало входных точек Справочника. А теперь - внимание ! юМаленький фокус (для тех, кто захочет немного поработать со скрытыми файлами) Для того, чтобы найти в каталоге скрытый файл (с байтом атри╨ бутов, неравным нулю), установите старший бит (со значением 80h) в номере драйвера в единицу. Если, например, шаблон поиска расположен по адресу Pattern, то это можно сделать командами ассемблера: ld a,(Pattern) or 80h ld (Pattern),a . Теперь, пользуясь подпрограммами BDOS 'Search First' и 'Search Next', Вы легко найдете не только файлы без установленного байта атрибутов, но и 'скрытые' и др. файлы, находящиеся на диске.