На этом шаге мы приведем пример программы, иллюстрирующей применение функций разширенной версии DOS.
Реализуем программу, приведенную на шаге 60, с помощью функций расширенной версии DOS.
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
FILE DB 'E:\Arkady\Site\Works\proba1.dat',0
HANDLE DW ? ;Файловый номер
DTA DW ? ;Область для размещения значения.
STR1 DB "Ошибка при создании файла. Программа завершена.$"
STR2 DB "Задайте целое число (0 - признак конца ввода): $"
STR3 DB "Содержимое файла: $"
STR4 DB "Задайте номер элемента (0 - выход): $"
STR5 DB "Элемента с таким номером нет!$"
STR6 DB "Элемент с этим номером: $"
STR7 DB "Новое значение элемента: $"
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
;Конец пролога.
@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,3CH ; Запрос на создание
MOV CX,00 ; обычного файла.
LEA DX,FILE ; ASCIIZ строка.
INT 21H ; Вызов DOS-прерывания.
JC ERROR ; Переход по ошибке.
MOV HANDLE,AX ; Сохранение файлового номера.
CALL Zapoln ; Обращение к процедуре заполнения файла.
JMP @N ; Переход на меню.
ERROR:
MOV DX,0000h
CALL Cursor ; Установка курсора.
LEA DX,STR1
CALL Write_Str ; Вывод строки.
RET ; Конец программы.
@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,3EH ; Запрос на закрытие файла.
MOV BX,HANDLE ; Файловый номер.
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:
ADD BX,BX ; Вычисляем смещение.
SUB BX,2
MOV RAB1,BX ; Запоминаем его в ячейке RAB1.
MOV AH,42H ; Установка указателя
MOV AL,00 ; от начала файла.
MOV BX,HANDLE ; Установка файлового номера.
MOV CX,00 ; Смещение на
MOV DX,RAB1 ; BX байтов.
INT 21H ; Вызов DOS-прерывания.
MOV DX,0100h
CALL Cursor ; Установка курсора.
LEA DX,STR7
CALL Write_Str ; Вывод строки-запроса значения элемента.
CALL Vvod ; Запрос на ввод элемента.
MOV DTA,BX ; Размещение значения в DTA.
MOV AH,40H ; Запрос записи.
MOV BX,HANDLE ; Файловый номер.
MOV CX,2 ; Длина записи.
LEA DX,DTA ; Адрес области вывода.
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:
ADD BX,BX ; Вычисляем смещение.
SUB BX,2
MOV RAB1,BX ; Запоминаем его в ячейке RAB1.
MOV AH,42H ; Установка указателя
MOV AL,00 ; от начала файла.
MOV BX,HANDLE ; Установка файлового номера.
MOV CX,00 ; Смещение на
MOV DX,RAB1 ; BX байтов.
INT 21H ; Вызов DOS-прерывания.
MOV AH,3FH ; Запрос на чтение.
MOV BX,HANDLE ; Файловый номер.
MOV CX,2 ; Длина записи.
LEA DX,DTA ; Адрес области ввода.
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,40H ; Запрос записи.
MOV BX,HANDLE ; Файловый номер.
MOV CX,2 ; Длина записи.
LEA DX,DTA ; Адрес области вывода.
INT 21H ; Вызов DOS-прерывания.
INC KOL ; Количество элементов увеличиваем на 1.
JMP @START
@EXIT: ; Выход.
MOV AH,3EH ; Запрос на закрытие файла.
MOV BX,HANDLE ; Файловый номер.
INT 21H ; Вызов DOS-прерывания.
MOV AH,3DH ; Запрос на открытие.
MOV AL,02 ; Чтение и запись.
LEA DX,FILE ; Строка в формате ASCIIZ.
INT 21H ; Вызов DOS-прерывания.
MOV HANDLE,AX ; Сохранение файлового номера.
RET
Zapoln ENDP
;========== ПРОЦЕДУРА ВЫВОДА СОДЕРЖИМОГО ФАЙЛА ==============
Vyvod_File PROC
MOV DX,0100h
CALL Cursor ; Установка курсора.
; Перемещение указателя в начало файла.
MOV AH,42H ; Установка указателя
MOV AL,00 ; от начала файла.
MOV BX,HANDLE ; Установка файлового номера.
MOV CX,00 ; Смещение на
MOV DX,00 ; 0 байтов.
INT 21H ; Вызов DOS-прерывания.
@PROD:
MOV AH,3FH ; Запрос на чтение.
MOV BX,HANDLE ; Файловый номер.
MOV CX,2 ; Длина записи.
LEA DX,DTA ; Адрес области ввода.
INT 21H ; Вызов DOS-прерывания.
CMP AX,0 ; Прочитано 0 байтов?
JE @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.