Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Абель.docx
Скачиваний:
13
Добавлен:
26.11.2018
Размер:
569.84 Кб
Скачать

X10err proc near

MOV AH,09 ;DX содержит адрес

Int 21h ; сообщения

RET

X10err endp

CODESG ENDS

END BEGIN

__________________________________________________________________________

Рис.16.2. Чтение дискового файла

На рис.16.2 приведена программа, которая выполняет чтение файла,

созданного предыдущей программой, и вывод на экран имен из записей файла.

Обе программы содержат идентичные блоки FCB, хотя, имена полей FCB могут

быть различны. Содержимое полей имени и типа файла должны быть одинаковы.

Программа содержит следующие процедуры:

BEGIN Инициализирует сегментны регистра, вызывает процедуру E10OPEN

для открытия файла и установки DTA и вызывает F10READ для чтения

записей. Если считан маркер конца файла, то программа

завершается, если нет, то вызывается процедура G10DISP.

E10OPEN Открывает файл, устанавливает значение размера и записей,

равное 32 (шест.20), и инициализирует адрес DTA.

F10READ Выполняет последовательное чтение записей. Операция чтения

автоматически увеличивает номер текущей записи в блоке FCB.

G10DISP Выводит на экран содержимое прочитанной записи.

X10err Выводит на экран сообщение об ошибке в случае некорректной

операции открытия или чтения.

Операция открытия выполняет поиск имени и типа файла в оглавлении.

Если необходимый элемент оглавления найден, то автоматически в блок FCB

заносятся размер файла, дата и длина записей. Первая операция чтения

записи с номером 00 получает доступ к диску и считывает весь сектор (16

записей) в буфер. После этого первая запись заносится в DTA, а номер

текущей записи в FCB увеличивается с 00 до 01:

Буфер: |запись 00|запись 01|запись 02|... |запись 15|

DTA : |запись 00|

Второй операции чтения нет необходимого обращаться к диску. Так как

требуемая запись уже находится в буфере, то операция просто пересылает

запись 01 из буфера в DTA и увеличивает номер текущей записи на единицу.

Таким же образом выполняются следующие операции чтения пока все 16 записей

из буфера не будут обработаны.

Операции чтения 16-ой записи приводит к физическому чтению следующего

сектора в буфер и пересылка первой записи сектора в DTA. Последующие

операции чтения переносят остальные записи из буфера в DTA. Попытка

прочитать после последней записи вызовет состояние конца файла и в регистр

AL будет записан код возврата шест.01.

ПРЯМОЙ ДОСТУП

________________________________________________________________

До сих пор в этой главе рассматривалась последовательная обработка

дисковых файлов, которая адекватна как для создания файла, так и для

печати его содержимого или внесения изменений в небольшие файлы. Если

программа ограничена только возможностью последовательной обработки, то

для изменения файла она должна считывать каждую запись, вносить изменения

в определенные из них и заносить записи в другой файл (программа может

использовать один DTA, но потребуются различные блоки FCB). Обычной

практикой является чтение входного файла с диска A и запись обновленного

файла на диск B. Преимущество этого способа состоит в том, что он

автоматически оставляет резервную копию.

В некоторых случаях применяется доступ к конкретным записям файла для

получения информации, например, нескольких служащих или о части

ассортимента товаров. Для доступа, скажем, к 300-ой записи файла,

последовательная обработка должна включать чтение всех 299 предшествующих

записей, пока не будет получена 300-я запись. П р и м е ч а н и е: система

может начать обработку с конкретного номера блока и записи).

Несмотря на то, что файл создается последовательно, доступ к записям

может быть последовательным или прямым (произвольным). Требования прямой

обработки, использующей вызов DOS, заключаются в установке требуемого

номера записи в соответствующее поле FCB и выдаче команды прямого чтения

или записи.

Произвольный доступ использует относительный номер записи (байты

33-36) в блоке FCB. Поле имеет размер двойного слова и использует обратную

последовательность байт в словах. Для локализации требуемой записи система

автоматически преобразует относительный номер записи в номер текущего

блока (байты 12-13) и номер текущей записи (байт 32).

Пpямое чтение

---------------

Операции открытия и установки DTA одинаковы как для прямой, так и для

последовательной обработки. Предположим, что программа должна выполнить

прямой доступ к пятой записи файла. Установим значение 05 в поле FCB для

относительного номера записи и выполним команды для прямого чтения. В

результате успешной операции содержимое пятой записи будет помещено в DTA.

Для прямого чтения записи необходимо поместить требуемое значение

относительного номера записи в FCB и вызвать функцию шест.21:

MOV AH,21H ;Запрос на

LEA DX,FCBname ; прямое чтение

INT 21H ;Вызов DOS

Операция чтения преобразует относительный номер записи в номера

текущего блока и записи. Полученные значения используются для локализации

требуемой дисковой записи, передачи содержимого записи в DTA и установки в

регистр AL следующие значения:

00 Успешное завершение

01 Данные не доступны

02 Чтение прекращено из-за нехватки места в DTA

03 Прочитана частичная запись, заполненная нулями.

Как видно, среди перечисленных кодов возврата отсутствует состояние

конец файла. При корректном чтении записи предполагается единственный код

возврата - 00. Остальные коды возврата могут являться результатом

установки неправильного относительного номера записи или некорректная

установка адреса DTA или FCB. Так как такие ошибки легко допустить, то

полезно выполнять проверку регистра AL на ненулевое значение.

Когда программа выдает первый запрос на прямую запись, операция,

используя оглавление для локализации сектора, на котором находится

требуемая запись, считывает весь сектор с диска в буфер и пересылает

запись в DTA. Предположим, например, что записи имеют размер 128 байт,

т.е. четыре записи в одном секторе. Запрос на прямое чтение записи 23

приводит к чтению в буфер четырех записей, лежащих в одном секторе:

| запись 20 | запись 21 | запись 22 | запись 23 |

Когда программа вновь выдаст прямой запрос на запись, например, 23,

то операция сначала проверит содержимое буфера. Так как данная запись уже

находится в буфере, то она непосредственно пересылается в DTA. Если

программа запросит запись 35, который нет в буфере, операция через

оглавление локализует требуемую запись, считает весь сектор в буфер и

поместит запись в DTA. Таким образом, операции прямого доступа к записям

более эффективны, если номера записей близки друг к другу.

Пpямая запись

---------------

Операция создания файла и установки DTA одинаковы как для прямого,

так и для последовательного доступа. Для обработки файла учета товаров

программа может, используя прямой доступ, считать необходимую запись,

внести, введенные вручную, изменения (например, новое количество товаров)

и вернуть запись на диск на то же место. Операция прямой записи использует

относительный номер записи в блоке FCB и функцию шест.22 следующим

образом:

MOV AH,22H ;Запрос на

LEA DX,FCBname ; прямую запись

INT 21H ;Вызов DOS

Операция устанавливает в регистре AL следующие коды возврата:

00 Успешная операция

01 На диске нет места

02 Операция прекращена в результате недостаточного места в DTA.

При создании нового файла прямым доступом может быть получен

ненулевой код возврата. Но при прямом чтении и переписывании измененных

записей на том же месте диска код возврата должен быть только 00.

Относительный номер записи в блоке FCB при прямом доступе имеет

размер двойного слова (четыре байта), каждое слово записывается обратной

последовательностью байтов. Для небольших файлов возможно потребуется

установка лишь самого левого байта или слова, но для больших файлов

установка номера записи в трех или в четырех байтах требует некоторой

тщательности.

ПРОГРАММА: ПРЯМОЕ ЧТЕНИЕ ДИСКОВОГО ФАЙЛА

________________________________________________________________

page 60,132

TITLE RANREAD (COM) Прямое чтение записей,

; созданных в FCBCREAT

CODESG SEGMENT PARA 'Code'

ASSUME CS:CODESG,DS:CODESG,SS:CODESG,ES:CODESG

ORG 100H

BEGIN: JMP MAIN

;-----------------------------------------------------

FCBREC LABEL BYTE ;FCB для дискового файла

FCBDRIV DB 04 ; дисковод D

FCBNAME DB 'MAMEFILE' ; имя файла

FCBEXT DB 'DAT' ; тип файла

FCBBLK DW 0000 ; номер текущего блока

FCBRCSZ DW 0000 ; длина логической записи

DD ? ; размер файла (DOS)

DW ? ; дата (DOS)

DT ? ; зарезервировано (DOS)

DB 00 ; номер текущей записи

FCBRNRC DD 000000000 ; относительный номер

RECLEN EQU 32 ;Длина записи

RECDPAR LABEL BYTE ;Список параметров:

MAXLEN DB 3 ;

ACTLEN DB ? ;

RECDNO DB 3 DUP(' ') ;

NAMEFLD DB RECLEN DUP(' '),13,10,'$' ;DTA

OPENMSG DB '*** Open error ***',13,10,'$'

READMSG DB '*** Read error ***',13,10,'$'

COL DB 00

PROMPT DB 'Record number? $'

ROW DB 00

ENDCDE DB 00

;-----------------------------------------------------

MAIN PROC NEAR

CALL Q10CLR ;Очистить экран

CALL Q20CURS ;Установить курсор

CALL C10OPEN ;Открыть файл,

; установить DTA

CMP ENDCDE,00 ;Открытие без ошибок?

JZ A20LOOP ; да - продолжить,

RET ; нет - завершить

A20LOOP:

CALL D10RECN ;Получить номер записи

CMP ACTLEN,00 ;Есть запрос?

JE A40 ; нет - выйти

CALL F10READ ;Чтение (прямой доступ)

CMP ENDCDE,00 ;Есть ошибки чтения?

JNZ A30 ; да - обойти

CALL G10DISP ;Вывести на экран

A30:

JMP A20LOOP

A40: RET ;Завершить программу

MAIN ENDP

; Подпрограмма открытия файла на диске:

; ------------------------------------

C10OPEN PROC NEAR

MOV AH,0FH ;Функция открытия

LEA DX,FCBREC

INT 21H

CMP AL,00 ;Открытие нормальное?

JNZ C20 ; нет - ошибка

MOV FCBRCSZ,RECLEN ;Длина записи (EQU)

MOV AH,1AH

LEA DX,NAMEFLD ;Установить адрес DTA

INT 21H

RET

C20:

LEA DX,OPENMSG

CALL X10ERR

RET

C10OPEN ENDP

; Ввод с клавиатуры номера записи:

; -------------------------------

D10RECN PROC NEAR

MOV AH,09H ;Функция вывода на экран

LEA DX,PROMPT

INT 21H

MOV AH,0AH ;Функция ввода с клавиатуры

LEA DX,RECDPAR

INT 21H

CMP ACTLEN,01 ;Проверить длину (0,1,2)

JB D40 ;Длина 0, завершить

JA D20

SUB AH,AH ;Длина 1

MOV AL,RECDNO

JMP D30

D20:

MOV AH,RECDNO ;Длина 2

MOV AL,RECDNO+1

D30:

AND AX,0F0FH ;Удалить ASCII тройки

AAD ;Преобразовать в двоичное

MOV WORD PTR FCBRNRC,AX

D40:

MOV COL,20

CALL Q20CURS ;Установить курсор

RET

D10RECN ENDP

; Чтение дисковой записи:

; ----------------------

F10READ PROC NEAR

MOV ENDCDE,00 ;Очистить код завершения

MOV AH,21H ;Функция прямого чтения

LEA DX,FCBREC

INT 21H

CMP AL,00 ;Чтение без ошибок?

JZ F20 ; да - выйти

LEA DX,READMSG ; нет - выдать

CALL X10ERR ; сообщение об ошибке

F20: RET

F10READ ENDP

; Вывод имени на экран:

; --------------------

G10DISP PROC NEAR

MOV AH,09 ;Функция вывода на экран

LEA DX,NAMEFLD

INC 21H

INC ROW

MOV COL,00

RET

G10DISP ENDP

; Очистка экрана:

; --------------

Q10CLR PROC NEAR

MOV AX,0600H ;Функция прокрутки

MOV BH,41H ;Цвет (07 для ч/б)

MOV CX,0000

MOV DX,184FH

INT 10H

RET

Q10CLR ENDP

; Установка курсора:

; -----------------

Q20CURS PROC NEAR

MOV AH,02 ;Функция установки

MOV BH,00 ; курсора

MOV DH,ROW

MOV DL,COL

INT 10H

RET

Q20CURS ENDP

; Вывод сообщения об ошибке на диске:

; ----------------------------------