
Jazik_Assemblera_dlja_IBM_PC_i_programmir
.pdfкоторое можно использовать для обработки |
файлов |
со |
специальными |
|
атрибутами. |
Для использования расширения необходимо закодировать в первом |
|||
байте шест.FF, во втором - атрибут файла, |
а в остальных |
пяти байтах |
||
шест. нули. |
|
|
|
|
ИСПОЛЬЗОВАНИЕ БЛОКА FCB ДЛЯ СОЗДАНИЯ ФАЙЛА НА ДИСКЕ
________________________________________________________________
Для ссылки на каждый дисковый файл программа должна содержать правильно составленный блок управления файлом. Операции ввода-вывода на диск требуют установки адреса блока FCB в регистре DX. Доступ к полям блока FCB осуществляются по этому адресу с помощью регистровой пары DS:DX. Для создания нового файла программа использует функцию шест.16 в прерывании DOS INT 21H следующим образом:
MOV |
AH,16H |
;Создание |
LEA |
DX,FCBname |
; дискового файла |
INT |
21H |
;Вызов DOS |
DOS осуществляет поиск имени файла |
и тип |
файла, |
взятого |
из |
|||
соответствующих полей FCB, в оглавлении. |
Если элемент |
оглавления, |
|||||
содержащий необходимое имя (и тип), будет найдено, то DOS очищает |
|||||||
найденный элемент для нового использования, если такой элемент |
не будет |
||||||
найден, то DOS ищет свободный элемент. Затем операция устанавливает размер |
|||||||
файла в 0 и |
"открывает" файл. На этапе |
открытия |
происходит |
проверка |
|||
доступного |
дискового |
пространства, |
результат |
такой |
проверки |
||
устанавливается в регистре AL: |
|
|
|
|
|
||
|
00 На диске есть свободное пространство |
|
|
|
|||
|
FF На диске нет свободного пространства. |
|
|
|
|||
При открытии также устанавливается в блок FCB номер текущего блока |
- |
||||||
0 и размер записей (по умолчанию) - 128 (шест.80) |
байтов. |
Прежде, |
чем |
начать запись файла, можно заменить это значение по умолчанию на требуемый размер записей.
Для определения выводной записи необходимо прежде обеспечить начальный адрес этой записи в область передачи данных (DTA - disk trausfer area). Так как блок FCB содержит размер записей, то в DTA не требуется устанавливать ограничитель конца записи. Затем с помощью функции шест.1A необходимо сообщить DOS адрес DTA. В любой момент времени может быть
активен только один |
DTA. В следующем примере инициализируется адрес DTA: |
|
MOV |
AH,1AH |
;Установка адреса |
LEA |
DX,DTAname |
; DTA |
INT |
21H |
;Вызов DOS |
Если программа обрабатывает только один дисковой файл, то должна быть только одна установка адреса DTA для всего выполнения. При обработке нескольких файлов программа должна устанавливать соответствующий адрес DTA непосредственно перед каждой операцией чтения или записи.
Для последовательной записи на диск существует функция шест.15:
MOV |
AH,15 |
;Последовательная |
LEA |
DX,FCBname |
; запись |
INT |
21H |
;Вызов DOS |
Операция записи использует информацию из блока FCB и адрес текущего буфера DTA. Если длина записи равна размеру сектора, то запись заносится на диск. В противном случае записи заполняют буфер по длине сектора и затем буфер записывается на диск. Например, если длина каждой записи составляет 128 байтов, то буфер заполняется четырьмя записями (4*128=512) и затем буфер записывается в дисковой сектор.
После успешного занесения записи на диск DOS увеличивает в блоке FCB
размер файла на размер записи и текущий номер записи на 1. Когда номер текущей записи достигает 128, происходит сброс этого значения в 0 и в FCB увеличивается номер текущего блока на 1. Операция возвращает в регистре AL следующие коды:
00 Успешная запись.
01 Диск полный.
02 В области DTA нет места для одной записи.
Когда запись файла завершена, можно, хотя и не всегда обязательно, записать маркер конца файла (шест.1A). Для закрытия файла используется функция шест.10:
MOV |
AH,10H |
;Закрыть |
|
LEA |
DX,FCBname |
; файл |
DOS |
INT |
21H |
;Вызов |
Эта операция записывает на диск данные, которые еще остались в дисковом буфере DOS и изменяет в соответствующем элементе оглавления, дату и размер файла. В регистре AL возвращаются следующие значения:
00 Успешная запись.
FFОписание файла оказалось в неправильном элементе оглавления (возможно в результате смены дискеты).
ПРОГРАММА: ИСПОЛЬЗОВАНИЕ FCB ДЛЯ СОЗДАНИЯ ФАЙЛА НА ДИСКЕ
________________________________________________________________
__________________________________________________________________________
TITLE |
page |
60,132 |
|
|
FCBCREAT (EXE) Использование FCB для создания файла |
||||
;---------------------------------------------------------- |
|
|
|
|
STACKSG SEGMENT PARA STACK 'Stack' |
|
|||
|
DW |
80 DUP(?) |
|
|
STACKSG ENDS |
|
|
|
|
;---------------------------------------------------------- |
SEGMENT PARA 'Data' |
|
|
|
DATASG |
|
|
||
RECLEN |
EQU |
32 |
;Список параметров: |
|
NAMEPAR |
LABEL |
BYTE |
||
MAXLEN |
DB |
RECLEN |
; |
макс.длина имени |
NAMELEN |
DB |
? |
; |
число введенных символов |
NAMEDTA |
DB |
RECLEN DUP(' ') ; |
область передачи (DTA) |
|
FCBREC |
LABEL |
BYTE |
;FCB для дискового файла |
|
FCBDRIV |
DB |
04 |
; |
дисковод D |
FCBNAME |
DB |
'NAMEFILE' |
; |
имя файла |
FCBEXT |
DB |
'DAT' |
; |
тип файла |
FCBBLK |
DW |
0000 |
; |
номер текущего блока |
FCBRCSZ |
DW |
? |
; |
размер логической записи |
FCBFLSZ DD |
? |
; |
размер файла (DOS) |
|
|
DW |
? |
; |
дата (DOS) |
|
DT |
? |
; |
зарезервировано (DOS) |
FCBSQRC DB |
00 |
; |
номер текущей записи |
|
|
DD |
? |
; |
относительный номер |
CRLF |
DB |
13,10,'$' |
|
|
ERRCDE |
DB |
00 |
|
|
PROMPT |
DB |
'Name? ','$' |
|
|
ROW |
DB |
01 |
|
|
OPNMSG |
DB |
'*** Open error ***', '$' |
||
WRTMSG |
DB |
'*** Write error ***', '$' |
||
DATASG |
ENDS |
|
|
|
; --------------------------------------------------------- |
SEGMENT PARA 'Code' |
|
|
CODESG |
|
||
BEGIN |
PROC |
FAR |
|
|
ASSUME CS:CODESG,DS:DATASG,SS:STACKSG,ES:DATASG |
||
|
PUSH |
DS |
|
|
SUB |
AX,AX |
|
|
PUSH |
AX |
|
|
MOV |
AX,DATASG |
|
|
MOV |
DS,AX |
|
|
MOV |
ES,AX |
|
|
MOV |
AX,0600H |
;Очистить экран |
|
CALL |
Q10SCR |
|
|
CALL |
Q20CURS |
;Установить курсор |
|
CALL |
C10OPEN |
;Открыть, установить DTA |
|
CMP |
ERRCDE,00 |
;Есть место на диске? |
|
JZ |
A20LOOP |
; да - продолжить, |
A20LOOP: |
RET |
|
; нет - вернуться в DOS |
CALL |
D10PROC |
|
|
|
;Конец ввода? |
||
|
CMP |
NAMELEN,00 |
|
|
JNE |
A20LOOP |
; нет - продолжить, |
|
CALL |
G10CLSE |
; да - закрыть файл |
BEGIN |
RET |
|
; и вернуться в DOS |
ENDP |
|
|
;Открытие дискового файла:
; |
------------------------ |
|
C10OPEN PROC |
NEAR |
;Функция создания файла |
MOV |
AH,16H |
|
LEA |
DX,FCBREC |
|
INT |
21H |
;Есть место на диске? |
CMP |
AL,00 |
|
JNZ |
C20 |
; нет - ошибка |
MOV |
FCBRCSZ,RECLEN |
;Размер записи (EQU) |
LEA |
DX,NAMEDTA |
;Загрузить адрес DTA |
MOV |
AH,1AH |
|
INT |
21AH |
|
RET |
|
|
C20: |
DX,OPNMSG |
;Сообщение об ошибке |
LEA |
||
CALL |
X10ERR |
|
RET |
|
|
C10OPEN ENDP |
|
|
;Ввод с клавиатуры:
; |
----------------- |
|
D10PROC PROC |
NEAR |
;Функция вывода на экран |
MOV |
AH,09 |
|
LEA |
DX,PROMPT |
;Выдать запрос |
INT |
21H |
|
MOV |
AH,0AH |
;Функция ввода |
LEA |
DX,NAMEPAR |
;Ввести имя файла |
INT |
21H |
;Прокрутка на экране |
CALL |
E10DISP |
|
CMP |
NAMELEN,00 |
;Имя введено? |
JNE |
D20 |
; да - продолжить, |
RET |
|
; нет - выйти |
D20: |
BH,00 |
;Заменить символ Return |
MOV |
||
MOV |
BL,NAMELEN |
|
MOV |
NAMEDTA[BX],' ' ;Записать пробел |
|
CALL |
F10WRIT |
;Вызвать |
|
|
; подпрограмму записи |
CLD |
DI,NAMEDTA |
;Очистить |
LEA |
||
MOV |
CX,RECLEN / 2 |
; поле |
MOV |
AX,2020H |
; имени |
REP STOSW |
;Выйти |
|
RET |
|
D10PROC ENDP
;Прокрутка и установка курсора:
; |
----------------------------- |
|
E10DISP PROC |
NEAR |
;Функция вывода на экран |
MOV |
AH,09 |
|
LEA |
DX,CRLF |
;CR/LF |
INT |
21H |
;Вызов DOS |
CMP |
ROW,18 |
;Последняя строка экрана? |
JAE |
E20 |
; да - обойти, |
INC |
ROW |
; нет - увеличить строку |
RET |
|
|
E20: |
AX,0601H |
;Прокрутка на 1 строку |
MOV |
||
CALL |
Q10SCR |
;Установить курсор |
CALL |
Q20CURS |
|
RET |
|
|
E10DISP ENDP |
|
|
;Запись на диск:
; |
|
-------------- |
|
F10WRIT PROC |
NEAR |
;Функция записи |
|
|
MOV |
AH,15H |
|
|
LEA |
DX,FCBREC |
|
|
INT |
21H |
;Запись без ошибок? |
|
CMP |
AL,00 |
|
|
JZ |
F20 |
; да |
|
LEA |
DX,WRTMSG |
; нет - |
|
CALL |
X10ERR |
; выдать сообщение |
F20: |
MOV |
NAMELEN,00 |
|
RET |
|
|
|
F10WRIT |
ENDP |
|
|
;Закрытие дискового файла:
; |
------------------------ |
|
G10CLSE PROC |
NEAR |
;Установить EOF |
MOV |
NAMEDTA,1AH |
|
CALL |
F10WRIT |
;Функция закрытия |
MOV |
AH,10H |
|
LEA |
DX,FCBREC |
|
INT |
21H |
|
RET |
|
|
G10CLSE ENDP |
|
|
;Прокрутка экрана:
; |
PROC |
---------------- |
;AX уже установлен |
Q10SCR |
NEAR |
||
|
MOV |
BH,1EH |
;Цвет желтый на синем |
|
MOV |
CX,0000 |
|
|
MOV |
DX,184FH |
;Прокрутка |
|
INT |
10H |
|
Q10SCR |
RET |
|
|
ENDP |
|
|
;Установка курсора:
; |
----------------- |
|
Q20CURS PROC |
NEAR |
|
MOV |
AH,02 |
|
MOV |
BH,00 |
|
MOV |
DL,00 |
;Установить курсор |
MOV |
DH,ROW |
|
INT |
10H |
|
RET |
|
|
Q20CURS ENDP
;Вывод сообщения об ошибке на диске:
; |
PROC |
NEAR---------------------------------- |
|
X10ERR |
;DX содержит |
||
|
MOV |
AH,09 |
|
|
INT |
21H |
; адрес сообщения |
|
MOV |
ERRCDE,01 |
;Установить код ошибки |
X10ERR |
RET |
|
|
ENDP |
|
|
|
CODESG |
ENDS |
BEGIN |
|
|
END |
|
__________________________________________________________________________
Рис.16.1. Создание дискового файла.
Программа, приведенная на рис.16.1, создает дисковый файл по имени, которое вводится пользователем с клавиатуры. Блок FCB (FCBREC) в данной программе содержит следующие поля:
FCBDRIV Программа должна создать файл на диске в дисководе 4 (или D). FCBNAME Имя файла - NAMEFILE.
FCBEXT Тип файла - DAT.
FCBBLK Начальное значение номера текущего блока - 0.
FCBRCSZ Размер записей неопределен, так как операция открытия устанавливает в данном поле значение 128.
FCBSQRC Начальное значение номера текущей записи - 0.
В программе организованы следующие процедуры:
BEGIN |
Инициализирует |
сегментные |
регистры, |
вызывает |
|
C10OPEN |
|
для |
|||||
|
создания файла и установки адреса DTA для DOS, |
|
вызывает D10PROC |
||||||||||
|
для ввода имени файла. |
Если ввод пустой, |
то |
происходит |
вызов |
||||||||
C10OPEN |
G10PROC для завершения программы. |
|
устанавливает |
размер |
|||||||||
Создает для файла элемент |
в |
директории, |
|||||||||||
|
записей - 32 (шест.20) и |
|
инициализирует адрес буфера DTA для |
||||||||||
D10PROC |
DOS. |
|
|
|
|
|
имена |
|
с |
клавиатуры |
и |
||
Выдает запрос на ввод имен, вводит |
|
|
|||||||||||
E10DISP |
вызывает процедуру F10WRIT для записи вводимых имен на диск |
|
|||||||||||
Управляет прокруткой и установкой курсора. |
|
|
|
|
|
|
|||||||
F10WRIT |
Записывает имена в дисковой файл. |
|
|
|
|
|
|
|
|
||||
G10CLSE |
Записывает маркер конца файла и закрывает файл. |
|
не |
корректной |
|||||||||
X10ERR |
Выдает на экран сообщение |
об |
ошибке |
в |
случае |
|
|||||||
|
операции создания файла или записи данных. |
|
|
|
|
|
|
||||||
Каждая операция записи автоматически добавляет |
1 |
к |
FCBSGRC |
(номер |
|||||||||
текущей записи) и шест.20 (размер записи) к FCBFLSZ |
(размер файла). Так |
||||||||||||
как каждая запись имеет длину 32 байта, то операция |
заносит |
в |
буфер |
16 |
|||||||||
записей и затем записывает |
весь |
буфер |
в сектор |
диска. |
|
Ниже |
показано |
||||||
содержимое DTA и буфера: |
|
|
|
|
|
|
|
|
|
|
|
|
DTA: |текущая запись|
Буфер: |запись 00|запись 01|запись 02|...|запись 15|
Если пользователь ввел 25 имен, то счетчик записей увеличится от 1 до 25 (шест.19). Размер файла составит:
25 * 32 байта = 800 байтов или шест. 320
Операция закрытия заносит во второй сектор оставшиеся в буфере девять записей и изменяет в оглавлении дату и размер файла. Размер записывается байтами в переставленном порядке: 20030000. Последний буфер имеет следующий вид:
Буфер: |запись 16|запись 17|...|запись 24|шест.1A|...|...|
Для простоты в |
приведенной программе создаются |
записи |
файла, |
содержащие только одно |
поле. Записи большинства других |
файлов, |
однако, |
содержит различные символьные и двоичные поля и требуют описания записи в DTA. Если записи содержат двоичные числа, то не следует использовать маркер конца файла (EOF), так как двоичное число может совпасть с шест. кодом 1A.
Для того, чтобы сделать программу более гибкой, можно разрешить пользователю указать дисковод, на котором находится или будет находиться файл. В начале выполнения программа может выдать на экран сообщение, чтобы пользователь ввел номер дисковода, а затем изменить первый байт блока FCB.
ПОСЛЕДОВАТЕЛЬНОЕ ЧТЕНИЕ ДИСКОВОГО ФАЙЛА
________________________________________________________________
В базовой версии DOS программа, читающая дисковый файл, содержит блок управления файлом, который определяет файл точно так, как он был создан. В начале программа для открытия файла использует функцию шест. OF:
MOV |
AH,OFH |
;Открытие |
LEA |
DX,FCBname |
; файла |
INT |
21H |
;Вызов DOS |
Операция открытия начинается с поиска в оглавлении элемента с |
именем |
|||||||||
и типом файла, определенными в FCB. |
Если такой элемент не будет найден |
в |
||||||||
оглавлении, то в регистре AL устанавливается шест.FF. Если элемент найден, |
||||||||||
то в регистре AL устанавливается 00 и |
в |
FCB |
заносится действительный |
|||||||
размер файла, а |
также устанавливается номер текущего блока в 0, |
длина |
||||||||
записи в шест.80. |
После открытия можно заменить длину |
записи |
на |
другое |
||||||
значение. |
|
|
|
|
|
|
|
|
|
с |
DTA должно содержать определение считываемой записи в соответствии |
||||||||||
форматом, который использовался при создании файла. |
Для установки |
адреса |
||||||||
DTA используется функция шест.1A (не путать с |
маркером |
конца |
файла |
EOF |
||||||
шест.1A) аналогично созданию дискового файла: |
|
|
|
|
|
|
||||
MOV |
AH,1AH |
;Установка |
|
|
|
|
|
|
||
LEA |
DX,DTAname |
; адреса DTA |
|
|
|
|
|
|
||
INT |
21H |
;Вызов DOS |
|
|
|
|
|
|
||
Для последовательного чтения записей |
с |
диска |
используется |
функция |
||||||
шест.14: |
|
|
|
|
|
|
|
|
|
|
MOV |
AH,14H |
;Последовательное |
|
|
|
|
|
|||
LEA |
DX,FCBname |
; чтение записей |
|
|
|
|
|
|||
INT |
21H |
;Вызов DOS |
|
|
|
|
|
|
Чтение записи с диска по адресу DTA осуществляется на основе информации в блоке FCB. Операция чтения устанавливает в регистре AL следующие коды возврата:
00 Успешное чтение.
01 Конец файла, данные не прочитаны.
02 В DTA нет места для чтения одной записи.
03 Конец файла, прочитана частичная запись, заполненная нулями.
Первая операция чтения заносит содержимое всего сектора в буфер DOS. Затем операция определяет из блока FCB размер записи и пересылает первую запись из буфера в DTA. После дующие операции чтения пересылают остальные записи (если имеются) пока буфер не будет исчерпан. После этого операция чтения определяет адрес следующего сектора и заносит его содержимое в буфер.
После успешной операции чтения в блоке FCB автоматически увеличивается номер текущей записи на 1. Завершение последовательного чтения определяется программой по маркеру конца файла (EOF), для чего в программе имеется соответствующая проверка. Так как оглавление при чтении файла не изменяется, то обычно нет необходимости закрывать файл после завершения чтения. Исключение составляют программы, которые открывают и читают несколько файлов одновременно. Такие программы должны закрывать файлы, так как DOS ограничивает число одновременно открытых файлов.
ПРОГРАММА: ИСПОЛЬЗОВАНИЕ FCB ДЛЯ ЧТЕНИЯ ДИСКОВОГО ФАЙЛА
________________________________________________________________
__________________________________________________________________________
TITLE |
FCBREAD (EXE) Чтение записей созданных в CREATDSK |
|||
; ------------------------------------------------------- |
|
|
|
|
STACKSG SEGMENT PARA STACK 'Stack' |
||||
|
DW |
80 DUP(?) |
|
|
STACKSG ENDS |
|
|
||
;-------------------------------------------------------- |
SEGMENT PARA 'Data' |
|
||
DATASG |
;FCB для файла |
|||
FCBREC |
LABEL |
BYTE |
||
FCBDRIV |
DB |
04 |
; дисковод D |
|
FCBNAME |
DB |
'NAMEFILE' |
; имя файла |
|
FCBEXT |
DB |
'DAT' |
; тип файла |
|
FCBBLK |
DW |
0000 |
; номер текущего блока |
|
FCBRCSZ DW |
0000 |
; длина логической записи |
||
|
DD |
? |
; размер файла (DOS) |
|
|
DW |
? |
; дата (DOS) |
|
|
DT |
? |
; зарезервировано (DOS) |
|
FCBSQRC DB |
00 |
; текущий номер записи |
||
|
DD |
? |
; относительный номер |
|
RECLEN |
EQU |
32 |
;Длина записи |
|
NAMEFLD |
DB |
RECLEN DUP(' '), 13, 10, '$' |
||
ENDCDE |
DB |
00 |
|
|
OPENMSG |
DB |
'*** Open error ***', '$' |
||
READMSG |
DB |
'*** Read error ***', '$' |
||
ROW |
DB |
00 |
|
|
DATASG |
ENDS |
|
|
|
;-------------------------------------------------------- |
SEGMENT PARA 'Code' |
|
||
CODESG |
|
|||
BEGIN |
PROC |
FAR |
|
|
|
ASSUME |
CS:CODESG,DS:DATASG,SS:STACKSG,ES:DATASG |
||
|
PUSH |
DS |
|
|
|
SUB |
AX,AX |
|
|
|
PUSH |
AX |
|
|
|
MOV |
AX,DATASG |
|
|
|
MOV |
DS,AX |
|
|
|
MOV |
ES,AX |
|
|
|
MOV |
AX,0600H |
;Очистить экран |
|
|
CALL |
Q10SCR |
||
|
CALL |
Q20CURS |
;Установить курсор |
|
|
CALL |
E10OPEN |
;Открыть файл, |
|
|
CMP |
ENDCDE,00 |
; установить DTA |
|
|
;Открытие без ошибок? |
|||
A20LOOP: |
JNZ |
A90 |
; нет - завершить |
|
CALL |
F10READ |
;Прочитать запись |
||
|
||||
|
CMP |
ENDCDE,00 |
;Чтение без ошибок? |
|
|
JNZ |
A90 |
; нет - выйти |
|
|
CALL |
G10DISP |
;Выдать имя на экран |
A90: |
JMP |
A20LOOP |
;Продолжить |
RET |
|
;Завершить |
|
BEGIN |
ENDP |
|
|
;Открытие файла на диске:
; |
----------------------- |
|
E10OPEN PROC |
NEAR |
|
LEA |
X,FCBREC |
;Функция открытия |
MOV |
AH,0FH |
|
INT |
21H |
;Файл найден? |
CMP |
AL,00 |
|
JNZ |
E20 |
; нет - ошибка |
MOV |
FCBRCSZ,RECLEN |
;Длина записи (EQU) |
MOV |
AH,1AH |
;Адрес DTA |
LEA |
DX,NAMEFLD |
|
INT |
21H |
|
RET |
|
|
E20: |
ENDCDE,01 |
;Сообщение об ошибке |
MOV |
||
LEA |
DX,OPENMSG |
|
CALL |
X10ERROR |
|
RET |
|
|
E10OPEN ENDP |
|
|
;Чтение дисковой записи:
; |
---------------------- |
|
F10READ PROC |
NEAR |
;Функция чтения |
MOV |
AH,14H |
|
LEA |
DX,FCBREC |
|
INT |
21H |
;Считан маркер EOF? |
CMP |
NAMEFLD,1AH |
|
JNE |
F20 |
; нет |
MOV |
ENDCDE,01 |
; да |
JMP |
F90 |
|
F20: |
AL,00 |
;Чтение без ошибок? |
CMP |
||
JZ |
F90 |
; да - выйти |
MOV |
ENDCDE,01 |
;Нет: |
CMP |
AL,01 |
;Конец файла? |
JZ |
F90 |
; да - выйти, |
LEA |
DX,READMSG |
; нет - значит |
CALL |
X10ERR |
; ошибка чтения |
F90: |
|
|
RET
F10READ ENDP
;Вывод записи на экран:
; |
|
--------------------- |
|
G10DISP PROC |
NEAR |
;Функция вывода на экран |
|
|
MOV |
AH,09 |
|
|
LEA |
DX,NAMEFLD |
|
|
INT |
21H |
;Последняя строка экрана? |
|
CMP |
ROW,20 |
|
|
JAE |
G30 |
; нет... |
|
INC |
ROW |
; да - увеличить строку |
G30: |
JMP |
G90 |
|
MOV |
AX,0601H |
|
|
|
; прокрутить |
||
|
CALL |
Q10SCR |
|
G90: |
CALL |
Q20CURS |
; установить курсор |
RET |
|
|
|
G10DISP |
ENDP |
|
|
;Прокрутка (скроллинг) экрана:
; |
NEAR---------------------------- |
;AX уже установлен |
Q10SCR PROC |
||
MOV |
BH,1EH |
;Установить цвет |
MOV |
CX,0000 |
;Функция прокрутки |
MOV |
DX,184FH |
|
INT |
10H |
|
RET |
|
|
Q1OSCR ENDP
;Установка курсора:
; |
----------------- |
Q20CURS PROC |
NEAR |
MOV |
AH,02 |
MOV |
BH,00 |
MOV |
DH,ROW |
MOV |
DL,00 |
INT |
10H |
RET |
|
Q20CURS ENDP |
|
;Вывод сообщения об ошибке на диске:
; |
PROC |
NEAR---------------------------------- |
|
X10ERR |
;DX содержит адрес |
||
|
MOV |
AH,09 |
|
|
INT |
21H |
; сообщения |
X10ERR |
RET |
|
|
ENDP |
|
|
|
CODESG |
ENDS |
BEGIN |
|
|
END |
|
__________________________________________________________________________
Рис.16.2. Чтение дискового файла
На рис.16.2 приведена программа, которая выполняет чтение файла, созданного предыдущей программой, и вывод на экран имен из записей файла. Обе программы содержат идентичные блоки FCB, хотя, имена полей FCB могут быть различны. Содержимое полей имени и типа файла должны быть одинаковы.
Программа содержит следующие процедуры:
BEGIN |
Инициализирует сегментны регистра, |
вызывает |
процедуру |
|
E10OPEN |
|||||||
|
для открытия файла и установки DTA и вызывает F10READ для чтения |
|||||||||||
|
записей. Если считан маркер конца файла, |
|
то |
программа |
||||||||
E10OPEN |
завершается, если нет, то вызывается процедура G10DISP. |
|
записей, |
|||||||||
Открывает файл, |
устанавливает |
значение |
размера |
и |
|
|||||||
F10READ |
равное 32 (шест.20), и инициализирует адрес DTA. |
|
|
|
чтения |
|||||||
Выполняет последовательное чтение записей. |
Операция |
|||||||||||
G10DISP |
автоматически увеличивает номер текущей записи в блоке FCB. |
|
||||||||||
Выводит на экран содержимое прочитанной записи. |
|
некорректной |
||||||||||
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. Остальные коды возврата могут являться результатом