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