Шаг 67.
Пример программы, иллюстрирующей использование функций блочного доступа в базовой версии DOS

    На этом шаге мы приведем пример программы, использующей блочное чтение и запись.

    Приведенный пример программы создает файл на диске, состоящие не более чем из 100 целых чисел (0 - признак выхода из процедуры ввода). Все числа помещаются в область DTA, содержимое которой помещается на диск перед завершением процедуры выхода.

    Перед чтением из файла указывется номер элемента, с которого нужно начать вывод элементов файла. После уменьшения этого значения на 1 (нумерация элементов в файле начинается с 0!) полученное значение помещается в поле относительного номера записи, так как именно оно отвечает за задание начального номера записи, с которого начинается блочное чтение.

    Прочитанные элементы помещаются в область DTA, откуда в цикле они выводятся на экран (количество реально прочитанных записей помещается именно в этот регистр).

        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	;Относительный номер.
DTA     DW      200 DUP (?)     ;Область DTA.
KOL     DW      ?               ;Количество элементов в файле.
PUNKT   DB      ?               ;Номер выбранного пункта меню.

STR1    DB  "На диске нет свободного пространства. Программа завершена.$"
STR2    DB  "Задайте целое число (0 - признак конца ввода): $"
STR3    DB  "Элементы файла: $"
STR4    DB  "Номер элемента, с которого осуществлять вывод содержимого файла: $"

;------- Главное меню (длина каждого элемента -  48 символов).
ELEM1   DB  "          Г Л А В Н О Е   М Е Н Ю :            $" 
ELEM2   DB  " Создание файла ............................. 1$" 
ELEM3   DB  " Просмотр файла ............................. 2$" 
ELEM6   DB  " Выход ...................................... 0$" 
ELEM7   DB  " Укажите номер пункта ....................... $" 
KOLP    DW      5       ;Количество пунктов меню.
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        ; Просмотр файла.
        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 Vyvod_File ; Обращение к процедуре вывода содержимого файла.
        MOV  AH,1       ; Задержка.
        INT  21H
        JMP  @N         ; Переход на меню.
@ET:    ;-------------- Выход из программы.
        MOV  AH,10H     ; Закрыть
        LEA  DX,FILE    ;   файл.
        INT  21H        ; Вызов DOS-прерывания.
        RET
Begin   ENDP
;========== ПРОЦЕДУРА ЗАПОЛНЕНИЯ ФАЙЛА ==============
Zapoln  PROC
        PUSH SI
        MOV  KOL,0      ; Обнуление количества элементов.
        MOV  SI,0       ; Индекс (номер) элемента.
@START:
        CALL Clear      ; Очистка экрана.
        MOV  DX,0000h
        CALL Cursor     ; Установка курсора.
        LEA  DX,STR2
        CALL Write_Str  ; Вывод строки-приглашения.
        CALL Vvod       ; Ввод числа.
        CMP  BX,0       ; Проверка на выход.
        JE   @EXIT
        MOV  DTA[SI],BX ; Размещение числа в DTA.
        ADD  SI,2       ; Новое значение индекса.
        INC  KOL        ; Количество элементов увеличиваем на 1.
        JMP  @START
@EXIT:                  ; Выход
        MOV  AH,28H     ; Блочная запись.
        MOV  CX,KOL     ; Количество элементов.
        LEA  DX,FILE    ; 
        INT  21H        ; Вызов DOS-прерывания.
        POP  SI
        RET  
Zapoln  ENDP
;========== ПРОЦЕДУРА ВЫВОДА СОДЕРЖИМОГО ФАЙЛА ==============
Vyvod_File PROC
        CALL Clear      ; Очистка экрана.
        MOV  DX,0000h
        CALL Cursor     ; Установка курсора.
        LEA  DX,STR4
        CALL Write_Str  ; Вывод строки.
        CALL Vvod
        DEC  BX         ; Вычисление начального номера элемента для вывода.
        MOV  DX,0100h
        CALL Cursor     ; Установка курсора.
        LEA  DX,STR3
        CALL Write_Str  ; Вывод строки.
                        ; Перемещение указателя на начальный элемент:
        MOV  WORD PTR FCBBLK,0   ;  - обнуление номера текущего блока;
        MOV  WORD PTR FCBSQRC,0  ;  - обнуление начального номера записи;
        MOV  WORD PTR FCBOTRC,BX ;  - установка относительного номера записи.
        MOV  AH,27H     ; Блочное чтение.
        MOV  CX,KOL     ; Количество записей 
        SUB  CX,BX      ; для чтения.
        LEA  DX,FILE    ;    
        INT  21H        ; Вызов DOS-прерывания.
        CMP  AL,0       ; Все нормально?
        JNE  @EXT;      ; Нет - выход.
        MOV  SI,0
@PROD:
        MOV  BX,DTA[SI] ; Размещение прочитанного в BX.
        CALL Vyvod      ; Вывод на экран
        MOV  AH,2
        MOV  DL,' '     ; Вывод пробела (разделителя между числами).
        INT  21H 
        ADD  SI,2
        LOOP @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
Текст этой программы можно взять здесь.

    На следующем шаге рассмотрим абсолютные операции дискового ввода и вывода.




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