Перейти на: Главную | Индексную | Форумную страницу |
Обычно нормальное закрытие файла приводит к занесению всех оставшихся в буфере записей на диск и корректировке оглавления. В особых случаях (между шагами программы или аварийном завершении) может потребоваться сброс диска. Функция DOS шест.D освобождает все файловые буфера и не корректирует оглавление диска. Если необходимо, то вначале данная функция закрывает все файлы. MOV AH,ODH ;Запрос на сброс диска INT 21H ;Вызов DOS Установка текущего дисковода: Шест.E -------------------------------------- Основное назначение функции DOS шест.E - установка номера текущего (по умолчанию) дисковода. Номер дисковода помещается в регистр DL, причем 0 соответствует дисководу A, 1 - B и т.д. MOV AH,OEH ;Запрос на установку MOV DL,02 ; дисковода C INT 21H ;Вызов DOS Операция возвращает в регистр AL число дисководов (независимо от типа). Так как для DOS необходимо по крайней мере 2 логических дисковода A и B, то DOS возвращает значение 02 и для систем с одним дисководом. (Для определения действительного числа дисководов используется команда INT 11H). Поиск элементов оглавления: шест.11 и 12 ------------------------------------------ Программной утилите может потребоваться поиск в оглавлении для доступа к имени файла, например, при удалении или переименовании. Для доступа к первому или единственному элементу оглавления необходимо загрузить в регистр DX адрес неоткрытого блока FCB и выполнить функцию 11H. При использовании расширенного блока FCB можно также получить код атрибута (см.техническое руководство по DOS). MOV AH,11H ;Запрос на первый элемент LEA DX,FCBname ;Неоткрытый FCB INT 21H ;Вызов DOS FCB может быть расположено по адресу 5CH в префиксе программного сегмента, предшествующем программе в памяти (DTA по умолчанию). Подробно см. гл.22. В регистре AL операция возвращает шест.FF, если элемент не найден, и шест.00, если найден. Операция устанавливает в DTA номер дисковода (1=A, 2=B и т.д.) имя файла и тип файла. Если найдено несколько элементов при выборке по шаблону (например, *.ASM), то для локализации элементов подмножества директории используется функция 12H: MOV AH,12H ;Запрос следующего элемента LEA DX,FCBname ;Неоткрытый FCB INT 21H ;Вызов DOS Коды возврата в регистре AL аналогичны кодам функции 11H. Удаление файла: шест.13 ------------------------- Для удаления файла в программе используется функция DOS 13H. Операция удаления устанавливает специальный байт в первой позиции имени файла в оглавлении. MOV AH,13H ;Запрос на удаление файла LEA DX,FCBname ;Неоткрытый FCB INT 21H ;Вызов DOS Если операция находит и удаляет элемент, то в регистре AL устанавливается код возврата 00, иначе код равен шест.FF. Переименование файла: шест.17 ------------------------------- Для переименования файла в программе используется функция DOS шест.17. Старое имя файла записывается в обычном месте блока FCB, а новое - начиная со смещения 16. MOV AH,17H ;Запрос на переименование LEA DX,FCBname ;Адрес FCB INT 21H ;Вызов DOS Символы ? и * в новом имени приводят к сохранению в соответствующих позициях символов из старого имени. Успешная операция устанавливает в регистре AL код возврата 00, а безуспешная (файл по старому имени не найден или по новому имени уже существует) - код FF. Получение текущего номера дисковода: шест.19 ---------------------------------------------- Функция DOS шест.19 позволяет определить текущий номер дисковода: MOV AH,19H ;Получить текущий дисковод INT 21H ;Вызов DOS Операция возвращает шест. номер дисковода в регистре AL (0=A, 1=B и т.д.). Полученное значение можно поместить непосредственно в FCB для доступа к файлу с текущего дисковода. Кроме перечисленных существуют функции для получения информации из таблицы FAT (1B и 10), установки поля прямой записи (24), установки вектора прерываний (25), создания нового программного сегмента (26) и анализа имени файла (29). Эти функции описаны в техническом руководстве по DOS. ПРОГРАММА: ВЫБОРОЧНОЕ УДАЛЕНИЕ ФАЙЛОВ ________________________________________________________________ __________________________________________________________________________ TITLE SELDEL (COM) Выборочное удаление файлов ; Предполагается текущий дисковод; ; Примеры параметров: *.*, *.BAK, и т.д. CODESG SEGMENT PARA 'Code' ASSUME CS:CODESG,DS:CODESG,SS:CODESG ORG 100H BEGIN JMP MAIN ; ---------------------------------------------------------- TAB EQU 09 LF EQU 10 CR EQU 13 CRLF DB CR,LF,'$' DELMSG DB TAB,'Erase','$' ENDMSG DB CR,LF,'No more directory entries',CR,LF,'$' ERRMSG DB 'Write protected disk','$' PROMPT DB 'y = Erase, N = Keep, Ret = Exit',CR,LF,'$' ; ---------------------------------------------------------- MAIN PROC NEAR ;Главная процедура MOV AH,11H ;Найти первый элемент CALL D10DISK CMP AL,0FFH ;Если нет элементов, JE A90 ; то выйти LEA DX,PROMPT ;Текст запроса CALL B10DISP A20: LEA DX,DELMSG ;Выдать сообщение CALL B10DISP ; об удалении файла MOV CX,11 ;11 символов MOV SI,81H ;Начало имени файла A30: MOV DL,[SI] ;Текущий символ CALL C10CHAR ; для вывода на экран INC SI ;Следующий символ LOOP A30 MOV DL,'?' CALL C10CHAR MOV AH,01 ;Получить односимвольный INT 21H ; ответ CMP AL,ODH ;Символ Return? JE A90 ; да - выйти OR AL,00100000B ;Перекодировать ; в прописную букву CMP AL,'y' ;Запрошено удаление? JNE A50 ; нет - обойти, MOV AH,13H ; да - удалить файл MOV DX,80H INT 21H CMP AL,0 ;Успешное удаление? JZ A50 ; да - обойти LEA DX,ERRMSG ; нет - выдать CALL B10DISP ; предупреждение JMP A90 A50: LEA DX,CRLF ;Перевести строку на экране CALL B10DISP MOV AH,12H CALL B10DISK ;Получить следующий элемент CMP AL,0FFH ;Есть еще? JNE A20 ; да - повторить A90: RET ;Выход в DOS MAIN ENDP ; Вывод строки на экран; ; --------------------- B10DISP PROC NEAR ;в DX находится адрес MOV AH,09 ; строки INT 21H RET B10DISP ENDP ; Вывод символа на экран; ; ---------------------- C10CHAR PROC NEAR ;в DL находится символ MOV AH,02 INT 21H RET C10CHAR ENDP ; Чтение элемента каталога: ; ------------------------ D10DISK PROC NEAR MOV DX,5CH ;Установить FCB INT 21H CMP AL,0FFH ;Есть еще элементы? JNE D90 PUSH AX ;Сохранить AL LEA DX,ENDMSG CALL B10DISP POP AX ;Восстановить AL D90: RET D10DISK ENDP CODESG ENDS END BEGIN __________________________________________________________________________ Рис.16.5. Выборочное удаление файлов. На рис.16.5 приведена COM-программа по имени SDEL, иллюстрирующая функции DOS 11H, 12H и 13H для удаления выбранных файлов. Для запроса на удаление файлов пользователь может ввести,например, следующие команды: SDEL *.* (все файлы) SDEL *.BAK (все BAK-файлы) SDEL TEST.* (все файлы по имени TEST) Посредством DOS программа определяет в оглавлении элементы, удовлетворяющие запросу. DOS заносит полное имя найденного элемента в PSP (префикс программного сегмента) по смещению шест.81 (DTA по умолчанию). Затем программа выводит на экран имя файла и запрос подтверждения. Ответ Y (да) разрешает удаление, N (нет) сохраняет файл, а Return завершает выполнение. Обратите внимание на то, что данная программа должна быть создана как COM-программа, так как EXE-программа требуют отличной адресации для использования смещений шест.5С и 81 в PSP. Для тестирования программы используйте скопированные временно файлы. ОСНОВНЫЕ ПОЛОЖЕНИЯ НА ПАМЯТЬ ________________________________________________________________ - Программа, использующая INT 21H в базовой версии DOS для операций ввода-вывода на диск, должна содержать блок управления файлом (FCB) для каждого доступного файла. - Один блок содержит 128 записей. Номер текущего блока и номер текущей записи в FCB указывают на дисковую запись, которая должна быть обработана. - В обратной последовательности байт в FCB записываются следующие элементы: номер текущего блока, размер записи, размер файла и относительный номер записи. - Все программы, обрабатывающие один и тот же файл, должны иметь одинаково описанный блок FCB. - Область ввода-вывода (DTA) определяется адресом памяти, куда должна быть помещена запись при чтении или откуда она заносится на диск. Прежде, чем выполнить операцию записи или чтения, в программе необходимо установить каждую область DTA. - Операция открытия файла устанавливает в блоке FCB значения для следующих элементов: имя файла, тип файла, размер записи (шест.80), размер файла и дата. Программа должна заменить размер записей на правильное значение. - Программа, использующая для записи файла операцию DOS INT 21H, должна закрыть файл в конце обработки для того, чтобы поместить на диск все оставшиеся в буфере записи (если таковые имеются) и скорректировать соответствующий элемент оглавления. - При использовании для чтения и записи операции DOS INT 21H система автоматически изменяет текущий номер записи в FCB. - Операция чтения по прерыванию DOS INT 21H проверяет наличие требуемой записи сначала в буфере и при отсутствии выполняет чтение с диска. - Прямой метод доступа требует указания номера записи в поле относительного номера записи блока FCB. - Восемь байт (двойное слово) относительного номера записи кодируются в обратной последовательности байт. - Если требуемая запись при прямом доступе уже находится в буфере, то система передает ее непосредственно в DTA. В противном случае выполняется чтение с диска в буфер всего сектора, содержащего необходимую запись. - Операции прямого блочного чтения и записи более эффективны при наличии достаточной памяти. Эти операции особенно удобны для загрузки таблиц. - Команды DOS INT 25H и 26H осуществляют дисковые операции абсолютного чтения и записи, но не поддерживают обработку оглавления, не определяют конец файла и не обеспечивают блокирование и деблокирование записей. ВОПРОСЫ ДЛЯ САМОПРОВЕРКИ ________________________________________________________________ 16.1. Напишите функции базовой версии DOS для следующих операций: а) создание файла, б) установка DTA, в) последовательная запись, г) открытие файла, д) последовательное чтение. 16.2. Программа использует размер записи, устанавливаемый при открытии файла по умолчанию. а) Сколько записей содержит один сектор? б) Сколько записей содержит дискета с тремя дорожками по девять секторов на каждой? в) Если на дискете (б) находится один файл, то при последовательном чтении сколько произойдет физических обращений к диску? 16.3. Напишите программу, которая создает дисковый файл, содержащий записи из трех элементов: номер товара (пять символов), наименование товара (12 символов) и стоимость единицы товара (одно слово). Ввод этих значений должен осуществляться пользователем с клавиатуры. Не забудьте преобразовать числа из ASCII представления в двоичное представление. 16.4. Напишите программу, которая выводит на экран файл, созданный в вопросе 16.3. 16.5. Определите текущий блок и запись для следующих номеров записей при прямом доступе: а)45, б)73, в)150, г)260. 16.6. В каком виде номер записи 2652 (десятичное) устанавливается в поле относительной записи блока FCB? 16.7. Укажите шестнадцатеричные номера функций для следующих операций: а) прямая запись, б) прямое чтение, в) прямая блочная запись, г) прямое блочное чтение. 16.8. Напишите команды для определения числа записей файла, предполагая, что операция открытия уже выполнена. Имена полей с размером файла FCB FLSZ и размером записи FCB FCSZ. 16.9. Используя программу из вопроса 16.4 для создания файла с количеством, ценами и наименованиями товаров, сформируйте файл с приведенными ниже данными. Напишите программу, которая выполняет одно блочное чтение данного файла и выводит каждую запись на экран. Номер Цена Наименование 023 00315 Ассемблеры 024 00430 Компоновщики 027 00525 Компиляторы 049 00920 Компрессоры 114 11250 Экстракторы 117 00630 Буксиры 122 10520 Лифты 124 21335 Процессоры 127 00960 Станки для наклеивания меток 232 05635 Черпатели? 999 00000 16.10. Измените программу из вопроса 16.9 так, чтобы цены записывались на диск в двоичном формате. 16.11. Измените программу из вопроса 16.9 так, чтобы а) использовалась операция прямого чтения, б) пользователь мог вводить номер и количество товара и в) выполнялось вычисление и вывод на экран стоимости (произведение количества товара на стоимость единицы товара). ГЛАВА 17 Дисковая память III: Расширенные функции DOS __________________________________________________________________________ Ц е л ь: Ознакомить с расширенными функциями DOS, начиная с версии 2.0 для обработки дисковых файлов. ВВЕДЕНИЕ ________________________________________________________________ Функции базовой версии DOS для обработки файлов, показанные в главе 16, действительны для всех последующих версий DOS. В данной главе показаны ряд расширенных функций, введенных в версиях DOS 2.0 и 3.0 и не поддерживаемых в ранних версиях. Прежде, чем пытаться выполнить дисковые операции из данной главы, следует убедиться в наличии необходимой версии DOS. Многие из расширенных функций проще своих аналогов в базовой версии DOS. В руководствах по DOS рекомендуется использовать новые функции, которые более естественны для систем типа UNIX. Некоторые операции включают использование строк в формате ASCIIZ для начальной установки дисковода, пути доступа и имени файла; номера файла для последовательного доступа к файлу; специальных кодов возврата. ДАННЫЕ В ФОРМАТЕ ASCIIZ ________________________________________________________________ При использовании многих расширенных функций для дисковых операций необходимо сообщить DOS адрес строки в формате ASCIIZ, содержащей идентификацию файла в виде номера дисковода, пути доступа и имени файла (все параметры необязательные) и строка должна завершаться шестнадцатеричным нулем, например: PATHNM1 DB 'B:\TEST.ASM',0 PATHNM2 DB 'C:\UTILITY\NU.EXE',0 Обратная косая (или прямая косая) используются в качестве разделителя. Нулевой байт (zero) завершает строку (отсюда название ASCIIZ формата). Для прерываний, использующих в качестве параметра ASCIIZ строку, адрес этой строки загружается в регистр DX, например, командой LEA DX,PATHNM1. ФАЙЛОВЫЙ НОМЕР И КОДЫ ВОЗВРАТА ________________________________________________________________ Операции создания и открытия файла требуют загрузки в регистр AX двухбайтового числа, представляющего собой файловый номер. В главе 8 показано, что стандартные устройства не нуждаются в операции открытия и могут использовать непосредственно файловые номера: 0 - ввод, 1 - вывод, 2 - вывод сообщений об ошибках, 3 - внешнее устройство, 4 - принтер. Для доступа к диску при создании или открытии файла используется ASCIIZ строка и функции DOS шест.3C или 3D. Успешная операция устанавливает флаг CF в 0 и помещает файловый номер в регистр AX. Этот номер необходимо сохранить в элементе данных DW и использовать его для всех последующих операций над дисковым файлом. При неуспешной операции флаг CF устанавливается в 1, а в регистр AX помещается код ошибки, зависящий от операции (см.табл.17.1). __________________________________________________________________________ 01 Ошибка номера функции 02 Файл не найден 03 Путь доступа не найден 04 Открыто слишком много файлов 05 Нет доступа (Операция отвергнута) 06 Ошибка файлового номера 07 Блок управления памятью разрушен 08 Недостаточно памяти 09 Ошибка адреса блока памяти 10 Ошибка оборудования 11 Ошибка формата 12 Ошибка кода доступа 13 Ошибка данных 15 Ошибка дисковода 16 Попытка удалить оглавление 17 Другое устройство ? 18 Нет больше файлов __________________________________________________________________________ Таб.17.1. Коды ошибок СОЗДАНИЕ ДИСКОВОГО ФАЙЛА ________________________________________________________________ В последующих разделах раскрыты требования к созданию, записи и закрытию дисковых файлов для расширенной версии DOS. Создание файла: Шест.3C ------------------------- Для создания нового файла или переписывания старого файла используется функция шест.3C. При этом регистр DX должен содержать адрес ASCIIZ-строки, а регистр CX - необходимый атрибут. Байт атрибут был рассмотрен в главе 15; для обычного файла значение атрибута - 0. Рассмотрим пример создания обычного файла: MOV AH,3CH ;Запрос на создание MOV CX,00 ; обычного файла LEA DX,PATHNM1 ;ASCIIZ строка INT 21H ;Вызов DOS JC error ;Переход по ошибке MOV HANDLE1,AX ;Сохранение файлового номера в DW При правильном открытии операция создает элемент оглавления с данным атрибутом, очищает флаг CF и устанавливает файловый номер в регистре AX. Этот номер должен использоваться для всех последующих операций. Если создаваемый файл уже существует (т.е. имя файла присутствует в оглавлении), то длина этого файла устанавливается в 0 для перезаписи. В случае возникновения ошибки операция устанавливает флаг CF в 1 и помещает в регистр AX код возврата: 03, 04 или 05 (см.табл.17.1). Код 05 свидетельствует либо о переполнении оглавления, либо о защите существующего файла атрибутом "только чтение". При завершении операции необходимо сначала проверить флаг CF, так как при создании файла возможна установка в регистре AX файлового номера 0005, который можно легко спутать с кодом ошибки 05 (нет доступа). Запись файла: шест.40 ----------------------- Для записи файла используется функция DOS шест.40. При этом в регистре BX должен быть установлен файловый номер, в регистре CX - число записываемых байт, а в регистре DX - адрес области вывода. В следующем примере происходит запись 256 байт из области OUTREC: HANDLE1 DW ? OUTREC DB 256 DUP (' ') MOV AH,40H ;Запрос записи MOV BX,HANDLE1 ;Файловый номер MOV CX,256 ;Длина записи LEA DX,OUTREC ;Адрес области вывода INT 21H ;Вызов DOS JC error2 ;Проверка на ошибку CMP AX,256 ;Все байты записаны? JNE error3 Правильная операция записывает из памяти на диск все данные (256 байт), очищает флаг CF и устанавливает в регистре AX число действительно записанных байтов. Если диск переполнен, то число записанных байтов может отличаться от заданного числа. В случае неправильной операции флаг CF устанавливается в 1, а в регистр AX заносится код 05 (нет доступа) или 06 (ошибка файлового номера). Закрытие файла: шест.3E -------------------------- После завершения записи файла необходимо установить файловый номер в регистр BX и, используя функцию DOS шест.3E, закрыть файл. Эта операция записывает все оставшиеся еще данные из буфера на диск и корректирует оглавление и таблицу FAT. MOV AH,3EH ;Запрос на закрытие файла MOV BX,HANDLE1 ;Файловый номер INT 21H ;Вызов DOS В случае ошибки в регистре AX устанавливается код 06 (неправильный файловый номер). ПРОГРАММА:ИСПОЛЬЗОВАНИЕ ФАЙЛОВОГО НОМЕРА ДЛЯ СОЗДАНИЯ ФАЙЛА. ________________________________________________________________ __________________________________________________________________________ page 60,132 TTILE HANCREAT (EXE) Создание файла на диске ; ----------------------------------------------------- STACKSG SEGMENT PARA STACK 'Stack' DW 80 DUP(?) STACKSG ENDS ; ----------------------------------------------------- DATASG SEGMENT PARA 'Data' NAMEPAR LABEL BYTE ;Список параметров: MAXLEN DB 30 ; NAMELEN DB ? ; NAMEREC DB 30 DUP(' '), 0DH, 0AH ; введенное имя, CR/LF для записи ERRCDE DB 00 HANDLE DW ? PATHNAM DB 'D:\NAMEFILE.DAT',0 PROMPT DB 'Name? ' ROW DB 01 OPNMSG DB '*** Open error ***', 0DH, 0AH WRTMSG DB '*** Write error ***', 0DH, 0AH DATASG ENDS ; ------------------------------------------------------- CODESG SEGMENT PARA 'Code' BEGIN PROC FAR ASSUME CS:CODESG,DS:DATASG,SS:STACKSG,ES:DATASG PUSH DS SUB AX,AX PUSH AX MOV AX,DATASG MOV DS,AX MOV ES,AX MOV AX,0600H CALL Q10SCR ;Очистка экрана CALL Q20CURS ;Установка курсора CALL C10CREA ;Создание файла, установка DTA CMP ERRCDE,00 ;Ошибка при создании? JZ A20LOOP ; да - продолжить, RET ; нет - вернуться в DOS A20LOOP: CALL D10PROC CMP NAMELEN,00 ;Конец ввода? JNE A20LOOP ; нет - продолжить, CALL G10CLSE ; да - закрыть файл RET ; и выйти в DOS BEGIN ENDP ; Создание файла на диске: ; ----------------------- C10CREA PROC NEAR MOV AH,3CH ;Функция создания файла MOV CX,00 ;Нормальный атрибут LEA CX,PATHNAM INT 21H JC C20 ;Есть ошибка? MOV HANDLE,AX ; нет - запомнить номер, RET C20: ; да - LEA DX,OPNMSG ; выдать сообщение CALL X10ERR ; об ошибке RET C10CREA ENDP ; Ввод с клавиатуры: ; ----------------- D10PROC PROC NEAR MOV AH,40H ;Функция вывода на экран MOV BX,01 ;Номер (Handle) MOV CX,06 ;Длина текста запроса LEA DX,PROMPT ;Выдать запрос INT 21H MOV AH,0AH ;Функция ввода с клавиатуры LEA DX,NAMEPAR ;Список параметров INT 21H CMP NAMELEN,00 ;Имя введено? JNE D20 ; да - обойти RET ; нет - выйти D20: MOV AL,20H ;Пробел для заполнения SUB CH,CH MOV CL,NAMELEN ;Длина LEA DI,NAMEREC ; ADD DI,CX ;Адрес + длина NEG CX ;Вычислить ADD CX,30 ; оставшуюся длину REP STOSB ;Заполнить пробелом D90: CALL F10WRIT ;Запись на диск CALL E10SCRL ;Проверка на скроллинг RET D10PROC ENDP ; Проверка на скроллинг: ; --------------------- E10SCRL PROC NEAR CMP ROW,18 ;Последняя строка экрана JAE E10 ; да - обойти, INC ROW ; нет - увеличить строку JMP E10 E10: MOV AX,0601H ;Продвинуть на одну строку CALL Q10SCR E90: CALL Q20CURS ;Установка курсора RET E10SCRL ENDP ; Запись на диск: ; -------------- F10WRIT PROC NEAR MOV AH,40H ;Функция записи на диск MOV BX,HANDLE MOV CX,32 ;30 для имени + 2 для CR/LF LEA DX,NAMEREC INT 21H JNC F20 ;Ошибка записи? LEA DX,WRTMSG ; да - CALL X10ERR ; выдать предупреждение MOV NAMELEN,00 F20: RET F10WRIT ENDP ; Закрытие файла на диске: ; ----------------------- G10CLSE PROC NEAR MOV NAMEREC,1AH ;Маркер конца записи (EOF) CALL F10WRIT MOV AH,3EH ;Функция закрытия MOV BX,HANDLE INT 21H RET G10CLSE ENDP ; Прокрутка (скроллинг) экрана: ; ---------------------------- Q10SCR PROC NEAR ;в AX - адрес элемента MOV BH,1EH ;Цвет - желтый на синем MOV CX,0000 MOV DX,184FH INT 10H ;Скроллинг RET Q10SCR ENDP ; Установка курсора: ; ----------------- Q20CURS PROC NEAR MOV AH,02 MOV BH,00 MOV DH,ROW ;Установить курсор MOV DL,00 INT 10H RET Q20CURS ENDP ; Вывод сообщения об ошибке: ; ------------------------- X10ERR PROC NEAR ;DX содержит MOV AH,40H ; адрес сообщения MOV BX,01 MOV CX,21 ;Длина сообщения INT 21H MOV ERRCDE,01 ;Установить код ошибки RET X10ERR ENDP CODESG ENDS END BEGIN __________________________________________________________________________ Рис.17.2. Использование файлового номера для создания файла. Программа, приведенная на рис.17.2, создает файл по имени, которое вводится пользователем с клавиатуры. В программе имеются следующие основные процедуры: C10CREA Использует функцию шест.3C для создания файла и сохраняет файловый номер в элементе данных по имени HANDLE. D10PROC Принимает ввод с клавиатуры и очищает пробелом байты от конца введенного имени до конца области ввода. F10WRIT Записывает файл, используя функцию шест.40. G10CLSE В завершении обработки, используя функцию шест.3E,закрывает файл для того, чтобы создать правильный элемент оглавления. Область ввода имеет длину 30 байтов и завершается двумя байтами: возврат каретки (шест.0DH) и конец строки (шест.0AH). Таким образом общая длина области ввода - 32 байта. Программа переносит на диск 32-x байтовые записи, как записи фиксированной длины. Можно опустить байты "возврат каретки" и "конец строки", но включить их, если потребуется сортировка файла. Программа DOS SORT требует наличия этих байтов для индикации конца записей. Для нашего примера команда SORT может выглядеть следующим образом: SORT B:NAMEFILE.SRT В результате выполнения данной команды записи из файла NAMEFILE.DAT в возрастающей последовательности будут помещены в файл NAMEFILE.SRT. Программа, приведенная на рис.17.3 выполняет чтение записей из файла NAMEFILE.SRT и вывод их на экран. Обратите внимание на два момента: 1) Символы возврат каретки и конец строки включены в конце каждой записи только для выполнения сортировки и в других случаях могут быть опущены. 2) Записи могут иметь переменную длину (по длине вводимых с клавиатуры имен); эта особенность включает некоторое дополнительное программирование, как это будет показано на рис.17.4. ЧТЕНИЕ ДИСКОВОГО ФАЙЛА ________________________________________________________________ В следующих разделах раскрыты требования для открытия и чтения дисковых файлов в расширенной версии DOS. Открытие файла: шест.3D ------------------------- Если в программе требуется прочитать дисковый файл, то прежде необходимо открыть его, используя функцию шест.3D. Эта операция проверяет правильность имени файла и его наличие на диске. При открытии регистр DX должен содержать адрес необходимой ASCIIZ-строки, а регистр AL - код доступа: 0 Открыть файл только для ввода 1 Открыть файл только для вывода 2 Открыть файл для ввода и вывода Остальные биты регистра AL используются для разделения файлов DOS версии 3.0 и старше (см.техническое руководство по DOS). Обратите внимание, что для записи файла используется функция создания (шест.3C), но не функция открытия файла. Ниже приведен пример открытия файла для чтения: MOV AH,3DH ;Запрос на открытие MOV AL,00 ;Только чтение LEA DX,PATHNM1 ;Строка в формате ASCIIZ INT 21H ;Вызов DOS JC error4 ;Выход по ошибке MOV HANDLE2,AX ;Сохранение номера в DW Если файл с необходимым именем существует, то операция открытия устанавливает длину записи равной 1, принимает существующий атрибут, сбрасывает флаг CF и заносит файловый номер в регистр AX. Файловый номер используется в дальнейшем для всех последующих операций. Если файл отсутствует, то операция устанавливает флаг CF и заносит в регистр AX код ошибки: 02, 04, 05 или 12 (см. рис.17.1). Не забывайте проверять флаг CF. При успешном создании файла система может установить в регистре AX файловый номер 0005, что легко можно спутать с кодом ошибки 05 (нет доступа). Чтение файла: Шест.3F ----------------------- Для чтения записей файла используется функция DOS шест.3F. При этом необходимо установить в регистре BX файловый номер, в регистре CX - число байтов и в регистре DX - адрес области ввода. В следующем примере происходит считывание 512-байтовой записи: HANDLE2 DW ? INPREC DB 512 DUP (' ') MOV AH,3FH ;Запрос на чтение MOV BX,HANDLE2 ;Файловый номер MOV CX,512 ;Длина записи LEA DX,INPREC ;Адрес области ввода INT 21H ;Вызов DOS JC error5 ;Проверка на ошибку CMP AX,00 ;Прочитано 0 байтов? JE endfile Правильно выполненная операция считывает запись в память, сбрасывает флаг CF и устанавливает в регистре AX число действительно прочитанных байтов. Нулевое значение в регистре AX обозначает попытку чтения после конца файла. Ошибочная операция устанавливает флаг CF и возвращает в регистре AX код ошибки 05 (нет доступа) или 06 (ошибка файлового номера). Так как DOS ограничивает число одновременно открытых файлов, то программа, успешно отработавшая с несколькими файлами, должна закрывать их. ПРОГРАММА: ИСПОЛЬЗОВАНИЕ ФАЙЛОВОГО НОМЕРА ДЛЯ ЧТЕНИЯ ФАЙЛА ________________________________________________________________ __________________________________________________________________________ page 60,132 TITLE HANREAD (EXE) Чтение записей, созданных в HANCREAT ; ----------------------------------------------------- STACKSG SEGMENT PARA STACK 'Stack' DW 80 DUP(?) STACKSG ENDS ; ----------------------------------------------------- DATASG SEGMENT PARA 'Data' ENDCDE DB 00 HANDLE DW ? IOAREA DB 32 DUP(' ') PATHNAM DB 'D:\NAMEFILE.SRT',0 OPENMSG DB '*** Open error ***', 0DH, 0AH READMSG DB '*** Read error ***', 0DH, 0AH ROW DB 00 DATASG ENDS ; ------------------------------------------------------ CODESG SEGMENT PARA 'Code' BEGIN PROC FAR ASSUME CS:CODESG,DS:DATASG,SS:STACKSG,ES:DATASG PUSH DS SUB AX,AX PUSH AX MOV AX,DATASG MOV DS,AX MOV ES,AX MOV AX,0600H CALL Q10SCR ;Очистить экран CALL Q20CURS ;Установить курсор CALL E100PEN ;Открыть файл, ; ; установить DTA CMP ENDCDE,00 ;Ошибка открытия? JNZ A90 ; да - завершить программу A20LOOP: CALL F10READ ;Чтение записи с диска CMP ENDCDE,00 ;Ошибка чтения? JNZ A90 ; да - выйти, CALL G10DISP ; нет - выдать имя, JMP A20LOOP ; и продолжить A90: RET BEGIN ENDP ; Открытие файла: ; -------------- E100PEN PROC NEAR MOV AH,3DH ;Функция открытия MOV CX,00 ;Нормальные атрибуты LEA DX,PATHNAM INT 21H JC E20 ;Ошибка открытия? MOV HANDLE,AX ; нет - сохранить RET ; файловый номер E20: MOV ENDCDE,01 ; да - выдать LEA DX,OPENMSG ; сообщение об ошибке CALL X10ERR RET E100PEN ENDP ; Чтение дисковой записи: ; ---------------------- F10READ PROC NEAR MOV AX,3FH ;Функция чтения MOV BX,HANDLE MOV CX,32 ;30 для имени, 2 для CR/LF LEA DX,IOAREA INT 21H JC F20 ;Ошибка при чтении? CMP AX,00 ;Конец файла? JE F30 CMP IOAREA,1AH ;Маркер конца файла (EOF)? JE F30 ; да - выйти RET F20: LEA DX,READMSG ; нет - выдать CALL X10ERR ; сообщение об ошибке F30: MOV ENDCDE,01 ;Код завершения F90: RET F10READ ENDP ; Вывод имени на экран: ; -------------------- G10DISP PROC NEAR MOV AH,40H ;Функция вывода на экран MOV BX,01 ;Установить номер MOV CX,32 ; и длину LEA DX,IOAREA INT 21H CMP ROW,20 ;Последняя строка экрана? JEA G90 ; да - обойти INC ROW RET G90: MOV AX,0601H CALL Q10SCR ;Прокрутка (скроллинг) CALL Q20CURS ;Установить курсор RET G10DISP ENDP ; Прокрутка (скроллинг) экрана: ; ---------------------------- Q10SCR PROC NEAR ;в AX - адрес элемента MOV BH,1EH ;Установить цвет MOV CX,0000 MOV DXX,184FH ;Функция прокрутки INT 10H RET Q10SCR ENDP ; Установка курсора: ; ----------------- Q20CURS PROC NEAR MOV AH,02 ;Функция установки курсора MOV BH,00 ; курсор MOV DH,ROW ; строка MOV DL,00 ; столбец INT 10H RET Q20CURS ENDP ; Вывод сообщения об ошибке: ; ------------------------- X10ERR PROC NEAR MOV AH,40H ;в DX - адрес сообщения MOV BX,01 ;Номер MOV CX,20 ;Длина сообщения INT 21H RET X10ERR ENDP CODESG ENDS END BEGIN __________________________________________________________________________ Рис.17.3. Использование файлового номера для чтения файла. На рис.17.3 приведена программа, которая читает файл, созданный предыдущей программой (см.рис.17.2) и отсортированный командой DOS SORT. Для открытия файла используется функция шест.3D. Полученный в результате файловый номер заносится в поле HANDLE и используется затем в функции шест.3F для чтения файла. В программе нет необходимости переносить курсор на новую строку, так как записи содержат в конце символы "возврат каретки" и "новая строка". ASCII-ФАЙЛЫ (ФАЙЛЫ В ФОРМАТЕ ASCII) ________________________________________________________________ В предыдущих примерах были показаны операции создания и чтения файлов. Аналогичным образом можно обрабатывать ASCII-файлы (текстовые файлы), созданные DOS или редактором. Для этого необходимо знать организацию оглавления и таблицы FAT, а также способ записи данных в сектор диска, используемый системой. Система DOS записывает, например, ASM-файл в точном соответствии с вводом с клавиатуры, включая символы табуляции (шест.09), возврат каретки (шест.OD) и конец строки (шест.OA). Для экономии дисковой памяти DOS не записывает пробелы, которые находятся на экране и предшествуют символу табуляции, и пробелы, находящиеся в строке справа от символа "возврат каретки". Следующий пример иллюстрирует ассемблерную команду, как она может выглядеть на экране: MOVAH,09 Для такой строки содержимое ASCII-файла будет: 094D4F560941482C30390D0A Когда программа TYPE или редактор читают файл и выводят на экран символы "табуляция", "возврат каретки" и "конец строки" автоматически выравнивают данные. Рассмотрим программу, приведенную на рис.17.4, которая читает и выводит на экран файл HANREAD.ASM (пример на рис. 17.3) по секторам. Если программа HANREAD уже введена и проверена, то можно просто скопировать ее в файл с новым именем. __________________________________________________________________________ page 60,132 TITLE ASCREAD (COM) Чтение ASCII файла CODESG SEGMENT PARA 'Code' ASSUME CS:CODESG,DS:CODESG,SS:CODESG,ES:CODESG ORG 100H BEGIN: JMP MAIN ; ------------------------------------------------- SECTOR DB 512 DUP(' ') ;Область ввода DISAREA DB 120 DUP(' ') ;Область вывода на экран ENDCDE DW 00 HANDLE DW 0 OPENMSG DB '*** Open error ***' PATHNAM DB 'D:\HANREAD.ASM', 0 ROW DB 00 ; ------------------------------------------------- MAIN PROC NEAR ;Основная программа MOV AX,0600H CALL Q10SCR ;Очистить экран CALL Q20CURS ;Установить курсор CALL E10OPEN ;Открыть файл, ; установить DTA CMP ENDCDE,00 ;Ошибка при открытии? JNE A90 ; да - выйти, A20LOOP: ; нет - продолжить CALL R10READ ;Чтение первого сектора CMP ENDCDE,00 ;Конец файла, нет данных? JE A90 ; да - выйти CALL G10XPER ;Выдать на экран A90: RET ;Завершить программу MAIN ENDP ; Открыть файл на диске: ; --------------------- E10OPEN PROC NEAR MOV AH,3DH ;Функция открытия MOV AL,00 ;Только чтение LEA DX,PATHNAM INT 21H JNC E20 ;Проверить флаг CF CALL X10ERR ; ошибка, если установлен RET E20: MOV HANDLE,AX ;Запомнить номер файла RET E10OPEN ENDP ; Построчный вывод данных на экран: ; -------------------------------- G10XPER PROC NEAR CLD ;Направление слева-направо LEA SI,SECTOR G20: LEA DI,DISAREA G30: LEA DX,SECTOR+512 CMP SI,DX ;Конец сектора? JNE G40 ; нет - обойти, CALL R10READ ; да - читать следующий CMP ENDCDE,00 ;Конец файла? JE G80 ; да - выйти LEA SI,SECTOR G40: LEA DX,DISAREA+80 CMP DI,DX ;Конец DISAREA? JB G50 ; нет - обойти, MOV [DI],0D0AH ; да - установить CR/LF CALL H10DISP ; и выдать на экран LEA DI,DISAREA G50: LODSB ;Загрузить [SI] в AL ; и увеличить SI STOSB ;Записать AL в [DI] ; и увеличить DI CMP AL,1AH ;Конец файла? JE G80 ; да - выйти CMP AL,0AH ;Конец строки? JNE G30 ; нет - повторить цикл, CALL H10DISP ; да - вывести на экран JMP G20 G80: CALL H10DISP ;Вывести последнюю строку G90: RET G10XPER ENDP ; Вывод строки на экран: ; --------------------- H10DISP PROC NEAR MOV AH,40H ;Функция вывода на экран MOV BX,01 ;Номер (Handle) LEA CX,DISAREA ;Вычислить NEG CX ; длину ADD CX,DI ; строки LEA DX,DISAREA INT 21H CMP ROW,22 ;Последняя строка экрана? JAE H20 ; нет - выйти INC ROW JMP H90 H20: MOV AX,0601H ;Прокрутка (скроллинг) CALL Q10SCR CALL Q20CURS H90: RET H10DISP ENDP ; Чтение дискового сектора: ; ------------------------ R10READ PROC NEAR MOV AH,3FH ;Функция чтения MOV BX,HANDLE ;Устройство MOV CX,512 ;Длина LEA DX,SECTOR ;Буфер INT 21H MOV ENDCDE,AX RET R10READ ENDP ; Прокрутка (скроллинг) экрана: ; ---------------------------- Q10SCR PROC NEAR ;в AX адрес элемента MOV BH,1EH ;Установить цвет MOV CX,0000 ;Прокрутка MOV DX,184FH INT 10H RET Q10SCR ENDP ; Установка курсора: ; ----------------- Q20CURS PROC NEAR MOV AH,02 ;Функция MOV BH,00 ; установки курсора MOV DH,ROW MOV DL,00 INT 10H RET Q20CURS ENDP ; Вывод сообщения об ошибке на диске: ; ---------------------------------- X10ERR PROC NEAR MOV AH,40H ;Функция вывода на экран MOV BX,01 ;Номер устройства MOV CX,18 ;Длина LEA DX,OPENMSG INT 21H MOV ENDCDE,O1 ;Индикатор ошибки RET X10ERR ENDP CODESG ENDS END BEGIN __________________________________________________________________________ Рис.17.4. Чтение ASCII-файла. Программа выполняет в основном те же функции, что и DOS TYPE, т.е. выводит на экран каждую запись до символов "возврат каретки" и "конец строки" (CR/LE). Прокрутка содержимого экрана (скроллинг) вызывает некоторые проблемы. Если в программе не будет предусмотрено специальной проверки на конец экрана, то вывод новых строк будет осуществляться поверх старых и при короткой длине старые символы будут оставаться справа от новой строки. Для правильной прокрутки необходимо подсчитывать строки и контролировать достижение конца экрана. Так как строки ASCII-файла имеют переменную длину, то следует определять конец каждой строки прежде, чем выводить ее на экран. Рассматриваемая программа считывает полный сектор данных в область SECTOR. Процедура G10XFER передает данные побайтно из области SECTOR в область DISAREA, откуда они будут выдаваться на экран. При обнаружении символа "конец строки", процедура выводит на экран содержимое DISAREA, включая "конец строки". (Экран дисплея принимает также символы табуляции (шест.09) и автоматически устанавливает курсор в следующую справа позицию кратную 8). В программе необходимо проверять конец сектора (для считывания следующего) и конец области вывода. Для стандартных ASCII-файлов, таких как ASM-файлы, каждая строка имеет относительно короткую длину и гарантировано завершается парой символов CR/LF. Нетекстовые файлы, такие как EXE или OBJ, не имеют строк и поэтому рассматриваемая программа должна проверять достижение конца области DISAREA во избежание разрушения. Хотя программа предназначена для вывода на экран только ASCII-файлов, она имеет проверку для страховки от всяких неожиданных несимвольных файлов. Процедура G10XFER выполняет следующее: 1. Инициализирует адрес области SECTOR. 2. Инициализирует адрес области DISAREA. 3. При достижении конца области SECTOR считывает следующий сектор. В случае конца файла, завершает работу программы, иначе инициализирует адрес области SECTOR. 4. При достижении конца области DISAREA вставляет символы CR/LF, выводит строку на экран и инициализирует адрес DISAREA. 5. Переписывает символ из области SECTOR в область DISAREA. 6. По символу "конец файла" (шест.1A) завершает работу программы. 7. По символу "конец строки" (шест.OA) выводит на экран строку и переходит на п.2, по другим символам идет на п.3. Попробуйте выполнить эту программу в отладчике DEBUG. При каждом вводе с диска просмотрите содержимое области ввода и обратите внимание на то, как DOS форматирует записи. Для улучшения данной программы организуйте вывод на экран запроса для указания пользователем имени и типа файла. ДРУГИЕ ДИСКОВЫЕ ФУНКЦИИ В РАСШИРЕННОЙ ВЕРСИИ DOS ________________________________________________________________ Получение размера свободного дискового пространства: шест.36 -------------------------------------------------------------- Данная функция выдает информацию о дисковой памяти. Для выполнения функции необходимо загрузить в регистр DL номер дисковода (0 - текущий дисковод, 1 - A, 2 - B и т.д.): MOV AH,36H ;Запрос на MOV DL,0 ; текущий дисковод INT 21H ;Вызов DOS При указании неправильного номера дисковода операция возвращает в регистре AX шест.FFFF, иначе следующие значения: в AX число секторов на кластер, в BX число доступных кластеров, в CX число байтов на сектор, в DX общее число кластеров на дисководе. В версии DOS младше 2.0 для получения информации о дисковой памяти следует использовать функцию шест.1B (получить информацию из таблицы FAT). Удаление файла: шест.41 ------------------------- Для удаления файлов из программы (за исключением файлов с атрибутом "только чтение") используется функция шест.41. При этом в регистре DX необходимо загрузить ASCIIZ строку, содержащую путь доступа и имя файла: MOV AH,41H ;Запрос на удаление LEA DX,PATHNAM ;ASCIIZ-строка INT 21H ;Вызов DOS В случае ошибки в регистре AX возвращается код 02 (файл не найден) или 05 (нет доступа). Управление файловым указателем: шест.42 ----------------------------------------- Система DOS имеет файловый указатель, который при открытии файла устанавливается в 0 и увеличивается на 1 при последовательных операциях записи или считывания. Для доступа к любым записям внутри файла можно менять файловый указатель с помощью функции шест.42, получая в результате прямой доступ к записям файла. Для установки файлового указателя необходимо поместить в регистр BX файловый номер и в регистровую пару CX:DX требуемое смещение в байтах. Для смещений до 65.535 в регистре CX устанавливается 0, а в DX - смещение. В регистре AL должен быть установлен один из кодов, который определяет точку отсчета смещения: 0 - смещение от начала файла. 1 - смещение текущего значения файлового указателя, которое может быть в любом месте, включая начало файла. 2 - смещение от конца файла. Размер файла (и следовательно смещение до конца файла) можно определить, установив регистровую пару CX:DX в 0 и используя код 2 в регистре AL. В следующем примере устанавливается файловый указатель на смещение 1024 байта от начала файла: MOV AH,42H ;Установка указателя MOV AL,00 ; от начала файла LEA BX,HANDLE1 ;Установка файлового номера MOV CX,00 ; MOV DX,1024 ;Смещение 1024 байта INT 21H ;Вызов DOS JC error Правильно выполненная операция сбрасывает флаг CF и возвращает новый указатель в регистровой паре DX:AX. Неправильная операция устанавливает флаг CF в 1 и возвращает в регистре AX код 01 (ошибка кода отсчета) или 06 (ошибка файлового номера). Проверка или изменение атрибута: шест.43 ------------------------------------------ Для проверки или изменения файлового атрибута в оглавлении диска используется функция шест.43H. При этом в регистре DX должен быть установлен адрес ASCIIZ строки. Для проверки атрибута регистр AL должен содержать 00. Для изменения атрибута регистр AL должен содержать 01, а регистр CX - новое значение атрибута. Следующий пример устанавливает нормальный атрибут: MOV AH,43H ;Запрос на установку MOV AL,01 ; нормального MOV CX,00 ; атрибута LEA DX,PATHNM2 ;ASCIIZ-строка INT 21H ;Вызов DOS В случае проверки функция возвращает текущий атрибут файла в регистре CX. В случае изменения функция устанавливает в соответствующем элементе оглавления атрибут из регистра CX. Неправильная операция возвращает в регистре AX коды ошибок 02, 03 или 05. Получить текущее оглавление: шест.47 -------------------------------------- Определение текущего оглавления для любого дисковода осуществляется с помощью функции шест.47. При этом необходимо определить область памяти достаточно большую, чтобы содержать пути доступа максимальной длины и загрузить адрес этой области в регистр DX. Регистр DL должен содержать номер дисковода: 0 - текущий, 1 - A, 2 - B и т.д. В результате выполнения операция помещает в область памяти имя текущей директории (без номера дисковода), например, в следующем виде: ASSEMBLE\EXAMPLES Нулевой байт (шест.00) идентифицирует конец составного имени пути доступа. Для корневой директории возвращаемое значение состоит только из одного байта - шест.00. Таким образом можно получить текущее имя пути доступа для любого файла в подоглавлении. Пример на рис.17.5 демонстрирует использование данной функции. __________________________________________________________________________ TITLE GETPATH (COM) Получить текущий каталог CODESG SEGMENT PARA 'Code' ASSUME CS:CODESG,DS:CODESG,ES:CODESG ORG 100H BEGIN: JMP SHORT MAIN ; ----------------------------------------------- PATHNAM DB 65 DUP(' ') ;Имя текущего пути доступа ; ----------------------------------------------- MAIN PROC NEAR MOV AH,19H ;Определить текущий диск INT 21H ADD AL,41H ;Заменить шест.номер MOV DL,AL ; на букву: 0=A, 1=B ... CAL B10DISP ;Выдать номер дисковода, MOV DL,':' CAL B10DISP ; двоеточие, MOV DL,'\' CAL B10DISP ; обратную косую MOV AH,47H ;Получить текущий каталог MOV DL,00 LEA SI,PATHNAM INT 21H A10LOOP: CMP BYTE PTR [SI],0 ;Конец имени пути доступа JE A20 ; да - выйти MOV AL,[SI] ;Выдать на экран MOV DL,AL ; имя пути доступа CALL B10DISP ; побайтно INC SI JMP A10LOOP A20: RET ;Выход в DOS MAIN ENDP B10DISP PROC NEAR MOV AH,02 ;в DL - адрес элемента INT 21H ;Функция вывода на экран RET B10DISP ENDP CODESG ENDS END BEGIN __________________________________________________________________________ Рис.17.5. Получить текущий каталог. Поиск файлов по шаблону: шест.4E и шест.4F -------------------------------------------- Данные функции аналогичны функциям шест. 11 и 12 базовой версии DOS. Функция 4E используется для начала поиска в оглавлении, а функция 4F - для продолжения. Для начала поиска в регистр DX необходимо загрузить адрес ASCIIZ-строки, содержащей имя пути доступа и шаблон поиска. Шаблон поиска может включать в себя символы ? и *. В регистре CX должно быть значение атрибута в любой комбинации битов (нормальный, оглавление, спрятанный или системный). MOV AH,4EH ;Запрос на начало поиска MOV CX,00H ;Нормальный атрибут LEA DX,PATHNM1 ;ASCIIZ-строка INT 21H ;Вызов DOS Если операция находит файл, удовлетворяющий шаблону поиска, то в текущий буфер DTA в FCB заполняется следующей информацией: 00 - резервировано DOS для последующего поиска 21 - атрибут файла 22 - время файла 24 - дата файла 26 - размер файла: младшее слово, затем старшее слово 30 - имя и тип в виде 13-байтовой ASCIIZ строки, завершаемой шест.00. В случае ошибки в регистре AX возвращается код 02 (не найдено) или 18 (нет больше файлов). Для продолжения поиска файлов (после функции шест.4E) используется функция 4F. Между этими функциями не следует нарушать содержимое DTA. MOV AH,4FH ;Запрос на продолжение поиска INT 21H ;Вызов DOS Единственно возможный код в регистре AX - 18 (нет больше файлов). Обе рассмотренные функции не меняют состояние флага CF. Переименование файла: шест.56 ------------------------------- Для переименования файла используется функция шест.56. При этом в регистр DX должен быть загружен адрес ASCIIZ-строки, содержащей старые значения дисковода, пути доступа, имени и типа файла, а в регистр DI (в действительности ES:DI) - адрес ASCIIZ-строки, содержащей новые значения дисковода, пути доступа, имени и типа файла. Если указывается номер дисковода, то он должен быть одинаков в обоих строках. Путь доступа может быть различным, поэтому данная операция может не только переименовывать файл, но и переносить его в другое подоглавление. MOV AH,56H ;Запрос на переименование файла LEA DX,oldstring ;DS:DX LEA DI,newstring ;ES:DI INT 21H ;Вызов DOS В случае ошибки регистр AX возвращает коды 03 (путь доступа не найден), 05 (нет доступа?) и 17 (разные дисководы). Другие функции DOS, имеющие отношение к дисковым файлам, включают создание подоглавления (шест.39), удаление элемента оглавления (шест.3A), изменение текущего оглавления (шест. 3B), управление вводом-выводом для устройств (шест.44), дублирование файлового номера (шест.45), принудительное дублирование файлового номера (шест.46), получение состояния проверки ? (шест.54). ОСНОВНЫЕ ПОЛОЖЕНИЯ НА ПАМЯТЬ ________________________________________________________________ - Многие функции расширенной версии DOS оперируют с ASCIIZ-строками, которые содержат путь доступа и завершаются байтом, содержащим шест.00. - Функции создания и открытия возвращают значение файлового номера, который используется для последующего доступа к файлу. - В случае ошибок многие функции устанавливают флаг CF и помещают код ошибки в регистр AX. - Как правило, функция создания используется для записи файла, а открытия - для чтения. - После того, как файл записан на диск, его необходимо закрыть для того, чтобы в оглавление были внесены соответствующие изменения. ВОПРОСЫ ДЛЯ САМОПРОВЕРКИ ________________________________________________________________ 17.1. Какие значения кодов возврата для ситуаций "файл не найден" и "ошибка файлового номера" ? 17.2. Определите ASCIIZ-строку по имени PATH1 для файла CUST.LST на дисководе C. 17.3. Для предыдущего файла (п.17.2) напишите команды а) определения элемента по имени CUSTHAN для файлового номера, б) создание файла, в) записи файла из области CUSTOUT (128 байт) и г) закрытия файла. Обеспечьте проверку на ошибки. 17.4. Для файла (п.17.3) напишите команды а) открытия файла и б) чтения файла в область CUSTIN. Обеспечьте контроль ошибок. 17.5. В каких случаях необходимо закрывать файл, который был открыт только для чтения ? 17.6. Измените программу на рис.17.4 так, чтобы пользователь мог вводить с клавиатуры имя файла, который необходимо выдать на экран. Обеспечьте возможность любого числа запросов и завершение программы только по пустому запросу, т.е. простому нажатию клавиши Return. ГЛАВА 18 Дисковая память IV: Функции BIOS __________________________________________________________________________ Ц е л ь: Показать основные требования к программированию функций BIOS для создания и чтения дисковых файлов. ВВЕДЕНИЕ ________________________________________________________________ Для дисковых операций можно программировать непосредственно на уровне BIOS, хотя BIOS и не обеспечивает автоматически использование оглавления или блокирование/деблокирование записей. Дисковая операция BIOS INT 13H рассматривает все "записи", как имеющие размер сектора, а адресацию диска осуществляет в терминах действительных номера дорожки и номера сектора. Для дисковых операций чтения, записи и верификации необходима инициализация следующих регистров: AH Определяет тип операции: чтение, запись, верификация или форматирование. AL Определяет число секторов. CH Определяет номер дорожки. CL Определяет номер начального сектора. DH Номер головки (стороны) : 0 или 1 для дискеты. DL Номер дисковода: 0=A, 1=B и т.д. ES:BX Адрес буфера ввода/вывода в области данных (за исключением операции верификации). ДИСКОВЫЕ ОПЕРАЦИИ В BIOS ________________________________________________________________ Для указания необходимой дисковой операции необходимо перед INT 13H загрузить в регистр AH соответствующий код. AH = 00: Сброс системы контролера дисковода --------------------------------------------- Данная операция осуществляет полный сброс контролера дисковода и требует для выполнения INT 13H загрузку в регистр AH значение шест.00. Операция используется в случаях, когда после других дисковых операций возвращается код серьезной ошибки. AH = 01: Определить состояние дисковода ----------------------------------------- Данная операция возвращает в регистре AL состояние дисковода после последней операции ввода/вывода (см.Байт состояния в следующем разделе). Операция требует только загрузки значения 01 в регистр AH. AH = 02: Чтение секторов -------------------------- Данная операция выполняет чтение в память определенного числа секторов на одной дорожке. Число секторов обычно 1, 8 или 9. Адрес памяти для области ввода должен быть загружен в регистр BX, причем следует помнить, что реальный адрес зависит от содержимого регистра EX, так как в данном случае используется регистровая пара ES:BX. В следующем примере выполняется чтение сектора в область INSECT, которая должна быть достаточно большой, чтобы вместить все данные: MOV AH,02 ;Запрос на чтение MOV AL,01 ; один сектор LEA BX,INSERT ;Буфер ввода в ES:BX MOV CH,05 ;Дорожка 05 MOV CL,03 ;Сектор 03 MOV DH,00 ;Сторона (головка) 00 MOV DL,01 ;Дисковод 01 (B) INT 13H ;Вызов BIOS Число действительно прочитанных секторов возвращается в регистре AL. Регистры DS, BX, CX и DX сохраняют свои значения. В большинстве случаев программа указывает только один сектор или все сектора на дорожке. Для последовательного чтения секторов программа должна увеличивать содержимое регистров CH и CL. Заметьте, что когда номер сектора достигает максимального значения, его необходимо сбросить в 01, а номер дорожки увеличить на 1 или изменить сторону 0 на 1 (для двухсторонних дискет). AH = 03: Запись секторов -------------------------- Данная операция записывает данные из указанной области памяти (обычно 512 байтов или кратное 512) в один или несколько определенных секторов. Управляющая информация загружается в регистры аналогично операции чтения диска (код 02). Операция записи возвращает в регистре AL число секторов, которые действительно были записаны. Регистры DX, BX, CX и DX сохраняют свои значения. AH = 04: Верификация сектора ------------------------------ Данная операция проверяет, может ли быть найден указанный сектор, и выполняет своего рода контроль на четность. Операцию можно использовать после записи (код 03) для гарантии более надежного вывода, на что потребуется дополнительное время ввода/вывода. Значения регистров устанавливаются аналогично операции записи (код 03), за исключением регистровой пары ES:BX - их инициализация не требуется. Операция возвращает в регистре AL число обработанных секторов. Регистры DX, BX, CX и DX сохраняют свои значения. AH = 05: Форматирование дорожек --------------------------------- Данная операция используется для форматирования определенного числа дорожек в соответствии с одним из четырех размеров (стандарт для системы PC - 512). Операции чтения и записи для локализации требуемого сектора требуют информацию о формате. Для форматирования регистровая пара ES:BX должна содержать адрес, который указывает на группу адресных полей для дорожки. Для каждого сектора на дорожке должен быть четырехбайтовый элемент в виде T/H/S|B, где T номер дорожки, H номер головки, S номер сектора, B число байт на секторе, (00-128, 01-256, 02-512, 03-1024). Например, для форматирования 03 дорожки, на стороне 00 и 512 байтов на сектор, первый элемент должен иметь значение шест.03000102 и за ним должны быть описаны элементы для остальных секторов на дорожке. Техническое руководство по AT содержит ряд дополнительных операций BIOS. БАЙТ СОСТОЯНИЯ ________________________________________________________________ Для всех рассмотренных выше операций (02, 03, 04 и 05) в случае нормального завершения флаг CF и регистр AH содержит 0. В случае ошибки флаг CF устанавливается в 1, а регистр AH содержит код состояния, идентифицирующий причину ошибки. Код состояния аналогичен значению в регистре AL после выполнения операции 01. AH Причина 0000 0001 Ошибка команды для дискеты 0000 0010 Не найден адресный маркер на диске 0000 0011 Попытка записи на защищенный диск 0000 0100 Не найден сектор 0000 1000 Выход за границы DMA (памяти прямого доступа) 0000 1001 Попытка доступа через границу 64K 0001 0000 Чтение сбойный участок на диске 0010 0000 Ошибка контролера дисковода 0100 0000 Ошибка установки (поиска) 1000 0000 Ошибка оборудования В случае возникновения ошибки, обычным действием является сброс диска (AH=00) и троекратное повторение операции. Если таким образом ошибка не устраняется, то на экран выводится соответствующее сообщение и пользователь может сменить дискету. ПРОГРАММА: ИСПОЛЬЗОВАНИЕ BIOS ДЛЯ ЧТЕНИЯ СЕКТОРОВ ________________________________________________________________ __________________________________________________________________________ TITLE BIOREAD (COM) Чтение дискового сектора через BIOS CODESG SEGMENT PARA 'Code' ASSUME CS:CODESG,DS:CODESG,SS:CODESG,ES:CODESG ORG 100H BEGIN JMP MAIN ; --------------------------------------------------------- RECDIN DB 512 DUP(' ') ;Область ввода ENDCDE DB 00 CURADR DW 0304H ;Начало (дорожка/сектор) ENDADR DW 0501H ;Конец (дорожка/сектор) READMSG DB '*** Read error ***$' SIDE DB 00 ; --------------------------------------------------------- MAIN PROC NEAR MOV AX,0600H ;Функция прокрутки экрана A20LOOP: CALL Q10SCR ;Очистить экран CALL Q20CURS ;Установить курсор CALL C10ADDR ;Определить адрес на диске MOV CX,CURADR MOV DX,ENDADR CMP CX,DX ;Последний сектор? JE A90 ; да - выйти CALL F10READ ;Получить дисковую запись CMP ENDCDE,00 ;Ошибка чтения? JNZ A90 ; да - выйти CALL G10DISP ;Вывести сектор на экран JMP A20LOOP ;Повторить A90 RET ;Завершить программу MAIN ENDP ; Вычислить следующий адрес на диске: ; ---------------------------------- C10ADDR PROC NEAR MOV CX,CURADR ;Последняя дорожка/сектор CMP CL,10 ;Последний сектор? JNE C90 ; нет - выйти CMP SIDE,00 ;Обойти, если сторона = 0 JE C20 INC CH ;Увеличить номер дорожки C20: XOR SIDE,01 ;Сменить сторону MOV CL,01 ;Установить сектор = 1 MOV CURADR,CX C90: RET C10ADDR ENDP ; Чтение дискового сектора: ; ------------------------ F10READ PROC NEAR MOV AL,01 ;Число секторов MOV AH,02 ;Функция чтения LEA BX,RECDIN ;Адрес буфера MOV CX,CURADR ;Дорожка/сектор MOV DH,SIDE ;Сторона MOV DL,01 ;Дисковод B INT 13H ;Выполнить ввод CMP AH,00 ;Ошибка чтения? JZ F90 ; нет - выйти MOV ENDCDE,01 ; да - CALL X10ERR ; ошибка чтения F90: INC CURADR ;Увеличить номер сектора RET F10READ ENDP ; Вывод сектора на экран: ; ---------------------- G10DISP PROC NEAR MOV AH,40H ;Функция вывода на экран MOV BX,01 ;Номер устройства MOV CX,512 ;Длина LEA DX,RECDIN INT 21H RET G10DISP ENDP ; Очистка экрана: ; -------------- Q10SCR PROC NEAR MOV AX,0600H ;Полный экран MOV BH,1EH ;Установить цвет MOV CX,0000 ;Функция прокрутки MOV DX,184FH INT 10H RET Q10SCR ENDP ; Установка курсора: ; ----------------- Q20CURS PROC NEAR MOV AH,02 ;Функция установки MOV BH,00 ; курсора MOV DX,0000 INT 10H RET Q20CURS ENDP ; Вывод сообщения об ошибке на диске: ; ---------------------------------- X10ERR PROC NEAR MOV AH,40H ;Функция вывода на экран MOV BH,01 ;Номер устройства MOV CX,18 ;Длина сообщения LEA DX,READMSG INT 21H RET X10ERR ENDP CODESG ENDS END BEGIN __________________________________________________________________________ Рис.18.1. Использование BIOS для чтения дискового файла. Рассмотрим программу, приведенную на рис.18.1, в которой используется команда BIOS INT 13H для чтения секторов диска. Программа базируется на примере, приведенном на рис.16.3, со следующими изменениями: 1. Отсутствует описание FCB и подпрограмма открытия. 2. Программа расчитывает каждый дисковый адрес. После каждого чтения происходит увеличение номера сектора. При достижении номера сектора 10 процедура C10ADDR сбрасывает это значение в 01. Если номер стороны = 1, программа увеличивает номер дорожки; затем меняется номер стороны: 0 на 1 и 1 на 0. 3. Область CURADR содержит начальные значения номеров дорожки и сектора (их программа увеличивает), а область ENDADR - конечные значения. Один из способов улучшения программы - предоставить пользователю возможность указать начальные и конечные номера дорожки и сектора с помощью соответствующего запроса. Выполните данную программу под управлением отладчика DEBUG. Проделайте трассировку команд, которые инициализируют сегментные регистры, и установите начальный и конечный номера секторов для файловой таблицы FAT (расположение таблицы FAT различно в разных версиях операционной системы). Используя команду G (до) для выполнения ввода с диска и проверки считанного содержимого таблицы FAT и элементов оглавления. В качестве альтернативы отладчику DEBUG можно преобразовать ASCII-символы в области ввода в их шест. эквиваленты и выдать на экран эти значения, как это делает отладчик DEBUG (см. программу на рис.14.5). Таким образом можно проверить содержимое любого сектора (в том числе "спрятанного"), а также предоставить пользователю возможность внести изменения и записать измененный сектор на диск. Следует помнить, что при создании файла DOS может вносить записи на любые доступные сектора, которые не обязательно будут смежными на диске. Следовательно, с помощью команды BIOS INT 13H нельзя выполнить последовательное чтение файла. ОСНОВНЫЕ ПОЛОЖЕНИЯ НА ПАМЯТЬ ________________________________________________________________ - Команда BIOS INT 13H обеспечивает прямой доступ к дорожкам и секторам диска. - Команда BIOS INT 13H не поддерживает операции с оглавлением, обнаружение конца файла, блокирование и деблокирование записей. - Верификация сектора выполняет элементарную проверку записанных данных, что приводит к увеличению времени обработки. - Проверяйте байт состояния после каждой дисковой операции через BIOS. ВОПРОСЫ ДЛЯ САМОПРОВЕРКИ ________________________________________________________________ 18.1. Напишите команды для сброса дискового контролера. 18.2. Напишите команды для чтения байта состояния дискеты. 18.3. Напишите команды для BIOS INT 13H, выполняющие чтение одного сектора в область памяти INDISK, с дисковода A, головки 0, дорожки 6 и сектора 3. 18.4. Напишите команды для BIOS INT 13H, выполняющие запись трех секторов из области памяти OUTDISK, на дисковод B, головку 0, дорожку 8 и сектор 1. 18.5. При записи данных в вопросе 18.4, как можно распознать попытку записи на защищенный диск? 18.6. На основе вопроса 18.4 напишите команды контроля записи (операция верификации). ГЛАВА 19 Печать __________________________________________________________________________ Ц е л ь: Описать возможности программ на языке ассемблера для вывода информации на печатающее устройство (принтер). ВВЕДЕНИЕ ________________________________________________________________ Вывод на принтер несколько проще операций с экраном и диском. Для печати существует несколько операций, выполняющихся через DOS INT 21H и BIOS INT 17H. Команды, посылаемые на принтер, включают коды "конец страницы", "конец строки" и "возврат каретки". Принтеры классифицируются по качеству печати. Матричный принтер формирует символы в виде матрицы точек и обеспечивает нормальный, узкий и широкий форматы символов. Более совершенные матричные принтеры обеспечивают точечную графику, наклонный шрифт, жирную печать и двойную плотность, а также могут печатать, например, символы игральных карт и другие алфавитно-цифровые символы. Высококачественные печатающие устройства ограничены набором символов на сменной "ромашке" или барабане, но обеспечивают отличное качество печати и большое разнообразие принтеров. Многие высококачественные принтеры обеспечивают печать 10, 12 или 15 символов на дюйм, а также пропорциональное расположение пробелов, подчеркивание, теневую и полужирную печать. Лазерные принтеры обладают преимуществами как для матричной графики, так и для качественной печати текстов. Другая классификация печатающих устройств связана с интерфейсами. Компьютеры IBM PC имеют параллельный интерфейс, позволяющий передавать одновременно восемь битов из процессора на принтер. Кроме того, существует последовательный интерфейс, который выполняет побитовую передачу данных. Многие принтеры имеют буфер памяти, объемом в несколько тысяч байтов. Принтеры также могут принимать биты контроля на четность (нечетность). Принтеры должны "понимать" специальные сигналы из процессора, например,
Материалы находятся на сайте http://cracklab.narod.ru/asm/