MOV BH,00 ; курсора
MOV DH,ROW
MOV DL,COL
INT 10H
RET
Q20CURS ENDP
; Вывод сообщения об ошибке на диске:
; ----------------------------------
X10ERR PROC NEAR
MOV AH,09 ;DX содержит адрес
INT 21H ; сообщения
INC ROW
MOV ENDCDE,01
RET
X10ERR ENDP
CODESG ENDS
END BEGIN
__________________________________________________________________________
Рис.16.3. Прямое чтение дисковых записей.
На рис.16.3 приведена программа, которая считывает файл, созданный
предыдущей программой (см. рис.16.1). Вводя любой относительный номер
записи, лежащей в границах файла, пользователь запрашивает вывод на экран
любой записи файла. Если файл содержит 25 записей, то правильными номера
являются номера от 00 до 24. Номер вводится с клавиатуры в ASCII формате и
должен быть в нашем случае одно- или двузначным числом.
Программа содержит следующие процедуры:
C10OPEN Открывает файл, устанавливает размер записи 32 и устанавливает
адрес DTA.
D10RECN Вводит номер записи с клавиатуры, преобразует его в двоичный
формат и записывает полученное значение в FCB. В качестве
усовершенствования процедуры можно вставить проверку вхождения
номера в границы от 00 до 24.
F10READ Помещает требуемую запись в DTA в соответствии с относительным
номером записи в FCB.
G10DISP Выводит запись на экран.
Процедура D10RECN вводит номер записи с клавиатуры и проверяет длину
ввода в списке параметров. Возможны три варианта:
00 Запрошен конец обработки
01 Введено однозначное число (в регистре AL)
02 Введено двузначное число (в регистре AX)
Данная процедура преобразует введенное число из ASCII формата в
двоичный формат. Так как значение находится в регистре AX, то лучше
использовать команду AAD для преобразования. После преобразования двоичный
код из регистра AX пересылается в два левых байта поля относительного
номера записи в блоке FCB. Если, например, введено число 12 в ASCII
формате, то AX будет содержать 3132. Команда AND преобразует это значение
в 0102, а команда AAD - в 000C. Результат преобразования заносится в поле
относительного номера записи блока FCB в виде С000 0000.
ПРЯМОЙ БЛОЧНЫЙ ДОСТУП
________________________________________________________________
Если в программе имеется достаточно места, то одна прямая блочная
операция может записать весь файл из DTA на диск, а также прочитать весь
файл с диска в DTA. Данная особенность весьма полезна для записи на диск
таблиц, которые другие программы могут считывать в память для обработки.
Начать можно с любого правильного относительного номера записи. Число
записей также может быть любым, хотя блок должен находится в пределах
файла. Перед началом необходимо открыть файл и инициализировать DTA.
Для операции прямой блочной записи необходимо установить в регистре
CX требуемое число записей, установить в FCB стартовый относительный номер
записи и выдать функцию шест.28:
MOV AH,28H ;Операция прямой блочной записи
MOV CX,records ;Установка числа записей
LEA DX,FCBname ;
INT 21H ;Вызов DOS
Операция преобразует относительный номер записи в текущие номер блока
и номер записи. Полученные значения используются для определения
начального адреса на диске. В результате операции в регистре AL
устанавливаются следующие коды возврата:
00 Успешное завершение для всех записей
01 На диске недостаточно места.
Кроме того операция устанавливает в FCB в поле относительного номера
записи и полях текущих номеров блока и записи значения, соответствующие
следующему номеру записи. Например, если были записаны записи с 00 до 24,
то следующий номер записи будет 25 (шест.19).
Для операции прямого блочного чтения необходимо установить в регистре
CX требуемое число записей и использовать функцию шест.27:
MOV AH,27H ;Операция прямого блочного чтения
MOV CX,records ;Установка числа записей
LEA DX,FCBname ;
INT 21H ;Вызов DOS
Операция чтения возвращает в регистре AL следующие значения:
00 Успешное чтение всех записей
01 Прочитана последняя запись файла
02 Прочитано предельное для DTA число записей
03 Прочитана последняя запись файла не полностью.
В регистре CX остается действительное число прочитанных записей, а в
FCB в поле относительного номера записи и полях текущих номеров блока и
записи устанавливаются значения, соответствующие следующему номеру записи.
Если необходимо загрузить в память весь файл, но число записей
неизвестно, то следует после операции открытия разделить размер файла на
длину записи. Например, для размера файла шест.320 (800) и длине записи
шест.20 (32) число записей будет шест.19 (25).
ПРОГРАММА: ПРЯМОЕ БЛОЧНОЕ ЧТЕНИЕ
________________________________________________________________
__________________________________________________________________________
TITLE RANBLOK (COM) Прямое блочное чтение файла
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 'NAMEFILE' ; имя файла
FCBEXT DB 'DAT' ; тип файла
FCBBLK DW 0000 ; номер текущего блока
FCBRCSZ DW 0000 ; логическая длина записи
FCBFLZ DD ? ; DOS размер файла
DW ? ; DOS дата
DT ? ; DOS зарезервировано
DB 00 ; номер текущей записи
FCBRNRC DD 00000000 ; относительный номер
DSKRECS DB 1024 DUP(?),'$' ;DTA для блока записей
ENDCODE DB 00
NORECS DW 25 ;Число записей
OPENMSG DB '*** Open error ***',13,10,'$'
READMSG DB '*** Open error ***',13,10,'$'
ROWCTR DB 00
; ---------------------------------------------------
MAIN PROC NEAR
CALL Q10CLR ;Очистить экран
CALL Q20CURS ;Установить курсор
CALL E10OPEN ;Открыть файл,
; установить DTA
CMP ENDCODE,00 ;Успешное открытие?
JNZ A30 ; нет - выйти
CALL F10READ ;Читать записи
CALL G10DISP ;Вывод блока на экран
A30: RET ;Завершить программу
MAIN ENDP
; Открыть дисковый файл:
; ---------------------
E10OPEN PROC NEAR
MOV AH,0FH ;Функция открытия файла
LEA DX,FCBREC
INT 21H
CMP AL,00 ;Успешное открытие?
JNZ A30 ; нет - ошибка
MOV FCBRCSZ,0020H ;Размер записи
MOV AH,1AH
LEA DX,DSKRECS ;Установить адрес DTA
INT 21H
RET
E20:
LEA DX,OPENMSG ;Ошибка открытия файла
CALL X10ERR
RET
E10OPEN ENDP
; Чтение блока:
; ------------
F10READ PROC NEAR
MOV AH,27H ;Прямое чтение блока
MOV CX,NORECS ;Число записей
LEA DX,FCBREC
INT 21H
MOV ENDCODE,AL ;Сохранить код возврата
RET
F10READ ENDP
; Вывод блока на экран:
; --------------------
G10DISP PROC NEAR
MOV AH,09 ;Функция вывода на экран
LEA DX,DSKRECS
INT 21H
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,ROWCTR
MOV DL,00
INT 10H
INC ROWCTR
RET
Q20CURS ENDP
; Подпрограмма сообщения об ошибке диска:
; --------------------------------------
X10ERR PROC NEAR
MOV AH,09 ;DX содержит адрес
INT 21H ; сообщения
MOV ENDCODE,01
RET
X10ERR ENDP
CODESG ENDS
END BEGIN
__________________________________________________________________________
Рис.16.4. Прямое блочное чтение.
На рис.16.4 приведена программа, выполняющая блочное чтение файла,
созданного программой на рис.16.1. Программа устанавливает начальный
относительный номер записи 00, в регистре CX - счетчик на 25 записей и
выводит на экран всю информацию из DTA (только для того, чтобы убедиться,
что информация считана). Другие варианты программы могут включать
установку другого начального номера записи и считывание менее 25 записей.
В программе организованы следующие процедуры:
E10OPEN Открывает файл, устанавливает размер записи в FCB равным 32 и
устанавливает адрес DTA.
F10READ Устанавливает число записей равным 25 и выполняет блочное чтение
G10DISP Выводит блок на экран.
Операция чтения преобразует относительный номер записи 00 в FCB в
номер текущего блока 00 и номер текущей записи 00. В конце операции чтения
в FCB текущий номер записи будет содержать шест.19, а относительный номер
записи - шест.19000000.
АБСОЛЮТНЫЕ ОПЕРАЦИИ ДИСКОВОГО ВВОДА-ВЫВОДА
________________________________________________________________
Для непосредственного доступа к диску можно использовать операции
абсолютного чтения и абсолютной записи с помощью функций DOS INT 25H и
26H. В этом случае не используются оглавление диска и преимущества
блокирования и разблокирования записей, обеспечиваемые функцией DOS INT
21H.
Абсолютные операции предполагают, что все записи имеют размер
сектора, поэтому прямой доступ осуществляется к полному сектору или блоку
секторов. Адресация диска выполняется по "логическому номеру записи"
(абсолютный сектор). Для определения логического номера записи на
двухсторонних дискетах с девятью секторами счет секторов ведется с дорожки
0, сектора 1, следующим образом:
Дорожка Сектор Логический номер записи
0 1 0
0 2 1
1 1 9
1 9 17
2 9 26
Для двухсторонних дискет используется следующая формула:
Логический номер записи = (дорожка х 9) + (сектор - 1)
Например, логический номер записи на дорожке 2 и секторе 9
определяется как
(2 х 9) + (9 - 1) = 18 + 8 = 26
Фрагмент программы для абсолютных операций ввода-вывода:
MOV AL,drive# ;0 для A, 1 для B и т.д.