Работа с файлами в программах на ассемблере (Часть 1)

Очевидно, целесообразно рассматривать прикладную систему как некоторую
совокупность данных и операций, определенных па этих данных, а не просто
как набор программ, взаимодействующих между собой посредством
обмена данными. Программы — это всего лишь рабочие инструменты,
в то время как данные — это своего рода исходное сырье,
из которого вырабатывается конечный продукт. Набор данных вне среды
приспособленной для его использования, не представляет
никакой ценности, однако в рамках такой среды именно
набор данных приобретает основное значение.
Динар Нурмухамедович Бибишев

Язык ассемблера не содержит средств для работы с файлами. Если такая необходимость возникает, то программа должна содержать фрагменты кода, в которых производится обращение к средствам операционной системы, осуществляющим взаимодействие с файловой системой. Это лишний раз подтверждает тот факт, что в области взаимодействия с внешним миром программа на ассемблере оказывается привязанной как к конкретной аппаратной, так и конкретной операционной платформам. В сегодняшней ситуации программисту все еще приходится сталкиваться с необходимостью программирования для MS DOS. Поэтому изучение средств для работы с файлами этой операционной платформы не потеряло своей актуальности и эти средства в плане совместимости поддерживаются различными реализациями Windows. В реализации MS DOS 7.0 введена поддержка длинных имен файлов, используемых системой файлового ввода-вывода Win 32. Таким образом можно выделить три аспекта работы с файлами из программ на ассемблере:

  • работа с системой файлового ввода-вывода MS DOS, использующей короткие имена (по схеме 8.3);
  • работа с системой файлового ввода-вывода MS DOS, использующей длинные имена (длиной до 255 символов);
  • работа с системой файлового ввода-вывода Win 32;
  • использование файлов особого вида, поддерживаемых Win 32 — проецированных на память.

Целью данной главы является предоставить читателю фрагменты кода, реализующего наиболее часто используемые операции по работе с файлами на различных операционных платформах. При этом нам не обойтись без определенной систематизации, но это будет сделано лишь для того, чтобы создать у читателя общее представление об этом вопросе. Если у вас впоследствии возникнет потребность в реализации файловых функций, чье полное практическое описание отсутствует в материале этой главы, то более подробные сведения о них можно будет найти в других справочных руководствах, например MSDN. Далее, используя общие принципы организации ввода-вывода, рассмотренные ниже, вы сможете без труда решить возникшую проблему. Материалы всех разделов подобраны так, чтобы читатель мог познакомиться с общими принципами организации ввода-вывода в каждом случае, начиная от самых простых.

Работа с файлами в MS DOS (имена 8.3)

В основе файловой системы MS DOS лежит древовидная структура каталогов. Корень этой структуры представляет собой совокупность ограниченного числа дескрипторов, описывающих файлы и каталоги (подкаталоги) следующего уровня. Подкаталог представляет собой файл особого типа, который содержит дескрипторы файлов и подкаталогов очередного нижележащего уровня. В отличие от корневого каталога количество дескрипторов в подкаталоге не ограничено и определяется только размером диска. Дескриптор представляет собой экземпляр структуры размером 32 байта. Поля этой структуры содержат различную информацию о файле: идентификатор файла и его характеристики — дата и время создания (модификации), номер начального кластера, длина файла и его атрибуты.
Для использования файла в программе необходимо выполнить следующие операции:

  • создание нового файла;
  • открытие существующего файла;
  • запись/чтение в/из файл(а);
  • закрытие файла.

Операционная система MS DOS поддерживает эти операции с помощью набора функций прерывания 21h. Кроме этих функций данное прерывание содержит функции для работы с каталогами:

  • создать каталог;
  • удалить каталог;
  • сменить каталог.

Существует также ряд других функций для работы с файловой системой, в том числе для поиска файлов и получения информации о них.

Создание, открытие, закрытие и удаление файла

Прежде чем использовать файл в программе, его необходимо открыть с помощью функции 3dh прерывания 21h. Если файл не существует, то перед открытием
его нужно создать. Оба эти действия выполняются одной из следующих функций: 3ch, 5bh, 5ah, 6ch.

Создание файла с усечением существующего до нулевой длины

Вход: АН = 3Ch; CX = атрибуты файла (значения битов: 0=1 — только чтение; 1= 1 — скрытый файл; 2=1 — системный файл; 3=0 — игнорируется; 4=0 — зарезервирован (каталог), должен быть равен 0; 5 — бит архивации; 6= 0 — резерв; 7=1 — общий файл в системе Novell Netware; 8...15=0 — резерв); DS:DX — ASCIZ-имя файла.
Выход: CF=O — АХ = дескриптор файла; CF=1 — АХ = код ошибки (3 — нет такого пути; 4 — нет свободного дескриптора файла; 5 — доступ отказан).

хогсх.сх :атрибуты файла - обычный файл Ids dx,point_fname:
формируем указатель на имя файла movah.5bh :номер функции DOS
int21h открываем файл
jnc ml : обойдем открытие файла
moval,02h ;режим доступа
movah.3dh ;номер функции DOS
int 21h : открываем файл
jc exit :переход, в случае ошибки
mi: :действия при успешном открытии файла:
mov handle.ax :сохраним дескриптор файла

Открытие или создание файла с расширенными возможностями

Функция 6Ch появилась в последних версиях MS DOS (DOS 4.0+). С ее появлением устраняется необходимость отслеживать существование создаваемого файла. Для корректной работы достаточно задать нужные значения в соответствующих регистрах. Анализ возможных значений показывает, что данная функция фактически заменяет существовавшие до этого функции создания и открытия файлов.
Вход: АХ = 6C00h; BL = флаги — режим открытия (значения битов: 7 — наследование; 4-6 — режим разделения; 3=0 — резерв; 0-2 — режим доступа); ВН = флаги (значения битов: 6=0 — использовать стандартную для MS DOS буферизацию; 6=1 — отменить стандартную для MS DOS буферизацию; 5=0 — использовать обычный обработчик ошибок (int 24h); 5=1 — не использовать обычный обработчик ошибок (int 24h), для выяснения причины ошибки использовать функцию 59h int 21h); CX = атрибуты создаваемого (и только) файла; DL = действия, если файл существует или не существует (значения бит: 0-3 — действие, если файл существует (0000 — вернуть ошибку; 0001 — открыть файл; 0002 — открыть файл без сохранения существующего); 4-7 — действие, если файл не существует (0000 — вернуть ошибку; 0001 — открыть файл; 0002 — создать и открыть файл); DH = 00h — резерв; DS:SI — адрес строки с ASCIZ-именем файла.
Выход: CF = 0 — успешное выполнение функции: АХ = дескриптор файла, СХ = состояние (0 — файл открыт; 1 — файл создан и открыт; 2 — файл открыт без сохранения содержимого существующего файла); CF = 1 — АХ = код ошибки.
Следующий фрагмент программы показывает вариант применения функции 6Ch.

:prg07_04.asm - программа демонстрации открытия или создания файла :с расширенными возможностями в текущем каталоге функцией 6Сп.
.data
handle dw 0 :дескриптор файла
filename db 'my_file.txt'.0
point_fname dd filename
.code
хогсх.сх атрибуты файла - обычный файл
movbx.2 :режим доступа обычный - доступ для чтения-записи
movdx.l :если файл существует, то открыть его. в обратной случае вернуть ошибку
(для эксперимента)
Ids si .point_fname-.формируем указатель на имя файла movah.6ch :номер функции DOS int 21h открываем файл jnc ml ;если файл существовал, то переход movdx.lOh -.открыть файл movah.6ch :номер функции DOS int 21h :открываем файл jc exit -.переход в случае ошибки ml: :действия при успешном открытии файла: mov handle.ах :сохраним дескриптор файла

Закрытие файла

В конце работы с файлом его нужно закрыть. Но это действие не является обязательным, так как функция 4сп, которая завершает выполнение программы, в числе прочих действий выполняет и закрытие всех файлов. Вход: АН = 3Eh; BX = дескриптор файла, полученный при его открытии. Выход: CF = 0 — АХ = не определен; CF = 1 — АХ = код ошибки: 6 — недопустимый
дескриптор.
Во время закрытия файла выполняются все незаконченные операции записи на диск в элементе каталога, соответствующего файлу, модифицируются различные поля, в том числе поля времени и даты устанавливаются в текущее время.

;prg07_05.asm - программа демонстрации закрытия файла функцией 3Eh.

:.........
.data
handle dw 0 :дескриптор файла filename db 'my_file.txt',О point fname dd filename
;......:
.code :*......
хогсх.сх :атрибуты файла - обычный файл
Ids dx.point_fnanve :фориируем указатель на имя файла
movah.5bh :номер функции DOS
int 21h :открываем файл
jnc ml ;обойдем открытие файла
moval.02h :режим доступа
1movah.3dh -.номер функции DOS
int 21h :открываем файл
jc exit :переход в случае ошибки
ml: :действия при успешном открытии файла:
mov handle.ах ;сохраним дескриптор файла
т2: ;закрываем файл:

В случае задания имени, как в примере выше, файл будет создан в корневом каталоге текущего диска. Для того чтобы разместить файл в конкретном каталоге, необходимо указать полный путь к нему с завершающим символом ' \' и 13 нулевыми байтами на конце, например:
filename db 'e:\asm_on_a\'.13 dup(0),0

Чтение, запись, позиционирование в файле

При работе с материалом данного раздела помните, что функции чтения и записи можно использовать не только с дескрипторами заранее открытых файлов, но и с дескрипторами стандартных устройств. Эти дескрипторы имеют постоянное значение и доступны в любое время функционирования системы: 0 — клавиатура; 1 и 2 — экран; 3 — последовательный порт СОМ1; 4 — параллельный порт LPT1.

Установка текущей файловой позиции

Чтение-запись в файле производятся с текущей файловой позиции, на которую указывает файловый указатель. Функция 42h MS DOS предоставляет гибкие возможности как для начального, так и для текущего позиционирования файлового указателя для последующей операции ввода-вывода.
Вход: АН = 42h; BX = дескриптор файла, полученный при его открытии; AL = начальное положение в файле, относительно которого производится операция чтения-записи (OOh — смещение (беззнаковое значение в CX:DX) от начала файла; O1h — смещение (значение со знаком в CX:DX) от текущей позиции в файле; 02h — смещение (значение со знаком в CX:DX) от конца файла); CX:DX = смещение новой позиции в файле относительно начальной.
Выход: CF = 0 — DX:AX = значение новой позиции в байтах относительно начала файла; CF = 1 — АХ = код ошибки: 1 — неверное значение в AL; 6 — недопустимый дескриптор файла.
Методы позиционирования, заданные величиной в AL, по-разному трактуют значение в паре регистров CX:DX. Метод al = 00 трактует значение в CX:DX как абсолютное. Два других метода (al = 01 и al = 02 ) трактуют содержимое CX:DX как значение со знаком. Необходимо быть внимательным при выполнении операции позиционирования для избежания последующих ошибок при операции чтения-записи. Так, значение в СХ: DX, позиционирующее указатель, может указывать за пределы файла. При этом выделяются два случая:

  • значение в СХ: DX указывает на позицию перед началом файла — в этом случае последующая операция чтения-записи будет выполнена с ошибкой;
  • значение в СХ:DX указывает на позицию за концом файла — в этом случае последующая операция записи приведет к расширению файла в соответствии со значением в CX:DX.

Примеры использования функции 42h приведем при рассмотрении функций чтения-записи.

Запись в файл или устройство

Запись в файл производится функцией 40h с текущей позиции файлового указателя. Вход: АН = 40 h; ВХ = дескриптор файла; СХ = количество байтов для записи;
DS:DX — указатель на область, из которой записываются данные. Выход: CF = 0 — АХ = число действительно записанных байтов в файл или устройство; CF = 1 — АХ = код ошибки: 5 — в доступе отказано; 6 — недопустимый дескриптор.
Если при вызове функции 40h регистр СХ равен нулю, то данные в файл не записываются и он усекается или расширяется до текущей позиции файлового указателя. Если СХ не равен нулю, то данные в файл записываются начиная с текущей позиции файлового указателя. Операция записи также продвигает файловый указатель на число действительно записанных байтов.
Положение файлового указателя можно изменять явно с помощью функции 42h. Вначале приведем пример программы, выводящей данные на экран.

:prg07_08.asm - программа демонстрации вывода на экран строки функцией 40h.
.data
string db 'строка для вывода на экран функцией 40h'
len_string=$-stnng point_fname dd string
..........
.code
movbx.l -.стандартный дескриптор - экран
mov cx.1en_string
Ids dx.point_fname;формируем указатель на строку string
movah.40h -.номер функции DOS
int 21h ;выводим
jc exit ;переход в случае ошибки
пор -.для тестирования

Далее приведем пример программы, которая заполняет файл my_file.txt данными в виде строк символов, вводимых с клавиатуры. Длина строк — не более 80 символов. Нажатие клавиши Enter после ввода каждой строки означает, что эта строка символов должна являться отдельной строкой файла my_file.txt. Для этого перед выводом каждой строки в файл в конце ее необходимо вставлять символы OdOah. При нажатии клавиши Пробел в начале ввода очередной строки (ASCII-код — 3210 или 2016) направление ввода данных в файл изменяется следующим образом: файл расширяется на величину, равную количеству уже введенных символов, и дальнейший ввод осуществляется с конца файла. Завершение работы программы определяется моментом, когда оба введенных потока Ь в файле встречаются (не перекрываясь).

:prg07_09.asm - программа заполнения файла my_file.txt данными в виде строк символов.
:вводимыми с клавиатуры.
buf_Oahstruc
len_buf db 83 ;длина buf_0ah
len_in db 0 действительная длина введенного слова (без учета 0dh)
buf_in db 82 dup (20h) :буфер для ввода Сс учетом 0dh и позднее добавляем Oah)
ends
.data
handle dw 0 :дескриптор файла
filename db 'my_file.txt',0
point_fname dd filename
buf buf_0ah<>
prev_d label dword ;для сохранения длины предыдущей строки при выводе с конца файла prev dw 0
dw 0
middle dd 0 ;позиция в середине файла, при достижении которой снизу выходим :из программы
.code
:-----открываем файл-----...............................--
хогсх.сх ;атрибуты файла - обычный файл
movbx,2 ;режим доступа - доступ для чтения-записи, режим буферизации MS DOS
movdx,12h ;если файл существует, то открыть его без сохранения прежнего содержимого, :в обратном случае создать его
Ids si ,point_fname:формируем указатель на имя файла
movah.6ch ;номер функции DOS
int 21h открываем (создаем) файл
jc exit :если ошибка, то переход на конец ;действия при успешном открытии файла:
mov handle.ax ,-сохраним дескриптор файла ;—позиционируем файловый указатель с начала файла.......
mov ah.42h
хог al,al
хог ex,ex
хог dx.dx
mov bx, handle
int 21h cycl: ;вводим очередную строку с клавиатуры
lea dx.buf
mov ah,Oah
Int 21h ;для красоты ввода выводим на экран символ Oah
mov dl .Oah
mov ah.2
int 21h
emp buf.buf_in.20h;первый символ введенной строки сравниваем с пробелом
je revers ;переход на изменение ввода - добавляем Oah в конец введенной строки
lea si.buf.buf_in
mov al .buf .lenjn
cbw push si
add si ,ax
incsi учитываем неучтенный в lenjn символ 0dh
mov byte ptr [si],Oah H--......вывод в файл:..........................---........
I popdx указатель на область, откуда будем выводить строку
mov bx.handle
add ax,2 учитываем неучтенный в len_in символ 0dh
movcx.ax :длина выводимых данных
mov ah.40h
int 21h
jmp cycl
revers: ;записываем файл с конца, предварительно расширив его ;узнаем. сколько было уже записано до этого: ;для этого вначале сбрасываем буферы на диск
mov bx.handle
mov ah.68h
int 21h ;теперь можно и узнать - определение длины файла:
mov al ,2
хог сх.сх
хог dx.dx ;CX:DX -0 - нулевое смещение
mov ah,42h
int 21h :в DX:AX возвращается длина файла в байтах
jc exit :если ошибка :формируем полную длину в edx
shl eax,16
shld edx.eax,16
mov middle.edx сохраним как условие выхода из программы при достижении снизу расширение файла с помощью функции 42h int 21h и последующей записи :умножаем длину на 2. при первой операции записи файл расширится:
shl edx.l
shld ecx.edx.16
mov al.O
хог сх.сх
mov ah.42h
int 21h расширяем файл, устанавливая указатель
jc exit :если ошибка расширим файл, выведя последнюю введенную строку с пробелом:
cycl2: lea si,buf,buf_in
mov al .buf .lenjn
cbw ptush si
add si.ax
incsi учитываем неучтенный в lenjn символ 0dh
добавляем Oah в конец введенной строки
mov byte ptr [si],Oah ;выводим в файл:
popdx указатель на область, откуда будем выводить строку
add ах.2 учитываем неучтенный в len_in символ 0dh
movcx.ax :длина выводимых данных
movprev.ax .сохраним длину для корректировки при выводе следующей строки
mov bx.handle movah.40h int 21h jc exit
;сбрасываем буфер, чтобы смотреть изменения в файле при работе в отладчике -:легче запретить (см. обсуждение ниже)
mov bx,handle
mov ah,68h Int 21h :вводим очередную строку с клавиатуры
lea dx.buf
mov ah.Oah
Int 21h :для красоты ввода выводим на экран символ Oah
mov dl .Oah
mov ah,2
int21h
;......использование 42h с отрицательным смещением относительно
:текущего значения файлового указателя:
устанавливаем файловый указатель в позицию вывода следующей строки
;с учетом того, что выводим с конца (текущей позиции) файла:
хог есх.есх
mov al.buf,len_in
cbw
add prev.ax
add prev.2 учитываем наличие OdOah
sub ecx.prev_d :получаем отрицательное смещение - сформируем его в паре СХ:DX
shrd edx,ecx,16
shr edx.16 :довернем edx
shr ecx.16 :и есх устанавливаем файловую позицию для записи очередной строки
mov bx,handle
mov ah.42h
moval.l ;смещение от текущей позиции
int 21h :сравним текущую позицию с middle
shl eax.16
shld edx,eax,16
cmp edx,middle
jl exit
jmp cycl2 exit:

Программа выглядит не очень эстетично, но главная ее цель достигнута — показать работу с файловым указателем при записи в файл. Мы попробовали разные варианты: позиционирование на конец файла (при этом можно узнать длину файла); использование отрицательного смещения (задавая нулевое значение в CX:DX при al = 1 можно получить в DX:AX текущую позицию в файле); расширение файла путем задания в СХ: DX заведомо большего значения, чем длина файла. Как видно из программы выше, все эти и другие эффекты достигаются за счет манипулирования значениями в парах СХ :DX и DX:AX, а также в регистре AL, где задается начальное положение в файле, относительно которого производится операция чтения-записи.
В заключение рассмотрения функции 40h записи в файл отметим то, для чего мы использовали функцию сброса буферов на диск 68h. Для этого коротко необходимо коснуться проблемы буферизации ввода-вывода в MS DOS. MS DOS ис-
пользует буферизацию ввода-вывода для ускорения работы с диском. При этом, р частности, данные, записываемые на диск, не записываются на него сразу, а по-щешаются вначале в буфер. Запись буфера на диск производится при его заполнении- Буферизацию эффективно использовать при интенсивной работе с одними и теми же данными. Тогда при необходимости чтения данных с диска они 6уДУт читаться из буфера. В нашей программе буферизация нам только мешала, так как при работе в отладчике мы не могли своевременно наблюдать за изменениями выходного файла my_file.txt Для этого нам приходилось использовать функцию 68h для принудительного сохранения буферов на диск. Вход: АН = 68h; BX = дескриптор файла. Выход: CF = 0 в случае успеха; CF = 1 — АХ = код ошибки.
В результате работы функции все данные из буферов дисков DOS немедленно записываются на диск, при этом модифицируется соответствующий файлу
элемент каталога.
Для нашей задачи буферизацию лучше вовсе запретить, тогда отпадет необходимость в принудительном сохранении строк в файле для того, чтобы в динамике отслеживать его изменения. Для этого при вызове функции 6ch в регистре ВН необходимо установить бит 6 следующим образом: 6 = 0 — использовать стандартную для MS DOS буферизацию; 6 = 1 — отменить стандартную для MS DOS буферизацию. В нашем примере это можно сделать так:

:......открываем файл-------------------------------------
хогсх.сх атрибуты файла - обычный файл
mov bx.4002h :режим доступа - доступ для чтения-записи, запрет буферизации
movdx,12h :если файл существует, то открыть его без сохранения прежнего
содержимого, в обратном случае создать файл Ids si.point_fname:формируем указатель на имя файла movah.6ch :номер функции DOS int21h открываем (создаем) файл jc exit :если ошибка, то переход на конец
--------------------------------------------------------------------------

Все вызовы функции 68h в приведенной выше программе можно закомментировать.

Чтение из файла или устройства

Чтение из файла в область памяти осуществляется функцией 3Fh.
Вход: АН = 3Fh; BX = дескриптор файла; СХ = количество байтов для чтения; DS-.DX — указатель на область памяти, в которую помещаются прочитанные байты. Выход: CF = 0 — АХ = число действительно прочитанных байтов из файла; CF = 1 — АХ = код ошибки: 5 — в доступе отказано; 6 — недопустимый дескриптор.

Чтение данных производится начиная с текущей позиции в файле, которая после успешного чтения смещается на значение, равное количеству прочитанных байтов. Если в качестве файла используется стандартная консоль (клавиатура), то чтение производится до первого символа CR (carriage return) с кодом 0dh, соответствующего нажатию клавиши Enter. Это, кстати, еще один способ ввода " Данных с клавиатуры в программу. Кроме символов введенной строки в ее конец помещаются символы 0dh и Oah. Это необходимо учитывать при задании размера буфера для ввода. Способ ввода данных с экрана с помощью функции 3Fh . стрирует приведенный ниже пример программы.

:prg07_10.asm - программа демонстрации ввода данных с экрана с помощью функции 3Fh.
.data
string db 80 dup Г ") 1en_string=$-string point_fname dd string
.code
:.........вводим с экрана......-----.....----------------
movbx.O стандартный дескриптор - клавиатура
mov cx.len_string
Ids dx.point_fname:формируем указатель на строку string
movah,3fh ;номер функции DOS
int 21h
jc exit :переход в случае ошибки ;---------выводим на экран---------------------...........
movbx.l стандартный дескриптор - экран :две строки ниже в данном случае можно опустить
mov ex.len_string
Ids dx.point_fname;0opMnpyeM указатель на строку string
movah.40h ;номер функции DOS
int 21h открываем файл
jc exit :переход в случае ошибки

Для демонстрации работы функции с дисковым файлом приведем программу чтения и вывода на экран содержимого файла, имя которого вводится в командной строке. Побочная цель этой программы — научиться обрабатывать в программе командную строку DOS. Поясним последний момент. Содержимое командной строки, следующее за именем программы при ее вызове и называемое хвостом команды, помещается в префикс программного сегмента (PSP) со смещением 80h от его начала и максимально имеет размер 128 байт. Первый байт этой области содержит длину хвоста команды, а первый символ хвоста, при его наличии, располагается со смещением 81h от начала PSP. Последний символ хвоста команды — всегда 0dh. Начало PSP найти очень легко — когда программа загружается в память для исполнения, то загрузчик устанавливает регистры ES и DS равными адресу PSP.

:prg07_ll.asm - программа чтения и вывода на экран содержимого файла. ;имя которого вводится в командной строке.
.data
filejiame db 128 dup (" ") ;буфер, в который будет помещен путь к файлу
point_fname dd file_name
string db 80 dup (" ")
len_stnng=$-string
point_string dd string
>handle dw 0 дескриптор файла
[size_f dd 0 :размер файла
.code
main: :копируем командную строку в filejiame
;вначале уберем (установкой указателя) ведущие пробелы в командной строке
:перед путем к файлу: movdi ,81h mov al," " mov ex. 128 repe scasb
dec di push di pop si
movax.@data -.адрес сегмента данных - в регистр АХ
mov es.ax :ax в es iTOvcl.ds:[80h] deccl
lea di .filejiame rep movsb push es pop ds
:--------открываем файл--......-----------------.........
moval.OOh :режим доступа - только чтение
Ids dx.point_fname:формируем указатель на имя файла
movah.3dh ;номер функции DOS
int 21h открываем файл
jc exit :переход в случае ошибки
mov handle.ax
;--------определяем размер файла-------------------------
raovbx.ax -.дескриптор файла - в bх mov al .2 xor ex. ex
xordx.dx :CX:DX =0 - нулевое смещение mov ah.42h
int 21h ;в DX:AX возвращается длина файла в байтах jc exit
:если ошибка :формируем полную длину в
edx shl eax.16 shld edx.eax.16 mov size_f.edx сохраним как условие выхода из программы при достижении снизу
;--------устанавливаем указатель на начало файла---.......
mov Ьх.handle :дескриптор файла - в Ьх
mov al .0
xor ex.ex
xordx.dx ;CX:DX =0 - нулевое смещение
mov ah,42h
int 21h :текущий указатель в начале файла
jc exit :если ошибка
;.........читаем файл по lenjstring байт................---
cycl: mov bx.handle :дескриптор файла в Ьх mov cx.lenjsthng
Ids dx.pointjstring :формируем указатель на строку string movah.3fh
:номер функции DOS int 21h :открываем файл jc exit ;переход в случае ошибки
;.........выводим на экран целиком.....---------.......----------
movbx.l стандартный дескриптор - экран
mov cx.len_string
Ids dx.point_string .формируем указатель на строку string movah.40h
;номер функции DOS
int 21h открываем файл
jc exit :переход в случае ошибки
cwde расширяем количество выведенных байт
sub size_f.eax cmp size_f.О
jleexit :достигли конца файла
. jmp cycl
exit: :выход из программы
mov al .1 int 21h
.......

He забывайте после определения размера файла возвращать файловый указатель в нужное место файла.

Получение и изменение атрибутов файла

MS DOS позволяет получить для анализа и при необходимости изменить имя файла, байт атрибутов файла, время и дату его последней модификации в элементе каталога, соответствующего этому файлу. Для этого предназначены функции 43h, 56h, 57h. Подфункция 00 функции 43h прерывания 21h предназначена для получения слова атрибутов файла.

Получить атрибуты файла

Вход: АХ = 4300h; DS:DX — ASCIZ-строка с именем (путем) файла.
Выход: CF = 0 — СХ = слово атрибутов файла; CF = 1 — АХ = код ошибки: 1 — неверное значение в AL; 2 — файл не найден; 3 — несуществующий путь; 5 — доступ запрещен.

:prg07_12.asm - программа демонстрации получения атрибутов файла.
.data
fname db "maket.asm".
point_fname dd fname
.code
:----.....получим атрибуты файла-----------------........-
Ids dx.point_fname:формируем указатель на строку string movax.4300h ;номер функции DOS int 21h
jc exit :переход в случае ошибки :в сх атрибуты (см. ниже)

Напомним формат байта атрибутов:

Биты Описание
7 Разделяемый в Novell NetWare
6 Не используется
5 Архивный
4 Каталог
3 Метка тома (только исполнение Novell NetWare)
2 Системный
1 Скрытый
0 Только чтение

Установить атрибуты файла

Подфункция 01 функции 43h прерывания 21h предназначена для установления
слова атрибутов файла.
Вход: АХ = 4301п; СХ = новое слово атрибутов файла; DS:DX — ASCIZ-строка с именем (путем) файла.
Выход: CF = 0 — АХ = не определен; CF = 1 — АХ = код ошибки: 1 — неверное значение в AL; 2 — файл не найден; 3 — несуществующий путь; 5 — доступ запрещен.

Переименовать файл

Для переименования файла используется функция 56h.
Вход: АН = 56h; DS:DX — ASCIZ-имя существующего файла; ES:DI — ASCIZ-имя
нового файла; CL = маска атрибутов.
Выход: CF = 0 — при успешном переименовании; CF = 1 — АХ = код ошибки: 2 — файл не найден; 3 — несуществующий путь; 5 — доступ запрещен; 1 lh — устройства для старого и нового файлов не совпадают.
Функция 56h позволяет произвести перемещение между каталогами, не изменяя устройства.

;prg07_13.asm - программа перемещения между каталогами.
;не изменяя устройства функцией 56h.
¦
.data
fname_s db "maket.asm".О
point_fname_s dd fname_s
fname_d db "e:\maket.asm".0
point_fname_d dd fname_d
.code
;.....переместим файл из текущего в корневой каталог------
Ids dx.point_fname_s :формируем указатель на строку fname_s (исх. файл)
1 es di,point_fname_d ;формируем указатель на строку fname_d (целевой файл)
Imov ah.56h ;номер функции DOS int 21h
jc exit ;переход в случае ошибки

Получить дату и время создания или последней модификации файла
Получить/изменить дату и время создания или модификации файла можно с помощью подфункций функции 57h.
Вход: АХ = 5700h; ВХ = дескриптор файла.
Выход: если CF = 0: СХ = время, DX = дата. Если CF = 1: АХ = код ошибки (CF = п. 1 — недопустимый номер подфункции в А1; 6 — недопустимый дескриптор Время и дата файла получаются в следующих форматах.

Время Дата
Биты Описание Биты Описание
15-11 Часы (0-23) 15-9 Год
10-5 Минуты 8-5 Месяц
4-0 Секунды 4-0 День

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

Вход: АХ = 5701п; ВХ - дескриптор файла; СХ - новое время, DX = новая дата. Выход: если CF = 0: СХ = время, DX = дата. Если CF = 1 — АХ = код ошибки: 1 — недопустимый номер подфункции в А1; 6 — недопустимый дескриптор.

Работа с дисками, каталогами и организация поиска файлов

Задача поиска традиционно является актуальной. При рассмотрении вопроса работы с файлами ее также не обойти. Мы рассмотрим номенклатуру средств, предлагаемых MS DOS для поиска файла и определения его местоположения в древовидной структуре каталогов текущего диска.
Во время работы с предыдущими программами вы заметили, что при задании имен файлов мы практически не указывали имен дисководов и путей к этим файлам. MS DOS имеет средства для установки текущего диска и каталога, в котором выполняются все текущие операции с файлами. При необходимости можно изменить текущий диск и каталог. Ниже приведено несколько функций для работы с текущими диском и каталогом — определение, изменение, получение информации.

Получить номер заданного по умолчанию дисковода

Вход: АН = 19h.
Выход: AL - номер дисковода (00h - A:, 01h - В: и т. д.).

:prg07_14.asm - программа получения номера текущего (по умолчанию) дисковода функцией 19h.

I .code
m ;.....Получить номер текущего (по умолчанию) дисковода ---
movah.l9h :номер функции DOS
1nt2lh
jc exit -.переход в случае ошибки :в al номер текущего диска

Выбрать заданный по умолчанию диск

Вход: АН = OEh; DL = номер нового диска по умолчанию (00h = A:, 01h = В: и т. д.).
Выход: AL = максимально возможный в данной системе номер дисковода (00h =
A:, 01h = В: и т. д.) определяется на основе параметра LASTDRIVE в файле
CONFIG.SYS.

Получить информацию о свободном дисковом пространстве

Вход: АН = 36h; DL = номер диска (00h- текущий,01h = А: и т. д.).
Выход: АХ = FFFFh — неправильный номер устройства в DL,
иначе: АХ = число секторов в одном кластере; ВХ - число свободных кластеров; СХ = размер сектора (в байтах); DX = общее число кластеров на диске.

Используя информацию, возвращаемую функцией 36h, можно подсчитать как свободное пространство на диске — произведение АХ*ВХ*СХ, так и полный объем диска — произведение AX*CX*DX.
MS DOS предоставляет следующие возможности для манипулирования каталогами: создание и удаление каталога, получение информации о текущем каталоге и его смена.

Создание каталога

Вход: АН = 39h; DS:DX — ASCIZ-строка пути к создаваемому каталогу. Выход: АХ = не определен (CF ¦ 0); АХ - код ошибки (CF = 1): 3 — несуществующий путь; 5 — доступ запрещен.
Путь к каталогу должен содержать перечисление всех каталогов начиная от корневого на пути к создаваемому каталогу, при этом они, естественно, должны существовать. Последнее имя каталога — имя создаваемого каталога.

;prg07_15.asm - программа демонстрации создания каталога функцией 39h.
.data
dname db "c:\windows\my_diг".0
point_dname dd dname
.code
;.....создадим каталог в каталоге c:\windows.......-.......
Ids пате;формируем указатель на строку с именем нового каталога
movah,39h :номер функции DOS
int 21h
jc exit ;переход в случае ошибки

Удаление каталога

Вход: АН = 3Ah; DS:DX — ASCIZ-строка пути к удаляемому каталогу. Выход: CF = 0 — АХ = не определен; АХ = код ошибки (CF = 1): 3 — несуществующий путь; 5 — доступ запрещен; 10h — попытка удаления текущего каталога. Удаляемый каталог должен быть пустым.

:prg07_16.asm - программа демонстрации удаления каталога функцией ЗАп.
.data
dname db "c:\windows\my_diг",О point_dname dd dname
.code
:----удалим каталог my_dir в каталоге c:\windows---------
Ids dx.point_dname;формируем указатель на строку с именем нового каталога movah.3ah :номер функции DOS *
int 21h
jc exit ;переход в случае ошибки

Изменить текущий каталог

MS DOS позволяет установить текущий каталог для того, чтобы не указывать полный путь для последующих операций с файлами. При необходимости можно получить полный путь к текущему каталогу в виде ASCIZ-строки. Вход: АН = 3Bh; DS:DX — указатель на буфер, содержащий полный путь от корневого каталога в виде ASCIZ-строки (до 64 байт). Выход: CF = 0 — АХ = не определен; CF = 1 — АХ = код ошибки: 03h — путь не найден.

:prg07_17.asm - программа демонстрации изменения текущего каталога функцией ЗВп.
.data
dname db "c:\windows",0
point_dname dd dname
.code
|.........
:.....изменим текущий каталог на каталог c:\windows--------
Ids dx.point_dname:формируем указатель на строку с именем нового каталога
movah.3bh :номер функции DOS
int21h
jc exit . :переход в случае ошибки
;.........

Получение текущего каталога

Вход: Ан = 47h;
DL = номер устройства (00h= текущее (по умолчанию),01h = А: и т. д.) DS:SI — указатель на 64-байтный буфер для записи полного пути от корневого каталога (ASCIZ-строка).
рыход: АХ = не определен или 0100h(CF=0);
АХ = код ошибки (CF=1): OFh — недопустимый дисковод.

:prg07_18.asm - программа демонстрации получения текущего каталога функцией 47h.
.data
dname db "e:\tools".О
point_dname dd dname
d_cur_name db 64 dup (20h).0
point_d_cur_name dd d_cur_name
.code
:.....изменим текущий каталог на каталог \tools ...........
Ids dx,point_dname;формируем указатель на строку с именем нового каталога
movah,3bh ;номер функции DOS
int 21h
jc exit :переход в случае ошибки
:----получим текущий каталог......-----.....
Ids si,point_d_cur_name ;формируем указатель на строку с именем нового каталога
mov ah.47h ;номер функции DOS
int 21h
jc exit :переход в случае ошибки

Возвращаемый путь не содержит имени диска и первого символа \.
Последняя проблема, на которой мы остановимся в этом разделе, — проблема поиска файлов. Для поиска в каталогах используется пара функций 4eh и 4fh. В имени искомого файла можно указывать символы шаблона * и ?. Совместное использование функций 4eh и 4fh подчинено следующему алгоритму. Первой вызывается функция 4eh. В качестве параметров ей передаются адрес ASCIZ-строки с путем к искомому файлу и комбинация его атрибутов. Имя файла может быть задано в виде шаблона. В случае успеха (cf=0), то есть при обнаружении первого подходящего шаблону файла, данная функция помещает его имя и расширение в область DTA со смещением leh от ее начала (см. таблицу ниже). Далее можно либо открыть файл, либо продолжить поиск, но уже функцией 4fh. При работе с шаблоном функцию 4fh можно вызывать циклически, до тех пор пока в процессе перебора не будут просмотрены имена всех подходящих файлов. Об этом можно узнать по состоянию флага cf, которое должно стать равным 1 в случае, когда файлов, удовлетворяющих шаблону, в данном каталоге больше нет.

Поиск первого соответствующего шаблону файла

Вход: АН = 4Eh; СХ = атрибуты файла (биты 0 и 5 игнорируются); DS:DX — ASCIZ-имя файла (возможно, с путем к нему и символами шаблона * и ?).
Выход: если CF - 0, то в DTA возвращается блок данных для первого найденно го файла (см. ниже). Если CF - 0, то в АХ - код ошибки: 2 — файл не най" ден; 3 — несуществующий путь; 12h — больше файлов в каталоге нет Область DTA (Data Transfer Area) располагается в префиксе программист
сегмента со смещением 80h от его начала и занимает 128 байт. При успешном
окончании поиска функция 4Eh (и 4Fh тоже) помещает блок данных, имеющий
приведенный ниже формат.

Смещение
Размер в байтах
Описание
00h
1
Буква логического диска, если бит 7 = 0, то удаленный диск
01h
И
Поисковый шаблон
0Сh
1
Атрибуты поиска
0Dh
2
Порядковый номер файла в каталоге
0Fh
2
Номер кластера начала каталога предыдущего уровня
11h
4
Резерв
15h
1
Атрибуты найденного файла
16h
2
Время создания (модификации) файла
18h
2
Дата создания файла
1Ah
4
Размер файла
1Eh
13
ASCIZ-имя файла с расширением

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

Найти следующий соответствующий шаблону файл

Вход: АН = 4Fh; в области DTA должен содержаться блок данных, заполненный единственным вызовом 4eh в начале поиска.
Выход: если CF = 0 — успех; если CF = 1 — в АХ = код ошибки: 12h — больше файлов в каталоге нет.
Для работы с DTA в системе MS DOS существуют две функции lah и 2fh. После старта программы текущей DTA является область по адресу PSP:OO8Oh. Мы уже имели с ней дело, когда рассматривали проблему обработки содержимого командной строки.

Получить адрес области DTA

Для выполнения работы, связанной с файлами, MS DOS предоставляет возможность установить свою область DTA.
Вход: АН = 2Fh.
Выход: ES:BX — адрес области, которую впоследствии функцией lah можно сделать текущей областью DTA для последующих операций ввода-вывода.
установить текущую область DTA
Вход: АН - 1Ah; DS:DX — адрес области, которая будет областью DTA для последующих файловых операций.
Понятно, что даже если мы устанавливаем свою область DTA, все смещения и данные, формируемые функциями 4Eh 4Fh, остаются актуальными.

Работа с файлами в MS DOS (длинные имена)

Перечисленные выше функции работают в различных версиях «чистой» системы MS DOS, вплоть до версии 6.22 включительно. Операционные системы Windows 95/98/Mil также поддерживают свою версию MS DOS, которая имеет номер 7.0. Операционная система Windows 95/98/Mil организует для программ MS DOS специальную среду для работы, называемую сеансом DOS. Система MS DOS 7.0, будучи созданной для работы в среде Windows 95/98/Mil, имеет в своем составе средства для работы с файловой системой Windows. Эта файловая система, как известно, отличается тем, что полное имя файла может достигать длины 255 символов. MS DOS 7.0 также умеет работать с длинными именами файлов. В данном разделе мы рассмотрим предназначенные для работы с файловой системой Windows средства среды MS DOS, работающей под управлением
Windows.
Определить факт того, в какой системе работает программа, можно по результатам работы функций 30h — получить версию DOS (прерывания 21п) и 4аЗЗп (прерывания 2fh).
Вход: АН = 30h; AL = определяет значение, возвращаемое в ВН: 00h— OEM-номер (как для DOS 2.0-4.0x);01h — номер версии.
Выход: AL = главный номер версии; АН - младший номер версии; BL:CX = 24-битный серийный номер пользователя (необязательно).

:prg07_19.a$m - программа демонстрации определения факта того. ;в какой системе работает программа.
.code
;.....определим номер версии ОС MS DOS
mov al .00
movah.30h ;номер функции DOS
int21h ;А1-главный номер версии. АН-младший номер версии
]с exit ;переход в случае ошибки

В регистрах AL и АН возвращаются главный и младший номера версии MS DOS. При функционировании под Windows эти номера равны 07h и Oah соответственно. Задание значения AL = 01 дает такой же эффект.

:prg07_20.asm - программа демонстрации определения факта работы в среде MS DOS 7.0.
.code
:-----определить факт работы в среде MS DOS 7.0
movax.4a33h ;номер функции DOS int 2fh
cmp ax, 0
jneexit ;переход, если работа не в среде MS DOS 7.0

Последняя функция возвращает 0 для MS DOS версии 7.0 и выше. Установить факт того, что система поддерживает длинные имена файлов, можно вызовом функции 71a0h прерывания 21п — получить информацию о томе. Если она возвращает ошибку (CF = 1), то текущая файловая система не поддерживает длинных имен файлов. Для вызова этой функции необходимо указать корневой каталог тома, о котором необходимо получить информацию. Вход: АХ = 71A0h; DS:SI — ASCIZ-имя корневого каталога тома, о котором необходимо получить информацию (например, "С:\"); ES:DI — буфер для имени файловой системы; СХ ¦= размер буфера, адрес которого задан в ES: DI (32 байта).
Выход: CF = 0 в случае успеха, следующие регистры установлены: ВХ = флаги файловой системы: 0 — при поиске учитывать регистр букв в именах файлов; 1 — сохранять регистр букв в элементах каталога; 2 — использование символов Unicode в именах каталогов и файлов; 3-13 — резерв (0); 14 — поддержка DOS-функций для длинных имен файлов; 15 — сжатый том; СХ = максимальная длина файловых имен (обычно 255); DX = максимальная длина пути (обычно 260); ES: DI — в буфере по этому адресу ASCIZ-имя файловой системы, например "FAT", "FAT32", "NTFS", "CDFS"; CF = 1 в случае неудачи, при этом АХ = код ошибки или AX=7100h, если функция не поддерживается.
В Windows 95/98 появились дополнительные возможности как самой файловой системы, так и средств по ее управлению. Основное нововведение — поддержка длинных имен файлов. Основа файловой системы та же — таблица разрешения файлов FAT, но любой файл в этой системе имеет два имени — длинное имя и его псевдоним, который соответствует формату 8.3. Данный псевдоним создается системой Windows 95/98 автоматически.
Нужно правильно понимать различие в способах использования длинных имен файлов в приложениях MS DOS и Win32. Приложения MS DOS получают до-ступ к длинным именам файлов с помощью дополнительных функций прерывания 21h. Приложения Windows используют для этого соответствующие функции API.
Длинное имя файла представляет собой ASCIIZ-строку длиной до 255 символов. Система формирует псевдоним для этого имени форматом 8.3 в соответствии со следующим правилом: берутся первые 6 символов длинного имени, после них добавляется символ тильда (-), за тильдой ставится некий порядковый номер. Для первого имени формата 8.3 это 1. Если такой псевдоним уже существует, то порядковый номер очередного псевдонима будет на 1 больше. Расширение псевдонима формируется из первых трех символов расширения длинного имени (если оно существует). Если похожих имен много, то номер в псевдониме может быть двузначным, при этом первая (символьная) часть псевдонима сокращается
до 5 символов, и т. д.
Рассмотренные выше функции MS DOS для работы с файлами и каталогами не поддерживают длинных имен. Для этого система Windows 95/98 предоставляет приложениям MS DOS аналогичные функции, но имеющие другие номера. Впрочем, при внимательном рассмотрении большинства из этих номеров, видно, какой из старых функций они соответствуют. Новые номера состоят из четырех цифр: первые две — 071h, последние две — номер старой функции. Для некоторых функций существуют особенности в их работе. Так, для поиска файлов по-прежнему используются две функции (по новой нумерации — 714eh и 714fh) прерывания 21h. Новые функции теперь возвращают информацию о файлах через специальную структуру WI N32_F INDDATA, адрес которой возвращается в качестве
результата их работы.
При работе с функциями, поддерживающими длинные имена файлов, используются еще две структуры: by handle_f 11 e_information и filetime. Назначение структуры by_hand1e_file_iinformation и работу с ней мы рассмотрим при обсуждении функции MS DOS 71a6h. Структура filetime содержит 64-разрядное значение, которое определяет число 100-наносекундных интервалов, прошедших с 12:00 утра 1 января 1901 года.

FILETIME Struc
DwLowDateTime dd ? :младшие 32 бита значения времени DwHighDateTime dd ? хтаршие 32 бита значения времени FILETIME ends

Теперь приведем перечень функций прерывания 21h, работающих с файлами, которые имеют длинные имена. Для удобства дальнейшего рассмотрения в следующей таблице приведены соответствующие функции API WIN32 и «старые» функции прерывания 21h.

Новая
функция int 21h
Старая функция int 21h
Назначение
Функция API Win32
5704h
Получить дату и время последнего доступа
GetFileTime
5705h
Установить дату и время
SetFileTime
последнего доступа
5706h
Получить дату и время создания
GetFileTime
5707h
Установить дату и время создания
SetFileTime
7139h
39h
Создать каталог
CreateDirectory
713Ah
3ah
Удалить каталог
RemoveDirectory
713Bh
3bh
Изменить текущий каталог
SetCurrentDi rectory
7141h
41h
Удалить файл
DeleteFile
7143h
43h
Получить или установить
GetFileAttributes,
атрибуты файла
SetFileAttributes
7147h
47h
Получить текущий каталог
GetCurrentDirectory
714Eh
4Eh
Найти первый файл
FindFirstFile
714Fh
4Fh
Найти следующий файл
FindNextFile
7156h
56h
Переименовать файл
MoveFile
7160h
Получить полный путь
GetFullPathName
7160h
Получить полный путь
GetShortPathName
с-краткими именами
7160h
Получить полный путь
Отсутствует
с длинными именами
716Ch
3ch, 3dh, 5bh
Создать или открыть файл
CreateFile, OpenFile
71A0h
Получить информацию о томе
GetVolumelnfonnati on
71Alh
Завершить поиск
FindClose
71A6h
Получить информацию о файле
GetFi1 elnformationByHandle
по описателю
71A7h
Преобразовать время файла
Fi1eTi meToDOSDateTime
в DOS-время
71A7h
Преобразовать DOS-время во время файла
00SDateTi meToFi1eTi me
71A8h
Создать псевдоним
Отсутствует
71A9h
Создать или открыть файл
Отсутствует
на сервере
71AAh
Провести подмену
Отсутствует
71AAh
Отменить подмену
Отсутствует
71AAh
Получить информацию
Отсутствует
о подмене

Рассмотрим наиболее интересные в контексте нашего изложения функции этой таблицы. Информацию по остальным функциям можно получить, в частности, из MSDN. Порядок рассмотрения будет от простых функций к сложным, так как это было в предыдущем разделе, посвященном функциям работы с файлами ДО DOS, имеющими короткие имена.

Создание, открытие, закрытие и удаление файла

функции MS DOS, поддерживающие длинные имена файлов, имеют номера из четырех цифр — первые две равны 71h, последние две соответствуют номеру аналогичной старой функции MS DOS. В программах старые и новые функции применяются вместе по принципу: там, где функция должна работать непосредственно с длинными именами файлов и каталогов, применяются новые функции; там, где функция работает с дескриптором файла, используются старые функции. Новые функции также используются для реализации новых возможностей по работе с файловой системой.

Открытие или создание файла

Для создания или открытия файла с длинным именем используется функция 716Ch (создать или открыть файл). Эта функция аналогична функции 6ch, которая появилась в последних версиях MS DOS (DOS 4.0+). Мы уже обсуждали ее в разделе, посвященном функциям работы с файлами с короткими именами.
Вход: АХ = 716Ch; BX = режимы доступа и флаги:
режим доступа: 0000h — файл только для чтения; 0001h — файл только для записи; 0002h — файл для чтения и записи; 0003h — резерв; 0004п — открыть файл для чтения без изменения даты последнего доступа к файлу; режим разделения: 0000h — режим эмуляции — файл можно открывать любой программе любое количество раз; 00Wh — файл открыт в монопольном режиме доступа; 0020h — файл открыт в монопольном режиме доступа по записи; 0030h — файл открыт в монопольном режиме доступа по чтению; 0040И — открыть файл, разрешая другим процессам доступ по чтению-записи, но с запретом режима эмуляции; флаги: 0080h — дочерний процесс не наследует дескриптор файла, его при необходимости нужно передавать явно; Ol00h — не использовать буферизацию или кэширование средствами ОС, операции чтения-записи выполняются напрямую с диском в соответствии с текущим положением файлового указателя; 0200h — файл нельзя сжимать; 0400h — содержимое регистра 01 следует использовать как порядковый номер в псевдониме файла; 2000h — не вызвать обработчик критической ошибки (int 24h), MS DOS вернет программе код ошибки; 4000h — после каждой операции записи MS DOS будет отправлять данные на диск без их кэширования; СХ - атрибуты создаваемого (и только) файла: 0000h — файл доступен по записи и чтению; 0001h — файл доступен по чтению; 0002h — скрытый файл; 0004п — системный файл; 0008h — метка тома; 0020h — архивный
файл;
DX ~ действия, если файл существует или не существует, значения битов: 00lOh — вернуть ошибку, если файл существует, иначе создать файл; 0001h — открыть файл, если он существует, иначе вернуть ошибку;

0002h — открыть файл без сохранения существующего, иначе вернуть ошибку (если файл не существует); DS:SI — ASCIZ-имя файла;
DI — порядковый номер, который добавляется к концу имени в псевдониме файла (для этого должен быть задан флаг 0400h в регистре ВХ) Номер будет десятичным письмом, то есть если DI=0010h, то конец псевдонима -----16.
Выход: CF=0 — успешное выполнение функции: АХ = дескриптор файла, СХ = состояние: 1 — файл открыт; 2 — файл создан и открыт; 2 — файл открыт без сохранения содержимого существующего файла; CF=1: AX = код ошибки.
После того как файл открыт или создан функцией 716ch, с ним можно работать, используя старые функции чтения-записи и позиционирования. Следующий фрагмент программы показывает вариант применения функции 716Ch.
Закрытие файла производится функцией 3Eh, которая использовалась для файловых функций MS DOS с короткими именами.

Удаление файла

Удаление файлов, имеющих длинные имена, производится функцией 7141h прерывания 21п. Имя файла может быть задано с использованием символов шаблона * и ?, при этом в результате работы функции будут удалены все файлы, чье имя удовлетворяет заданному шаблону.

Получение и изменение атрибутов файла

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

Вход: АХ = 5706h; ВХ - дескриптор файла. ; . М
Выход: CF = 0 — успешное выполнение функции: СХ = биты установлены следующим образом: 0..4 - секунды, деленные на 2; 5..10 = минуты 0..59; 11..15 -часы; DX - биты установлены следующим образом: 0..4 = день месяца в диапазоне 1..31; 5..8 = месяц в диапазоне 1..12; 9..15 = число лет начиная с 1980 года; SI - двоичное значение количества 10-миллисекундных интервалов, добавляемых ко времени MS DOS в диапазоне 0..199; CF = 1: АХ = код ошибки.
Данная функция реализована в полном объеме.

Установить дату последней модификации файла

Вход: АХ = 5705И; ВХ = дескриптор файла; СХ = 0000h; DX - биты установлены следующим образом: 0..4 - день месяца в диапазоне 1..31; 5..8 = месяц в диапазоне 1..12; 9..15- число лет, начиная с 1980 года.
Выход: CF = 0 — успешное выполнение функции; CF = 1: АХ код ошибки.

Аналогично функции 5704h данная функция позволяет установить только дату создания файла.

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

Вход: АХ = 5707h; ВХ = дескриптор файла; СХ - биты установлены следующим образом: 0..4 - секунды, деленные на 2; 5..10 = минуты 0..59; 11..15 - часы; DX " биты установлены следующим образом: 0..4 = день месяца в диапазоне 1..31; 5..8 = месяц в диапазоне 1..12; 9..15 = число лет начиная с
1980 года;
SI - двоичное значение количества 10-миллисекундных интервалов, добавляемых к времени MS DOS в диапазоне 0..199.
Выход: CF = 0 — успешное выполнение функции; CF = 1: АХ - код ошибки.

Данная функция реализована в полном объеме.
Кроме дополнительных функций для работы с различными временными характеристиками файла Windows-версия MS DOS содержит две функции для преобразования форматов времени. Дело в том, что Windows работает со временем в 64 разрядном формате. При этом точкой отсчета является 00 часов 00 минут 1 января 1601 года. Значение времени содержит число 100-наносекундных интервалов, прошедших с этой даты. По расчетам разработчиков этого значения должно хватить на 400 лет. Для того чтобы манипулировать этим 64-разрядным «средневековьем» с целью представления его в виде, воспринимаемом человеком (DOS-время), введена функция 71a7h.
Вход: АХ = 71a7h; BL = 0 — преобразовать 64-разрядное время в DOS-время; DS:SI = указатель на экземпляр структуры FILETIME, содержащей 64-битное значение времени.
Выход: CF = 0 — успешное выполнение функции, при этом регистры устанавливаются следующим образом: ВН = число 10-миллисекундных интервалов, добавляемых к времени MS DOS (значение в диапазоне 0..199); СХ - время в упакованном формате со значением бит: 0..4 — секунды, деленные на 2; 5..10 — минуты в диапазоне 0..59; 0..4 — часы в диапазоне 0..23; DX = дата в упакованном формате со значением бит: 0..4 — день месяца в диапазоне 1.31; 5..8 — месяц в диапазоне 1..12; 9..15 — число лет начиная с 1980 года (для получения истинного значения прибавьте 1980); CF = 1: АХ - код ошибки. (Структура filetime описывается в программе следующим образом:

FILETIME struc
DwLowOateTime dd ? :младшие 32 бита значения времени
DwHighDateTime dd ? :старшие 32 бита значения времени
FILETIME ends

Вход: АХ = 71a7h; BL - 1 — преобразовать DOS-время в 64-разрядное время; ВН = число 10-миллисекундных интервалов, добавляемых ко времени MS DOS (значение в диапазоне 0..199); СХ = время в упакованном формате со значением бит: 0..4 — секунды, деленные на 2; 5..10 — минуты в диапазоне 0..59; 0..4 — часы в диапазоне 0..23; DX - дата в упакованном формате со значением бит: 0..4 — день месяца в диапазоне 1..31; 5..8 — месяц в диа пазоне 1..12; 9..15 — число лет начиная с 1980 года (для получения истинного значения прибавьте 1980) DS:SI = указатель на экземпляр структуры FILETIME, в которой вернется 64-битное значение времени.
Выход: CF=O — успешное выполнение функции, при этом в области памяти, адресуемой DS:SI, возвращается 64-битное значение времени; CF=1: AX - код ошибки.

Получить атрибуты файла

Вход: АХ ¦ 7143h; BX = действие:
0 -- получить атрибуты, на выходе СХ = атрибуты файла: 0000h — файл доступен по записи и чтению; 0001h — файл доступен по чтению; 0002h — скрытый файл; 0004И — системный файл; 0008h — метка тома; 00lOh — каталог; 0020h — архивный файл;
2 — получить размер сжатого файла — на выходе DX:AX = размер сжатого файла в байтах на диске;
4 — получить дату и время последней записи — на выходе; СХ = время в формате: 0..4 = секунды, деленные на 2; 5.. 10 = минуты (0..59); 11..15 = часы(0..23);
DI дата в формате: 0..4 = день месяца (1..31); 5..8 = месяц (1..12); 9..15 = число лет с 1980 года;
6 — получить дату последнего доступа — на выходе: DI = дата в формате (см. ВХ = 4);
8 — получить дату и время создания — на выходе СХ - время в формате, DI - дата в формате (см. ВХ « 4), SI = двоичное значение количества 10-миллисекундных интервалов, добавляемых ко времени MS DOS в диапазоне 0..199;
DS:DX — ASCIZ-строка с именем (путем) файла.
Выход: CF = 0 в случае успеха, информация в регистрах определяется значением ВХ на входе (см. выше):
АХ = код ошибки (CF = 1): 1 — неверное значение в AL; 2 — файл не найден; 3 — несуществующий путь; 5 — доступ запрещен.

Установить атрибуты файла

Вход: АХ = 7143h; ВХ = действие:
1 — установить атрибуты на входе СХ = атрибуты файла: 0000h — файл доступен по записи и чтению; 0001h — файл доступен по чтению; 0002h — скрытый файл; 0004h — системный файл; 0020h — архивный файл; 3 — установить дату и время последней записи: СХ = время в формате: 0..4 " секунды, деленные на 2; 5..10 = минуты (0..59); П..15 - часы (0..23); 01 = дата в формате: 0..4 = день месяца (1..31); 5..8 = месяц (Т.. 12); 9..15 =" число лет с 1980 года;
5 — установить дату последнего доступа (см. ВХ = 3); 7 — установить дату и время создания: СХ = время в формате (см. ВХ - 3), DI = дата в формате (см. ВХ = 3), SI = двоичное значение количества 10-миллисекундных интервалов, добавляемых ко времени MS DOS в диапазоне 0..199; DS:DX — ASCIZ-строка с именем (путем) файла.
Выход: CF = о — СХ = слово атрибутов файла; CF=1 — АХ=код ошибки: 1 — неверное значение в AL; 2 — файл не найден; 3 — несуществующий путь; 5 — до-ступ запрещен.

Переименовать файл

Вход: АН = 7156h; DS:DX — ASCIZ-имя существующего файла; ES:O1
имя нового файла; CL - маска атрибутов. Выход: CF = 0 — при успешном переименовании; CF = 1 — АХ = код ошибки: 2 —
файл не найден; 3 — несуществующий путь; 5 — доступ запрещен;
устройства для старого и нового файлов не совпадают.

Работа с дисками, каталогами и организация поиска файлов

Получить информацию о томе

Вход: АН = 71A0h; DS:DX — адрес ASCIZ-строки с именем корневого каталога диска, о котором необходимо получить информацию (С:\); ES:DI — адрес буфера, в который будет помещена ASCIZ-строка с именем файловой системы; СХ = размер буфера, в который будет помещена ASCIZ-строка с именем файловой системы.
Выход: CF = 0 — успешное выполнение, при этом в буфер по адресу в ES-.DI помешается ASCIZ-строка с именем файловой системы и устанавливаются следующие регистры: ВХ =* флаги файловой системы (комбинация значений: 0001 — при поиске учитывается регистр букв в именах файлов; 0002 — файловая система сохраняет регистр букв в элементах каталога; 0004 — использование символов Unicode в именах каталогов и файлов; 4000 — файловая система поддерживает длинные имена файлов и функции для работы с ними; 8000 — том сжат); СХ = максимально допустимая длина имени файла на данном томе без последнего нулевого символа (до 255); DX = максимально допустимая длина пути для данного тома, включая последний нулевой символ (до 260); ;1. _ .,

Создание каталога

Вход: АН = 7139h; DS:DX — адрес строки с ASCIZ-именем существующего файла. Выход: CF = 0 — при успешном переименовании; CF = 1 — АХ = код ошибки: 3 — несуществующий путь; 5 — доступ запрещен.
Удаление каталога
Удаляемый каталог должен быть пуст.
Вход: АН = 713Ah; DS:DX — ASCIZ-строка пути к удаляемому каталогу. Выход: CF = 0 — АХ = не определен; CF = 1 — АХ = код ошибки: 3 — несуществующий путь; 5 — доступ запрещен; 10h — попытка удаления текущего каталога.

Изменить текущий каталог

Понятие текущего каталога аналогично тому, что приводилось выше при рассмотрении функций для работы с файлами, имеющими короткие имена.
АН = 713Bh; DS:DX — указатель на буфер, содержащий полный путь от кор. невого каталога в виде ASCIZ-строки и в качестве последнего элемента включающий имя нового текущего каталога (естественно, что допустимы длинные имена с ограничениями по максимальной длине (см. функцию 71a0h)). Выход: CF = 0 — АХ - не определен; CF=0 — АХ = код ошибки: 03h — путь не найден

Получение текущего каталога

Вход: АН = 7147h; DL - номер устройства (00h = текущее (заданное по умолчанию), 01h = А: И т. д.); DS:SI — указатель на буфер для записи полного пути от корневого к текущему каталогу (длина буфера должна быть не менее длины, возвращаемой в регистре DX функцией 71a0h). Выход: CF = 0 — успешное выполнение функции, в результате чего полный путь от корневого каталога в виде ASCIZ-строки без имени диска и символа \ записывается в буфер, адрес которого указан в DS:SI; АХ - код ошибки (CF = 1): OFh — недопустимый дисковод. Среди новых функций, работающих в том числе с длинными именами файлов, существует функция 7160h, позволяющая получить полные пути для указанных файлов или относительных путей: получить полный путь (сх = 0), получить полный путь с краткими именами (сх = 1), получить полный путь с длинными именами (сх = 2).

Получить полный путь

Вход: АН = 7160h; CL = 0; СН — содержимое результата (СН = 80 — получить имя диска; СН = 0 — получить полный путь); DS:SI — адрес ASCIIZ-строки с именем файла или каталога, для которых необходимо получить полный путь. Допускаются оба типа имен — длинные и короткие; ES:DI — адрес строки, в которую необходимо записать полный путь. Размер буфера должен быть достаточным для размещения пути максимальной длины (функция 71a0h).
Выход: CF = 0 — успешное выполнение функции, в результате чего полный путь от корневого каталога в виде ASCIZ-строки записывается в буфер, адрес которого указан в ES:DI; CF = 1 — АХ = код ошибки.

;prg07_24.asm - программа демонстрации применения функции 7160h (CL=0) прерывания 21h для получения полного пути.
.data
filename db 'my_file with long name.txt'.O
point_fname dd filename
PathFull db 260 dup (0)
point Path dd PalhFull
.code
Ids si .pointfname:формируем указатель на имя файла
les di,point_Path Нормируем указатель на буфер для полного пути

mcvax.7l60h ;номер функции DOS
movch,80h :CH=80h - получить имя : диска; СН=0 - получить полный путь
movCL.O ;получить полный путь
int 21h
jc exit

Данная функция работает очень принмитивно — при указании имени файла или относительного пути (с символами *«.» и «..») она не проверяет его существование, а лишь добавляет к нему имя тсекущего диска и каталога. Поэтому при использовании этой функции требуютсяя другие средства, позволяющие контролировать реальное наличие файла или шути на диске.

Получить полный путь с краткими именами (в формате 8.3)

Вход: АН = 7160h; CL = 1; СН — содержимоое результата (СН = 80 — получить имя диска; СН = 0 — получить полный путь); DS:SI — адрес ASCIIZ-строки с именем файла или каталога, для ксоторых необходимо получить путь в короткой форме. Допускаются оба . типа имен — длинные и короткие: ES:DI — адрес строки, в которую необходцимо записать полный путь. Размер буфера должен быть достаточным длят размещения пути максимальной длины
(функция 71a0h).
Выход: CF = 0 — успешное выполнение функции, в результате чего полный путь от корневого каталога в виде /ASCIZ-строки записывается в буфер, адрес которого указан в ES: DI; CF ' = 1 — АХ = код ошибки.

:prg07_25.asm - программа демонстрации применения функции 7160h (CL=1) прерывания 21h для получения полного путии с краткими именами (в формате 8.3)
filename db 'my_file with lorg name.:.txt' .0
point_fname dd filename
PathFUll db 260 аир (О)
pointjath dd PathFull
* Ids si .pointjfname формирует указатель на имя файла lesdi.point_Path сформируем учазатель на буфер для полного пути movax.7160h :номер функции DOS
movch.80h ;CH»80h - попучить « имя диска; СН=0 - получить полный путь
movCL.l :получить пспный пууть с краткими именами

На выходе функция формирует стрроку, содержащую полный путь, причем все I Длинные компоненты этого пути замееняются их краткими псевдонимами, удовлетворяющими схеме 8.3. Данный вариант функции (при CL = 1) в отличие от ее Предыдущего варианта, производит прроверку наличия файла или пути.

Получить полный путь с длинными именами

Вход: АН = 7160h; CL = 2; СН — содержимое результата (СН = 80 — получить имя лиска; СН = 0 — получить полный путь); DS:SI — адрес ASCIIZ-строки с именем файла или каталога, для которых необходимо получить путь в длинной форме. Допускаются оба типа имен — длинные и короткие; ES:DI — адрес строки, в которую необходимо записать полный путь. Размер буфера должен быть достаточным для размещения пути максимальной длины (функция 71a0h).
Выход: CF = 0 — успешное выполнение функции, в результате чего полный путь от корневого каталога в виде ASCIZ-строки записывается в буфер, адрес которого указан в ES:DI; CF = 1 — АХ = код ошибки.

Получить информацию о файле по описателю

Вход: АН = 71A6h; флаг cf = 1; ВХ = дескриптор файла; DS:DX — адрес структуры
BYHANDLEFILEINFORMATION.
Выход: CF = 0 — успешное выполнение функции; CF = 1 — АХ = код ошибки. Формат структуры BYHANDLEFILEINFORMATION приведен ниже.

Y_HANDLE_FILE_INFORMATION StuiC
"DwFiieAttributes dd ?
FtCreationTimedd 2 dup(?)
FtLastAccessTime dd 2 dup(?)
FtLastWriteTime dd 2 dup(?)
DwVolumeSeria 1 Number dd ?
NFileSizeHigh dd ?
NfileSizeLow dd ?
NnunberOfLinksdd ?
NFilelndexHighdd ?
NFilelndexLow dd ?
BY_HANDLE_FILE_INFORMATION ends

Поля этой структуры описаны в следующей таблице.

Поле
Описание
dwFileAttributes
Атрибуты файла. Этот элемент может быть комбинацией следующих значений: FI LE_ATTR IBUTENORMAL (00000000H) - файл доступен по чтению и записи; этот атрибут нельзя комбинировать с другими; FILE_ATTRIBUTE_READONLY (00000001Н) - файл только для чтения; FILE_ATTRIBUTE_HIDDEN (00000002H) - скрытый файл; FILE_ATTRIBUTE_SYSTEM (00000004H) - системный файл; FI LE_ATTR IBUTEDI RECTORY (00000010H) - каталог; FILE ATTRIBUTE ARCHIVE (00000020H) - архивный файл
CreationTime
Время создания файла в 64-разрядном формате
ftLastAccessTime
Время последнего доступа к файлу в 64-разрядном формате
ftLastWriteTime
Время последней записи в файл в 64-разрядном формате
dwVolumeSeri alNumber
Серийный помер тома, на котором находится файл
NFileSizeHigh
Старшее слово значения, определяющего размер файла
NFiieSizeLow
Младшее слово значения, определяющего размер файла
NNumberOfLinks
Число связей с данным файлом. В файловых системах FAT и HPFS этот элемент всегда равен 1. В файловой системе NTFS число связей может превышать 1
NFilelndexHigh
Старшее слово уникального дескриптора, связанного с файлом
NFilelndexLow
Младшее слово уникального дескриптора, связанного с файлом. Файл однозначно определяется дескриптором
и серийным номером тома

:prg07_26.asm - программа демонстрации применения функции 71A6h прерывания 21п :для получения информации о файле по описателю.
BY_HANDLE_FILE_INFORMATION struc "DwFileAttributes dd ? FtCreationTime dd 2 dup(?) FtLastAccessTime dd 2 dup(?) FtLastWriteTime dd 2 dup(?) DwVolumeSerial Number dd ? NFileSizeHigh dd ? NfileSizeLow dd ? NnumberOfLinks dd ? NFilelndexHigh dd ? NFilelndexLow dd ? BY_HANDLE_F1LE_INFORMATION ends
.data
file_info_ BY_HANDLE_FILE_INFORMATION <>
poir,t_find_ dd file_info_
filename db 'my_file with long name.txt'.O
point_fname dd filename
handle dw 0
:.........
.code

.файл, о котором будем получать информацию

mov bx.0100h+0400h;не использовать буферизацию
содержимое 01 в псевдоним
movdx.l юткрыть файл, если он существует, иначе вернуть ошибку Ids si .point_fname-.формируем указатель на имя файла
mov di.7 repeat:mov ax.716ch
xor ex.ex
int21h
jnc ml
mov dx.10h
jmp repeat ml: mov handle.ax
действия при успешном открытии файла:
добавить в конец псевдонима символ 7 ; номер функции DOS атрибуты файла - обычный файл - доступ для чтения-записи
открываем файл
.если файл существовал, то переход
;создать файл
:переход - повторим открытие файла
:сохраним дескриптор файла
.получаем информацию о файле mov bx. handle
stc ;это обязательно
Idsdx.point_find_;формируем указатель на структуру BY_HANDLE_FILE_INFORMATION

Создать псевдоним

Функция 71A8h предназначена для генерации короткого (в формате 8.3) имени для заданного файла с длинным именем.
Вход: АН = 71A8h; DS:SI — адрес строки (с нулевым символом в конце), содержащей длинное имя нужного файла без указания пути; ES:DI — адрес буфера, в котором возвращается псевдоним; DH — формат псевдонима (0—11 -символьное имя элемента каталога; 1 — имя файла в формате 8.3); DL — набор символов для длинного имени и псевдонима. Это значение — упакованная величина в формате: биты 0..3 — набор символов в prpprg0дном имени файла (0 — Windows ANSI; I — OEM; 2 — Unicode); биты 4..7 — набор символов в создаваемом коротком имени (0 — Windows ANSI; I - OEM; 2 - Unicode).
Выход: CF ¦ 0 — успешное выполнение функции; CF = 1 — АХ = код ошибки.

:prgO7_27.asm - программа демонстрации применения функции 71A8h прерывания 21h ;для создания псевдонима.
.'data'"
fi1enamejong db 'my_file with long name.txt'.0
point_fname_long dd fi1enamejong
filename_short db 11 dup (20h)
point_fname_short dd filename short
handle dw 0
:.........
.code
mov bx.0100h+0400h;He использовать буферизацию + содержимое DI в псевдоним
movdx.l :открыть файл, если он существует, иначе вернуть ошибку
Ids si,point fname_long ;формируем указатель на имя файла
movdi.7 :добавить в конец псевдонима символ 7 repeat:mov ax,716ch ;номер функции DOS
хогсх.сх атрибуты файла - обычный файл - доступ для чтения-записи
int 21h открываем файл
jnc ml :если файл существовал, то переход
movdx.lOh :создать файл
jmp repeat ;переход - повторим открытие файла ml: mov handle.ax :сохранин дескриптор файла создадим псевдоним
Ids si.point_fname_long
les di,point_fname_short
mov dh. 1:prg07_27.asm - программа демонстрации применения функции 71A8h прерывания 21h ;для создания псевдонима.
mov dl. 0
mov ax,7la8h int 21h действия при успешном открытии файла

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

Поиск файлов и каталогов

В Windows-версии MS DOS процесс поиска несколько отличается от рассмотре-ного выше. Для этого используются три функции и структура WIN32_FIND_DATA в памяти, в которой возвращается информация о файле. Для запуска процесса поиска вызывается функция 714eh — найти первый файл.
Вход: АН = 714eh; CL — атрибуты искомых файлов (0000h — файл доступен по записи и чтению; 0001h — файл доступен по чтению; 0002h — скрытый файл; 0004И — системный файл; 0008И — метка тома; 00lOh — каталог; 0020h — архивный файл); СН — дополнительные атрибуты искомых файлов (0000h — файл доступен по записи и чтению; 0001h — файл доступен по чтению; 0002h — скрытый файл; 0004h — системный файл; 0008h — метка тома; 00lOh — каталог; 0020h — архивный файл); DS:DX — адрес ASCIIZ-строки с именем искомого файла или каталога. Допускаются оба типа имен — длинные и короткие. В именах допустимы символы шаблона * и ?; ES-.DI — адрес структуры WI N32_F I ND_DATA, в которой будет возвращена ин-_ формация о файле; SI — формат, в котором возвращается дата и время
(О — дата и время возвращаются в 64-разрядном формате; 1 — дата и время возвращаются в формате MS DOS).
Выход: CF = 0 — успешное выполнение функции, в результате в регистрах АХ и СХ возвращается следующая информация: АХ = дескриптор, использующийся далее для процесса поиска; СХ = возможные значения: 0000 — все символы структуры WIN32_FIND_DATA, составляющие основное и альтернативное имя файла, успешно преобразованы из Unicode; 0001 — основное имя, возвращенное в структуре WIN32_FIND_DATA, содержит знаки подчеркивания на месте символов, не преобразованных из Unicode; 0002 — альтернативное имя, возвращенное в структуре WIN32_FIND_DATA, содержит знаки подчеркивания на месте символов, не преобразованных из Unicode; CF = 1 — АХ = код ошибки при неудачном выполнении функции. Вызов функции 714eh приводит к заполнению полей структуры WIN32_FIND_ DATA, после чего можно проанализировать ее поля. Основной интерес представляют поля основного (CfileName) и альтернативного (CaHernateFiieName) имен. Их можно анализировать на предмет удовлетворения условиям поиска. Если необходимо продолжить поиск, вызывается функция 714fh — найти следующий файл. Если же поиск считается удачным либо его необходимо прекратить, то вызывается функция 71alh — прекратить поиск. Ниже приведены порядок вызова функций 714fh и 71alh и формат структуры WIN32_FIND_DATA.
Вход: АН = 714fh; ВХ = дескриптор, полученный функцией 714eh; ES:DI — адрес структуры WIN32FINDDATA, в которой будет возвращена информация о файле; SI — формат, в котором возвращается дата и время (0 — дата и время возвращаются в 64-разрядном формате; 1 — дата и время возвращаются в формате MS DOS).
Выход: CF = 0 — успешное выполнение функции, в результате в регистрах АХ и СХ возвращается следующая информация: СХ = возможные значения: 0000 — все символы структуры WIN32FINDDATA, составляющие основное и альтернативное имя файла, успешно преобразованы из Unicode; 0001 — основное имя, возвращенное в структуре WIN32FINDDATA, содержит знаки подчеркивания на месте символов, не преобразованных из Unicode; 0002 — альтернативное имя, возвращенное в структуре WIN32FINDDATA, содержит знаки подчеркивания на месте символов, не преобразованных из Unicode; CF = 1 — АХ = код ошибки при неудачном выполнении функции. Функция 714eh в отличие от аналогичных функций «старой» MS DOS использует не область DTA, а некоторый блок в памяти. Этот блок важно своевременно освобождать, для этого и предназначена функция 71alh.
Вход: АН = 71Alh; ВХ = дескриптор, полученный функцией 714eh. Выход: CF = 0 — успешное выполнение функции; CF = 1 — АХ = код ошибки при неудачном выполнении функции.

Ниже приведена структура WI N32_FIND_DATA, в которую в процессе поиска записывается информация о файлах.

WIN32_FIND_DATA struc
DwFlleAttributes dd ?
FtCreationTime dd 2 dup(?)
FtLastAccessTime dd 2 dup(?)
FtLastWriteTime dd 2 dup(?)
NFileSizeHigh dd ? .размер файла в байтах (старшее слово)
NFiieSizeLow dd ? ;размер файла в байтах (младшее слово)
DwReservedO dd 0 ;резерв
OwReservedl dd 0 ;резерв
CFileName db MAX_PATH dup(?)
CAlternateFileName db 14 dup(?) WIN32_FIND_DATA ends

Поля этой структуры описаны в следующей таблице.

dwFileAttributes
Атрибуты найденного файла (см. описание аналогичного элемента структуры BY HANDLE FILE INFORMATION)
ftCreationTime
Время создания файла в одном из двух форматов: MS DOS или в 64-разрядном, в зависимости от параметров, указанных при вызове функций 714eh (найти первый файл) и 714fh (найти следующий файл)
ftLastAccessTime
Время последнего доступа к файлу в одном из двух форматов: MS DOS или в 64-разрядном, в зависимости от параметров, указанных при вызове функций 714eh и 714fh
fUastWrUeTime
MS DOS или в 64-разрядном, в зависимости от параметров, указанных при вызове функций 714eh и 714fh
CFileName
ASCIIZ-строка, содержащая имя файла. Размер строки должен быть не менее 256 символов
cAlternateFileName
ASCIIZ-строка, содержащая альтернативное имя файла в стандартном формате 8.3. Если элемент cFileName содержит имя в формате 8.3 или файловая система не поддерживает альтернативные имена в формате 8.3, то элемент cAlternateFileName равен нулю

Приведем пример поиска файла по шаблону. Для этого предварительно создадим несколько файлов в соответствии с шаблоном file*.*. Среди этих файлов должен быть файл file_O5.txt. В отладчике проследим за тем, как изменяется
содержимое области памяти, отведенное для экземпляра структуры WIN32_FIND_ DATA. Выход из программы — при обнаружении файла file_5.txt

:prgO7_28.asm - программа демонстрации поиска файла по шаблону.

WIN32_FIND_DATA -uc
DwFlleAttributes dd ?
FtCreationTime dd 2 dup(?)
FtLastAccessTime dd 2 dup(?)
FtLastWriteTime dd 2 dup(?)
NFileSizeHigh dd ? .размер файла в байтах (старшее слово)
NFileSizeLow dd ? .размер файла в байтах (младшее слово)
DwReservedO dd 0 ;резерв
DwReservedl dd 0 :резерв
CFileName db 260 dup(?)
CAlternateFileName db 14 dup(?)
WIN32_FIND_DATA ends
.data
find_ WIN32_FIND_DATA <>
point_find_ dd find_
f_name_pattern db 'file_*.*'.O
point_f_name_pattern dd f_name_pattern
filename db 'file_05.txt',0 :искомый файл
1e*n_fi1ename=$-fi1ename
handle dw 0
movCL.O ;атрибуты искомого файла
movch.O ;дополнителные атрибуты для поиска
Ids dx,point_f_name_pattern ;формируем указатель на строку с шаблоном
les di.point_find_;формируем указатель на экземпляр структуры WIN32_FIND_DATA
movax.714eh :номер функции DOS
int 21h
jc exit
;в ах был возвращен дескриптор - если нужно, то его необходимо сохранить:

mov handle.ax
:проверяем, тот ли это файл: ml: mov ex.1en_fi1ename
lea di.find_.CfileName
lea si .filename repe empsb
jz exit ;продолжаем поиск - в Ьх дескриптор, полученный от 714eh:
mov bx.handle
les di.point_find_ :формируем указатель на экземпляр структуры WIN32_FIND_DATA
mov ax.714fh :номер функции DOS
хог si.si :формат даты
int 21h
jnc ml exit: завершить поиск
mov ax.71alh
mov bx.handle
int 21h

В отладчике хорошо видно, что выход из данной программы происходит в двух случаях:

  • когда файл найден, выход из программы производится в результате сравнения командой empsb (флаг ZF устанавливается в 1);
  • когда файлов, удовлетворяющих шаблону, нет, функция поиска 714еп и 714fh завершается неудачей (флаг CF устанавливается в 1).

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