На этом шаге мы приведем текст программы, иллюстрирующей рассмотренные на предыдущих шагах функции.
Проиллюстрируем использование изложенных в предыдущих шагах функций на конкретном примере.
Г Л А В Н О Е М Е Н Ю :
Создание файла ............................. 1
Просмотр файла ............................. 2
Вывод элемента с заданным номером .......... 3
Изменение элемента с заданным номером ...... 4
Выход ...................................... 0
Укажите номер пункта .......................
Используя это меню можно выбрать необходимое действие. Обращаем внимание на то, что в программе отсутствует защита от повторного создания файла. Реализацию запрета на повторное создание файла, запрос имени создаваемого файла и другие необходимые защиты мы оставляем читателю.
Текст программы хорошо прокомментирован, поэтому больше никаких комментариев мы не приводим.
TITLE Работа с файлами в базовой версии DOS.
;Программа сделана как EXE-файл.
;-------------------------------
EXTRN Vvod:FAR,Vyvod:FAR,Clear:FAR,Write_Str:FAR,Cursor:FAR
;----- Сегмент стека
StackSg SEGMENT PARA STACK 'Stack'
DW 256 DUP(?)
StackSg ENDS
;----- Сегмент данных
DataSg SEGMENT PARA PUBLIC
;-------- Блок FCB
FILE LABEL BYTE ;Список параметров.
FCBDRV DB 05 ;Диск E (При необходимости - измените!!!).
FCBNAME DB 'PROBA ' ;Имя файла, дополненное
;тремя пробелами.
FCBEXT DB 'DAT' ;Расширение.
FCBBLK DW 0000 ;Номер текущего блока.
FCBRCSZ DW ? ;Размер логической записи.
DD ? ;Размер файла (DOS).
DW ? ;Дата (DOS).
DT ? ;Зарезервировано (DOS).
FCBSQRC DB 00 ;Номер текущей записи.
FCBOTRC DD 00000000 ;Относительный номер.
STR1 DB "На диске нет свободного пространства. Программа завершена.$"
STR2 DB "Задайте целое число (0 - признак конца ввода): $"
STR3 DB "Содержимое файла: $"
STR4 DB "Задайте номер элемента (0 - выход): $"
STR5 DB "Элемента с таким номером нет!$"
STR6 DB "Элемент с этим номером: $"
STR7 DB "Новое значение элемента: $"
DTA DW ? ;Область DTA (1 слово).
KOL DW ? ;Количество элементов в файле.
PUNKT DB ? ;Номер выбранного пункта меню.
;------- Главное меню (длина каждого элемента - 48 символов).
ELEM1 DB " Г Л А В Н О Е М Е Н Ю : $"
ELEM2 DB " Создание файла ............................. 1$"
ELEM3 DB " Просмотр файла ............................. 2$"
ELEM4 DB " Вывод элемента с заданным номером .......... 3$"
ELEM5 DB " Изменение элемента с заданным номером ...... 4$"
ELEM6 DB " Выход ...................................... 0$"
ELEM7 DB " Укажите номер пункта ....................... $"
KOLP DW 7 ;Количество пунктов меню.
DLINA DW 48 ;Длина пункта меню.
RAB1 DW ? ;Рабочая ячейка.
RAB2 DW ? ;Рабочая ячейка.
DataSg ENDS
;----- Сегмент кода
CodeSg SEGMENT PARA PUBLIC
ASSUME CS: CodeSg, DS:DataSg, SS: StackSg
Begin PROC FAR
;Пролог EXE-файла.
PUSH DS
XOR AX,AX
PUSH AX
MOV AX,DataSg
MOV DS,AX
;Конец пролога.
;---------------- Установка области DTA.
MOV AH,1AH ; Установка адреса
LEA DX,DTA ; DTA.
INT 21H ; Вызов DOS-прерывания.
@N: ;---------------- Главное меню.
CALL Menu ; Вывод меню.
CMP PUNKT,0
JE @ET ; Выход из программы.
CMP PUNKT,1
JE @P1 ; Создание файла.
CMP PUNKT,2
JE @P2 ; Просмотр файла.
CMP PUNKT,3
JE @P3 ; Вывод элемента с заданным номером.
CMP PUNKT,4
JE @P4 ; Изменение элемента с заданным номером.
JMP @N
@P1: ;---------------Создание файла.
CALL Clear ; Очистка экрана.
MOV AH,16H ; Создание
LEA DX,FILE ; дискового файла.
INT 21H ; Вызов DOS-прерывания.
CMP AL,0FFH ; Проверка на наличие свободного пространства.
JNE @PR ; Не равно - продолжаем.
MOV DX,0000h
CALL Cursor ; Установка курсора.
LEA DX,STR1
CALL Write_Str ; Вывод строки.
RET ; Конец программы.
@PR:
MOV FCBRCSZ,2 ; Установка длины записи (2 байта).
CALL Zapoln ; Обращение к процедуре заполнения файла.
JMP @N ; Переход на меню.
@P2: ;---------------Просмотр файла.
CALL Clear ; Очистка экрана.
MOV DX,0000h
CALL Cursor ; Установка курсора.
LEA DX,STR3
CALL Write_Str ; Вывод строки.
CALL Vyvod_File ; Обращение к процедуре вывода содержимого файла.
MOV AH,1 ; Задержка.
INT 21H
JMP @N ; Переход на меню.
@P3: ;---------------Обращение к процедуре вывода элемента.
CALL Vyv_Elem
JMP @N ; Переход на меню.
@P4: ;---------------Обращение к процедуре изменения элемента.
CALL Izm_Elem
JMP @N ; Переход на меню.
@ET: ;-------------- Выход из программы.
MOV AH,10H ; Закрыть
LEA DX,FILE ; файл.
INT 21H ; Вызов DOS-прерывания.
RET
Begin ENDP
;========== ПРОЦЕДУРА ИЗМЕНЕНИЯ ЭЛЕМЕНТА ==============
Izm_Elem PROC
@V00:
CALL Clear ; Очистка экрана.
MOV DX,0000h
CALL Cursor ; Установка курсора.
LEA DX,STR4
CALL Write_Str ; Вывод строки-запроса номера элемента.
CALL Vvod ; Ввод номера элемента.
CMP BX,KOL ; Сравниваем с количеством элементов.
JG @NOO ; Нет элемента с таким номером.
CMP BX,0
JL @NOO
JNE @V10
RET ; Выход при 0.
@V10:
MOV WORD PTR FCBOTRC,BX ; Заполнение поля "Относительный номер".
DEC WORD PTR FCBOTRC ; Нумерация элементов начинается с 0.
MOV DX,0100h
CALL Cursor ; Установка курсора.
LEA DX,STR7
CALL Write_Str ; Вывод строки-запроса значения элемента.
CALL Vvod ; Запрос на ввод элемента.
MOV DTA,BX ; Размещение значения в DTA.
MOV AH,22H ; Запрос на
LEA DX,FILE ; прямую запись.
INT 21H ; Вызов DOS-прерывания.
JMP @V00 ; Переход на начало.
@NOO:
MOV DX,0400h
CALL Cursor ; Установка курсора.
LEA DX,STR5
CALL Write_Str ; Вывод строки c сообщением об отсутствии элемента.
MOV AH,1 ; Задержка.
INT 21H
JMP @V00 ; Переход на начало.
Izm_Elem ENDP
;========== ПРОЦЕДУРА ВЫВОДА ЭЛЕМЕНТА ==============
Vyv_Elem PROC
@V0:
CALL Clear ; Очистка экрана.
MOV DX,0000h
CALL Cursor ; Установка курсора.
LEA DX,STR4
CALL Write_Str ; Вывод строки-запроса номера элемента.
CALL Vvod ; Ввод номера элемента.
CMP BX,KOL ; Сравниваем с количеством элементов.
JG @NO ; Нет элемента с таким номером.
CMP BX,0
JL @NO
JNE @V1
RET ; Выход при 0.
@V1:
MOV WORD PTR FCBOTRC,BX ; Заполнение поля "Относительный номер".
DEC WORD PTR FCBOTRC ; Нумерация элементов начинается с 0.
MOV AH,21H ; Запрос на
LEA DX,FILE ; прямое чтение.
INT 21H ; Вызов DOS-прерывания.
MOV DX,0100h
CALL Cursor ; Установка курсора.
LEA DX,STR6
CALL Write_Str ; Вывод строки-вывода элемента.
MOV BX,DTA ; Размещение прочитанного в BX.
CALL Vyvod ; Вывод на экран
MOV AH,1 ; Задержка.
INT 21H
JMP @V0 ; Переход на начало.
@NO:
MOV DX,0400h
CALL Cursor ; Установка курсора.
LEA DX,STR5
CALL Write_Str ; Вывод строки c сообщением об отсутствии элемента.
MOV AH,1 ; Задержка.
INT 21H
JMP @V0 ; Переход на начало.
Vyv_Elem ENDP
;========== ПРОЦЕДУРА ЗАПОЛНЕНИЯ ФАЙЛА ==============
Zapoln PROC
MOV KOL,0 ; Обнуление количества элементов.
@START:
CALL Clear ; Очистка экрана.
MOV DX,0000h
CALL Cursor ; Установка курсора.
LEA DX,STR2
CALL Write_Str ; Вывод строки-приглашения.
CALL Vvod ; Ввод числа.
CMP BX,0 ; Проверка на выход.
JE @EXIT
MOV DTA,BX ; Размещение числа в DTA.
MOV AH,15H ; Последовательная
LEA DX,FILE ; запись.
INT 21H ; Вызов DOS-прерывания.
INC KOL ; Количество элементов увеличиваем на 1.
JMP @START
@EXIT: ; Выход
RET
Zapoln ENDP
;========== ПРОЦЕДУРА ВЫВОДА СОДЕРЖИМОГО ФАЙЛА ==============
Vyvod_File PROC
MOV DX,0100h
CALL Cursor ; Установка курсора.
; Перемещение указателя в начало файла.
MOV FCBBLK,0 ; Обнуление номера текущего блока.
MOV FCBSQRC,0 ; Обнуление номера текущей записи.
@PROD:
MOV AH,14H ; Последовательное
LEA DX,FILE ; чтение.
INT 21H ; Вызов DOS-прерывания.
CMP AL,0 ; Все нормально?
JNE @EXT; ; Нет - выход.
MOV BX,DTA ; Размещение прочитанного в BX.
CALL Vyvod ; Вывод на экран
MOV AH,2
MOV DL,' ' ; Вывод пробела (разделителя между числами).
INT 21H
JMP @PROD
@EXT: ; Выход.
RET
Vyvod_File ENDP
;========== ГЛАВНОЕ МЕНЮ ==============
Menu PROC
PUSH CX
PUSH DX
CALL Clear ; Очистка экрана.
MOV DX,0000 ; Начальная позиция курсора.
MOV RAB1,DX ; Сохраним значение DX (позицию курсора).
LEA DX,ELEM1 ; Адрес первого пункта меню.
MOV CX,KOLP ; Количество пунктов меню.
MOV RAB2,DX ; Сохраним значение DX (адрес начала меню).
@POWT:
MOV DX,RAB1 ; Восстановим сохраненную позицию курсора.
CALL Cursor ; Установка курсора.
INC DH ; Увеличим номер строки.
MOV RAB1,DX ; Сохраним значение DX (позицию курсора).
MOV DX,RAB2 ; Восстановим сохраненный адрес начала меню.
CALL Write_Str ; Вывод пункта меню.
ADD DX,DLINA ; Получм адрес следующего пункта меню.
MOV RAB2,DX ; Сохраним значение DX (адрес пункта меню).
LOOP @POWT
MOV AH,1
INT 21H
SUB AL,30H
MOV PUNKT,AL ; Сохраняем номер выбранного пункта.
POP DX
POP CX
RET
Menu ENDP
CodeSg ENDS
END Begin
Со следующего шага мы начнем рассматривать функции, используемые для работы с файлами в расширенной версии DOS.