Шаг 60.
Функции базовой версии DOS для работы с файлами. Пример программы

    На этом шаге мы приведем текст программы, иллюстрирующей рассмотренные на предыдущих шагах функции.

    Проиллюстрируем использование изложенных в предыдущих шагах функций на конкретном примере.


    Пример. Создать программу, реализующую последовательный и прямой доступ к записям файла. В результате работы программы на экран выводится меню:
          Г Л А В Н О Е   М Е Н Ю :            
 Создание файла ............................. 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.




Предыдущий шаг Содержание Следующий шаг