Справочник программиста на персональном компьютере фирмы IBM. Дисковые накопители - Запись в файлы прямого доступа. Часть 2

ОГЛАВЛЕНИЕ

   Средний уровень.


   Как и все другие операции с файлами в MS DOS имеется два мето-
да записи в файл прямого доступа, один с использованием управляю-

щего блока файла, а другой с  помощью  дескриптора файла. В обоих
случаях  Вы должны создать буфер обмена данными, размер  которого
должен быть не меньше, чем размер записи.

Метод управляющего блока файла:
   Откройте управляющий блок  файла с помощью функции 0FH и пусть
DS:DX  указывают на него.  После того как файл  открыт  поместите
номер записи для  прямого  доступа  в поле записи прямого доступа
FCB.  Затем вызовите функцию 22H прерывания 21H, которая  пердаст
данные из DTA в файловый буфер, созданный при создании FCB.  Дан-
ные могут не быть немедленно записаны на диск, если размер записи
меньше чем размер буфера.  Реальная запись на диск будет происхо-
дить тогда, когда очередной вызов функции 22H заполнит буфер.
   При  возврате из функции 22H AL будет содержать 00, если обмен
прошел успешно. В противном случае в нем будет 1, если не хватает
пространства на диске и 2 - если область переноса мала для  того,
чтобы записать одну запись (т.е.  если размер буфера, установлен-
ный системой меньше, чем тот, который указан в FCB).

;---в сегменте данных
FCB       DB   1, 'NEWDATA    ', 25 DUP (0)
DTA       DB   256 DUP (?)

;---открываем файл и устанавливаем поля FCB
   MOV  AH,0FH          ;номер функции
   LEA  DX,FCB          ;DS:DX указывают на FCB
   MOV  BX,DX           ;копируем смещение для FCB
   INT  21H             ;открываем файл
   MOV  AX,256          ;размер записи
   MOV  [BX]+14,AX      ;помещаем в поле размера записи
   MOV  AX,233          ;номер записи
   MOV  [BX]+33,AX      ;помещаем в поле номера записи
   MOV  AX,0            ;обнуляем старший байт этого слова
   MOV  [BX]+35,AX      ;
;---перенос данных из DTA в файл
   MOV  AH,22H          ;номер функции записи с прямым доступом
   LEA  DX,FCB          ;DS:DX указывают на FCB
   INT  21H             ;записываем данные
   CMP  AL,0            ;проверка на ошибку
   JNE  WRITE_ERROR     ;

;---позднее, закрываем файл
   LEA  DX,FCB          ;DS:DX указывают на FCB
   MOV  AH,10H          ;функция закрытия файла
   INT  21H             ;закрываем файл
   CMP  AL,0FFH         ;проверка на ошибку
   JE   CLOSE_ERROR     ;

   Часто  программа работает сразу с набором записей прямого дос-
тупа, передавая их в память и из памяти  как единое целое. MS DOS
предоставляет  специальную  функцию для этого  при  использовании
метода FCB, называемую запись блока  с прямым доступом. Это функ-
ция 28H прерывания 21H.  При входе DS:DX должны указывать на отк-

рытый FCB, в  котором  поле  записи  прямого  доступа должно быть
равно номеру первой из записываемых записей набора.  Эта  функция
совершенно  аналогична  вышеприведенному  примеру.   Единственное
отличие  (кроме  номера функции) состоит в том, что в  CX  должно
быть указано число  записей  в  блоке  (не  путайте эти "блоки" с
блоками по 128 записей, с помощью которых система находит требуе-
мую запись - программа может  читать любое число записей, начиная
с любого места).

   В CX возвращается число реально прочитанных записей.  AL будет
содержать 0, если все записи  успешно  записаны, 1 - если не хва-
тает  пространства  на диске, при этом не будет записана ни  одна
запись. В отличии от функции 22H эта функция автоматически увели-
чивает поля текущей записи, текущего блока и записи прямого  дос-
тупа в FCB, так что они будут  указывать  на запись, следующую за
последней  прочитанной.   Отметим, что если при  выполнении  этой
функции установить CX = 0,  то  размер  файла  будет установлен в
соответствии с числом записей, равным полю записи прямого  досту-
па, и таким образом можно резервировать для файла дисковое прост-
ранство.

Метод дескриптора файлов:
   При использовании для доступа метода дескриптора файлов систе-
ма не различает  последовательные  файлы и файлы прямого доступа.
Ваша программа должна вычислить позицию в файле, с которой  начи-
нается требуемая запись, и  установить на нее файловый указатель.
Файловый указатель позиционируется с помощью функции 42H прерыва-
ния 21H. Поместите номер файла  в  BX, а смещение в файле в CX:DX
(CX будет содержать старший байт значения).  Затем поместите в AL
кодовый номер от 0 до 2. При AL  =  0, указатель будет установлен
со смещением CX:DX байтов относительно начала файла; при AL =  1,
указатель будет установлен со  смещением CX:DX относительно теку-
щей  позиции, а при AL = 2, указатель будет установлен со  смеще-
нием CX:DX относительно  конца  файла  (т.е.   таким образом файл
будет расширен).  Отрицательные числа недопустимы в качестве сме-
щений.  При возврате DX:AX будут содержать новое положение указа-
теля (старший байт в DX).  Если устанавливается флаг переноса, то
произошла ошибка. В этом случае AX будет содержать 1, если указан
неверный код в AL и 6 - если указан неверный номер файла.
   После  позиционирования  файлового  указателя  запись  прямого
доступа записывается с помощью той же функции 40H прерывания 21H,
которая  использовалась для записи в последовательный файл.   При
входе BX содержит номер файла, а CX  - число байтов, которое надо
записать.  При возврате AX будет содержать число реально записан-
ных байтов. Если  оно  отличается  от  числа помещенного в CX, то
вероятно диск полон (см. [5.1.4]).  Как обычно, при возникновении
ошибки устанавливается  флаг  переноса.   В  этом случае AX будет
содержать  5  при  ошибке накопителя и 6 - если  указан  неверный
номер файла.
   Файловый указатель играет ту же  роль для образа файла на дис-
ке,  что DTA для образа файла в памяти.  Он может сдвигаться  как
угодно для доступа к различным частям файла.  Будьте внимательны,
манипулируя файловым указателем при работе с фалом прямого досту-

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

;---в сегменте данных
HANDLE        DW    ?           ;номер файла
FILEPATH      DB    'A:NEWDATA',0   ;строка пути к файлу
REC_BUFFER    DB    30 DUP (?)  ;буфер выводимых записей

;---открываем файл
   MOV  AH,3DH               ;номер функции
   MOV  AL,1                 ;код открытия для записи
   LEA  DX,FILEPATH          ;DS:DX указывают на путь
   INT  21H                  ;открываем файл
   JC   OPEN_ERROR           ;проверка на ошибку
   MOV  HANDLE,AX            ;сохраняем номер файла

;---вычисляем позицию записи и устанавливаем файловый указатель
   MOV  AX,30                ;размер записи 30 байтов
   MOV  CX,54                ;номер записи #54 (55-я запись)
   MUL  CX                   ;теперь смещение для нее в DX:AX
   MOV  CX,DX                ;помещаем старшее слово в DX
   MOV  DX,AX                ;помещаем младшее слово в CX
   MOV  AL,0                 ;устанавливаем указатель на начало
   MOV  AH,42H               ;функция установки указателя
   MOV  BX,HANDLE            ;номер файла
   INT  21H                  ;устанавливаем указатель
   JC   POINTER_ERROR        ;проверка на ошибку
;---пишем запись с прямым доступом
   MOV  AH,40H               ;номер функции
   MOV  BX,HANDLE            ;номер файла
   MOV  CX,30                ;размер записи
   LEA  DX,REC_BUFFER        ;DS:DX указывают на буфер
   INT  21H                  ;пишем запись
   JC   WRITE_ERROR          ;проверка на ошибку

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