Вывести время создания файла ассемблер
Файл - важнейшая образующая практически любой программы. С появлением скоростных дисков больших объемов значение файлов сильно возросло. Использование API-функций управления файлами может сделать вашу программу более эффективной и производительной. Большинство программ данной главы являются консольными, потому что консольная программа как никакая другая подходит для демонстрации файловой обработки.
32-битная FAT. Характеристики файлов
Давая описание характеристикам файлов, я буду основываться на характеристиках, которыми манипулируют функции API. О типах и структуре файловых систем речь пойдет далее.
Атрибут файла. Размер - DWORD.
FILE_ATTRIBUTE_READONLY equ 1h
Атрибут - "только чтение". Приложения могут лишь читать данный файл. Соответственно, попытка открыть файл для записи вызовет ошибку.
FILE_ATTRIBUTE_HIDDEN equ 2h
Атрибут - "скрытый файл". "Невиден" при обычном просмотре каталога (см. ниже, поиск файлов).
FILE_ATTRIBUTE_SYSTEM equ 4h
Атрибут - "системный файл". Говорит о том, что данный файл принадлежит операционной системе.
FILE_ATTRIBUTE_DIRECTORY equ 10h
Атрибут - "директорий", С файлами с таким атрибутом операционная система обращается особым образом, считая его каталогом, т.е. считая его списком файлов, состоящим из записей по 32 байта.
FILE_ATTRIBUTE_ARCHIVE equ 20h
Со времен MS DOS таким атрибутом отмечались файлы, над которыми не произведена операция BACKUP или XCOPY. Для целей программирования данный атрибут эквивалентен нулевому значению атрибута.
FILE_ATTRIBUTE_NORMAL equ 80h
Данный атрибут означает, что у файла не установлены другие атрибуты.
FILE_ATTRIBUTE_TEMPORARY equ 100h
Атрибут означает, что данный файл предназначен для временного хранения. После закрытия файла система должна его удалить.
FILE_ATTRIBUTE_COMPRESSED equ 800h
Для файла это означает, что он сжат системой; для директория - что вновь создаваемый файл по умолчанию должен быть сжат.
FILE_ATTRIBUTE_OFFLINE equ 1000h
Данный атрибут означает, что данные файла не доступны в данный момент.
Смену атрибута можно осуществить функцией SetFileAttributes, получить значение атрибута функцией GetFileAttributes. Следует заметить, что если операционная система не накладывает никаких ограничений на возможности изменения атрибутов файлов, то фактически обесценивается смысл самих атрибутов - всегда можно снять атрибут "только чтение" и делать с файлом, что заблагорассудится.
Файл имеет три временные характеристики: время создания, время последней модификации, время последнего доступа. Время отсчитывается в наносекундных интервалах начиная с 12.00 по полудни 1 января 1600 года и хранится в двух 32-битных величинах. Надо сказать, что время хранится в так называемых универсальных координатах и должно еще быть преобразовано в локальное время (функция FileTimeToLocalFileTime). Получить значение всех трех времен можно функцией GetFileTime.
Длина файла в байтах хранится обычно в двух 32-битных величинах либо в одной 64-битной величине. Если 32-битные величины обозначить как l1 (младшая часть) и l2 (старшая часть), то 64-битная величина выразится формулой l2*0FFFFH+l1. Paзмер файла можно получить функцией GetFileSize.
Кроме указанных характеристик, файл, разумеется, имеет имя. При этом мы будем различать длинное и короткое имя. Точно также будем различать полный путь (со всеми длинными именами) и укороченный путь (все длинные имена заменены укороченными). Необходимость использования укороченного имени и пути диктуется, прежде всего, тем, что некоторые программы получают путь или имя на стандартный вход и трактуют пробелы как разделители для параметров. Преобразование длинного имени в короткое можно осуществить функцией GetShortPathName, которая работает и для имени, и для пути. Обратное преобразование можно осуществить функиией GetFullPathName.
В данной книге мы не рассматриваем вопроса о прямом доступе к диску. Но вопрос о структуре записей каталога может у читателя все же возникнуть. Это и понятно, ведь с переходом к FAT32 33 , во-первых, появилась возможность хранения файлов с длинным именем, во-вторых, у файла, кроме времени и даты модификации, появились еще время и дата создания и доступа. Где же все это хранится?
Для того чтобы ответить на поставленный вопрос, вспомним, что каталог в файловых системах FAT 34 делится на записи длиной 32 байта. Ниже приводится структура записи для FAT32. Пустыми записями считаются записи, содержащие нулевые байты, либо начинающиеся с кода E5H (для удаленных записей). На файл с обычным именем (восемь байт на имя и 3-на расширение) отводится 32 байта. В байте со смещением +11 содержится атрибут файла. Если атрибут файла равен 0FH, то система считает, что здесь содержится длинное имя. Длинное имя кодируется в UNICODE и записывается в обратном порядке. За одной или несколькими записями с длинным именем должна следовать запись с обычным именем, содержащим знак "~" - тильда. Здесь содержится также остальная информация о файле. Как видите, алгоритм просмотра каталога с выявлением информации о файле весьма прост. Обратимся теперь к структуре записи каталога. В старой операционной системе MS DOS байты с 12 по 21 никак не использовались системой (см. [1]). Новой системе они пригодились. Ниже в таблице дана новая структура записи каталога.
Смещение | Размер | Содержимое |
---|---|---|
(+0) | 8 | Имя файла или каталога, выровненное на левую границу и дополненное пробелами. |
(+8) | 3 | Расширение имени файла, выровненное на левую границу и дополненное пробелами. |
(+11) | 1 | Атрибут файла. |
(+12) | 2 | Время доступа. |
(+14) | 2 | Время создания. |
(+16) | 2 | Дата создания. |
(+18) | 2 | Дата доступа. |
(+20) | 2 | Два старших байта номера первого кластера файла. |
(+22) | 2 | Время модификации файла. |
(+24) | 2 | Дата модификации файла. |
(+26) | 2 | Два младших байта номера первого кластера файла. |
(+28) | 4 | Размер файла в байтах. |
Как видите, все байты 32-байтной записи каталога теперь заняты. Лишний раз убеждаешься в первоначальной непродуманности файловой системы MS DOS, Это касается, в частности, длины файла. Как можно заметить, на длину файла отводится всего 4 байта. А как найти длину файла, если на нее требуется более 4 байт? Разумеется, в этом случае следует считать, что в каталоге хранятся младшие байты длины, а полную длину легко определить, обратившись к таблице размещения файлов. Но, согласитесь, что это уже явная недоработка. Странно также выглядит функция GetFileSize, которая возвращает четыре младших байта длины файла, старшие же байты возвращаются во втором параметре функции.
Иное дело в файловой системе NTFS, поддерживаемой Windows NT, изначально планируемой для работы с файлами больших размеров. Здесь для индексации кластеров используются 64-битные поля.
33 В начале Windows 95 работала с 16-битной FAT, но длинные имена уже поддерживала.
34 FAT (File Allocation Table) - один из элементов, на котором базируются файловые системы MS DOS и Windows 9х. По этой причине часто такие файловые системы называют FAT системами.
Поиск файлов. Для поиска файлов в Windows существуют две функции FindFirstFile и FindNextFile, очень похожие на аналогичные функции MS DOS и, как и там, работающие в паре. При успешном поиске первая функция возвращает некое число или идентификатор, который затем используется второй функцией для продолжения поиска.
Первым параметром функции FindFirstFile является указатель на строку для поиска файлов, второй параметр - указатель на структуру, которая получает информацию о найденных файлах. Функция FindNextFile первым своим параметром имеет идентификатор, полученный первой функцией, а вторым параметром - указатель на структуру. Эту структуру можно изучить по программе на Рис. 2.5.1.
Основным отличием этих функций от соответствующих функций MS DOS является то, что поиск ограничивается только маской поиска (*.*, *.ЕХЕ и т.п.). Если файл найден, то тогда по возвращаемой структуре, где содержится вся информация о нем, Вы уже можете решать, подходит файл или нет.
На Рис. 2.5.1 представлена программа, осуществляющая поиск файлов в указанном каталоге. Программа может иметь один или два параметра, или не иметь их вовсе. Если имеются два параметра, то первый параметр трактуется как каталог для поиска, причем программа учитывает, есть ли на конце косая черта или нет (допустимо c:, c:\, c:\windows\, c:\windows\system и т.п.). Второй параметр (в программе он третий, так как первым считается командная строка), если он есть, представляет собой маску поиска. Если его нет, то маска поиска берется в виде "*.*". Наконец, если параметров нет вообще, то поиск осуществляется в текущем каталоге по маске "*.*". Эту программу легко развить и сделать из нее полезную утилиту. Предоставляю это Вам, дорогой читатель. Ниже будет дан комментарий к означенной программе.
Программа на Рис. 2.5.1 довольно проста. Из нового здесь Вы обнаружите лишь то, как обращаться с функциями FindFirstFile и FindNextFile. Процедуры, которые используются для работы с параметрами командной строки, Вы уже встречали ранее. Вывод информации осуществляется в текущую консоль, с чем Вы тоже знакомы. Для получения дескриптора консоли используется функция GetStdHandle. Процедура WRITE позволила несколько упростить те участки программы, которые отвечают за вывод информации на экран. Ранее я обещал, что мы не обойдем вниманием строковые API-функции. В данной программе это обещание выполнено, и наряду со строковыми процедурами "собственного изготовления" используется строковая функция lstrcat, которая осуществляет сложение (конкатенацию) строк. По поводу параметра в командной строке замечу, что при наличии в имени каталога пробела Вам придется задавать имя в укороченном виде. Так, например, вместо C:\Program Files придется написать C:\Progra~1. Это должно быть понятно - пробелы отделяют параметры. Чтобы корректно решать проблему, необходимо ввести специальный разделитель для параметров, например "-" или "/".
Данная программа осуществляет поиск в указанном или текущем каталоге. Если бы программа была написана на языке высокого уровня, например Си, ее легко можно было бы видоизменить так, чтобы она осуществляла поиск по дереву каталогов. Собственно, небольшая модификация потребовалась бы только для процедуры FIND, которая должна была бы вызываться рекурсивно. Можно видеть, что эта легкость произрастает из наличия в языках высокого уровня такого элемента, как локальная переменная. Попробуем осуществить это, основываясь на материале Главы 1.2. А можно осуществить это без использования локальных переменных?
Программа на Рис. 2.5.2 немного похожа на предыдущую программу. Но поиск она осуществляет по дереву каталогов, начиная с заданного каталога. Эта программа - одна из самых сложных в книге, поэтому советую читателю скрупулезно в ней разобраться. Может быть, Вам удастся ее усовершенствовать. Я могу дать и направление, в котором возможно такое усовершенствование. Дело в том, что вторым параметром командной строки можно указать маску поиска. Если, например, указать маску "*.ЕХЕ", по этой маске будет осуществляться поиск не только файлов, но и каталогов. Этот недостаток и следовало бы устранить в первую очередь.
Поиск по дереву каталогов оптимально производить рекурсивным образом, однако для этого необходимы локальные переменные 35 . Смысл использования локальной переменной в рекурсивном алгоритме заключается в том, что часть данных должна сохраняться при возврате из процедуры.
В данной программе я, ради простоты, отказался от процедуры LENSTR и использую функцию API lstrlen. Кроме того, я усовершенствовал вывод так, чтобы на экран выводилось полное имя файла.
35 Конечно, можно обойтись и без них, храня данные, например, в глобальном массиве, обращаясь к той или иной области массива в зависимости от уровня рекурсии.
Разберем ту роль, которую играют локальные переменные в процедуре FIND. Переменная FINDH - здесь хранится дескриптор поиска в данном каталоге. Рекурсивный вызов процедуры FIND может происходить и тогда, когда поиск в текущем каталоге еще не закончился. Следовательно, после возврата из рекурсии поиск должен быть продолжен. Это можно обеспечить только старым значением дескриптора. Локальная переменная обеспечивает такую возможность, поскольку она разрушается только при переходе на более низкий уровень (к родительскому каталогу).
Аналогичную роль играет переменная DIRSS. В ней хранится текущий каталог. Это важно, т.к. с помощью этой переменной формируется полное имя файла.
Переменные DIRS и DIRV играют вспомогательную роль. В принципе, вместо них можно было бы использовать и глобальные переменные. Хотя, с точки зрения эффективности рекурсивных алгоритмов, чем меньше объем локальных переменных - тем лучше.
Еще один вопрос я хочу здесь обсудить. Для передачи имени каталога при вызове процедуры используется переменная DIRV. Почему же для этой цели нельзя использовать переменную DIRSS? Причина вот в чем. В процедуру передается не само значение, а указатель (адрес). Следовательно, любые изменения с параметром DIR приведет к аналогичным изменениям с переменной DIRSS на нижнем уровне рекурсии, В чем мы, разумеется, не заинтересованы.
Трансляция программы в TASM. Основная проблема при трансляции программ на Рис. 2.5.1 и Рис. 2.5.2 возникнет с локальными метками. Локальная метка - это метка, которая действует в пределах некоторого блока программы. В нашем случае таким блоком программы является процедура. Транслятор MASM автоматически различает метки, находящиеся в пределах процедуры, и считает их локальными. Поэтому не возникает проблемы, когда в разных процедурах встречаются метки с одинаковым именем. В TASM несколько иной подход: по умолчанию метки считаются глобальными. Локальные метки должны иметь перед именем обозначение "@@". Кроме того, в начале программы следует поставить директиву LOCALS. Сделав нужные метки локальными и поставив директиву LOCALS, Вы без труда, уже известными действиями, приведете программу к виду, приемлемому для TASM. Не забудьте о преобразовании wsprintfA -> _wsprintfA.
Приемы работы с двоичными файлами * . Манипуляция внешними файлами 36 основывается на нескольких функциях API, главной и наиболее сложной из которых является функция CreateFile.
В связи с ограниченностью объема книги, мы не можем подробно остановиться на свойствах функции CreateFile. Однако замечу, что с помощью этой функции можно не только создавать или открывать файл, но и такие объекты как каналы (PIPE), консоли, устройства жесткого диска (disk device), коммуникационный ресурс и др. Функция различает устройство по структуре имени. К примеру, "C:\config.sys" определяет файл, a "CONOUT$" - буфер вывода текущей консоли.
Сейчас я представлю две простые, но весьма важные программы (Рис. 2.5.3(1) и Рис. 2.5.3(2)). Обе программы выводят содержимое текстового файла 37 , имя которого указано в командной строке, в текущую консоль. В первом случае мы получаем дескриптор текущей консоли стандартным способом. Во втором случае - открываем консоль как файл и, соответственно, выводим туда информацию, как в файл. Хочу обратить Ваше внимание на роль буфера, в который читается содержимое файла. Поэкспериментируйте с размером буфера, взяв для пробы большой текстовый файл. Интересно, что в указанных программах никак не учитывается структура текстового файла. Для такого ввода-вывода это ни к чему. Ниже мы поговорим и о структуре текстового файла.
36 Имеется в виду файлами, расположенными на внешнем устройстве.
37 Точнее любого файла, но смысл выводить файл на консоль именно таким образом имеется только для текстового файла.
* Кажется, автор имеет ввиду текстовые файлы, а не бинарные, как это следует из дальнейшего повествования :)
Сейчас мы поговорим более подробно о структуре текстового файла. При работе с языками высокого уровня теряются определенные алгоритмические навыки. Это касается, в частности, и работы с текстовыми файлами. Ассемблер не дает расслабиться. Рассмотрим возможные варианты работы с текстовыми файлами.
Основным признаком текстового файла является то, что он состоит из строк разной длины. Строки отделены друг от друга разделителями. Чаще всего это последовательность двух кодов - 13 и 10. Возможны и другие варианты, например, некоторые DOS-редакторы отделяли строки только одним кодом 13.
Построчное чтение текстового файла можно осуществить четырьмя наиболее очевидными способами.
- Побайтное чтение из файла. Как только достигаем символа-разделителя, производим действие над считанной строкой и переходим к чтению следующей строки. При этом, разумеется, следует учесть, что на конце файла может не быть символа-разделителя. Если кто-то решит, что это слишком медленный способ, то замечу, что Windows неплохо кэширует диск, так что все выглядит не так уж плохо.
- Чтение в небольшой буфер, но так чтобы туда входила, по крайней мере, одна строка. Прочитав, находим в буфере конец строки и производим над ней какое-либо действие. Далее следует обратиться к файлу и передвинуть указатель так, чтобы он был в файле на начале следующей строки и, разумеется, повторить действие.
- Чтение в произвольный буфер. После чтения производится поиск всех строк, попавших в буфер, и совершение над ними действий. При этом с большой вероятностью должна возникнуть ситуация, когда одна строка неполностью умещается в буфере. Мы обязаны учесть такую возможность.
- Чтение в буфер, в который помещается весь файл. Это частный случай третьего подхода, и наиболее простой с точки зрения программирования.
В программе на Рис. 2.5.4 реализуется третий подход.
Программа на Рис. 2.5.4 демонстрирует один из возможных алгоритмов обработки текстового файла - построчное чтение текстового файла. Часть программы, занимающаяся чтением и анализом текстового файла, сосредоточена между метками L00 и CONT. Детально разберитесь в алгоритме и проникнитесь тем, что язык высокого уровня никогда не будет стимулировать написание таких алгоритмов, а значит, язык ассемблера делает нас интеллектуально богаче.
Получить дату и время последнего изменения web-страницы(файла)
Возможно ли средствами VBA получить с web-сервера дату и время последнего изменения.
Изменить дату и время создания/изменения/открытия файла без использования API
Вопрос собственно в названии. Почему без API - потому что на 32 битн. Оффисе работает с API, а на.
Как узнать были изменения в БД. Или дата время последнего изменения
Как узнать были изменения в БД. Или дата время последнего изменения. InnoDB INSERT UPDATE DELETE
Вывести и изменить дату создания или изменения файла
1 задача) На форму установлена метка Label1. Вывести в нее расстояние в мм. Между точкой нажатия.
Решение
Для вывода числа нужно его преобразовать в строку символов, и именно строку символов выводить на экран.
Примеры в закреплённой теме
Ввод и вывод чисел в различных системах счисления
Вывести на экран имя и дату создания (или изменения) самого свежего файла в заданной папки
Добрый день, есть небольшая проблема: Нужно вывести на экран имя и дату создания (или изменения).
Как в Командной строке получить дату последнего изменения файла или последнего доступа к нему?
суть такова, у меня есть список фаилов с полным адресом типо C:\sad\asds\dich.obj. требуется.
Изменить время последнего изменения
При обращении к файлу меняется 3 времени: доступа, модификации и изменения. Я могу изменить время.
Скрипт построчно выводит время последнего доступа, изменения
Помогите написать скрипт в bash, который Запрашивает путь к файлу и выводит построчно время.
Изменить время последнего изменения всех файлов jpg или jpeg в директории
Здравствуйте, господа программисты! Необходимо изменить время последнего изменения всех файлов jpg.
Создать программу, которая определяет время создания, модификацию в последнего доступа к файлу
Создать программу которая определяет время создания, модификацию в последнего доступа к файлу.
Аналогично группе функций MS DOS для работы с файловой системой файловая подсистема Win32 содержит ряд функций, с помощью которых можно определить характеристики конкретного файла.
Начальные значения атрибутов файла назначаются при создании файла. Впоследствии их можно изменить вызовом функции SetFiIeAttributes.
Параметры этой функции означают следующее:
- ipFileName – указатель на ASCIIZ-строку, содержащую имя файла;
- dwFileAttributes – двойное слово, определяющее, какие атрибуты файла могут быть установлены.
Планируя использование этой функции, необходимо иметь в виду, что не все возможные атрибуты файлов могут быть установлены с ее помощью. Перечислим те атрибуты, комбинацию которых можно задавать для изменения атрибутов файла, специфицированного параметром lpFileName:
При удачном завершении функция SetFileAttributes возвращает ненулевое значение в регистре ЕАХ. В случае неудачи функция возвращает в регистре ЕАХ значение NULL.
Для получения атрибутов файла используется функция GetFileAttributes.
Функция имеет один параметр lpFileName, который является указателем на ASCIIZ-строку, содержащую имя файла.
При удачном завершении функция GetFileAttributes возвращает значение в регистре ЕАХ, которое является комбинацией атрибутов файла, специфицированного параметром lpFileName. Выделить эти атрибуты можно, используя логические команды ассемблера или команды обработки битов. В случае неудачи функция возвращает в регистре ЕАХ значение NULL.
В приложениях очень часто требуется определить размер файла. Для этого Win32 содержит отдельную функцию:
Параметры функции означают следующее:
- hFile – дескриптор файла, размер которого требуется определить;
- lpFileSizeHigh – адрес области памяти, куда помещаются старшие 32 бита значения размера файла, младшие 32 бита возвращаются функцией в регистре ЕАХ.
При удачном завершении функция GetFileSize возвращает значение младших 32 бит размера файла в регистре ЕАХ. В случае неудачи функция возвращает в регистре ЕАХ значение Offffffffh.
Особого разговора заслуживают возможности получения информации о временных характеристиках файлов. По сравнению с аналогичными средствами MS DOS в Win32 этот вопрос проработан значительно глубже. Хотя если посмотреть номенклатуру и описание функций MS DOS для работы с длинными именами файлов, то видно, что у них уже есть общие идеи, реализованные рассматриваемыми ниже функциями Win32.
Как уже отмечалось выше, в Win32 с файлом связаны три значения времени: время создания, время последнего доступа и время последней модификации. Получить эти значения можно с помощью функции GetFileTime.
Перед вызовом данной функции, необходимо открыть файл, о значениях времени которого мы хотим получить информацию. Функции GetFileTime передается дескриптор этого файла и указатели на три экземпляра структуры FILETIME, в которые будут записаны время создания (IpCreationTime), время последнего доступа (lpLastAccessTime) и время последней записи (lpLastWriteTime).
Аналогично функции MS DOS 71a7h Win32 предоставляет две функции для взаимного преобразования DOS-времени файла в 64-битное представление времени:
DX – биты установлены следующим образом: 0..4 – день месяца в диапазоне 1..31; 5..8 = месяц в диапазоне 1..12; 9..15 – число лет, начиная с 1980 года.
Выход: CF = 0 – успешное выполнение функции; CF = 1: АХ код ошибки.
Аналогично функции 5704h данная функция позволяет установить только дату создания файла.
Установить дату и время создания или последней модификации файла
СХ – биты установлены следующим образом: 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.
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 описывается в программе следующим образом:
ВН = число 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-битное значение времени;
Файл – это совокупность данных, которая хранится на некотором внешнем носителе (флеш-накопитель, жесткий диск) и может загрузиться в ОЗУ по мере необходимости.
В настоящее время любая программа, будь то устаревшая или современная, использует файлы и работает с ними: файлы постоянно нужно открывать, закрывать, создавать, удалять, записывать, считывать. Программы чаще всего используют файлы в качестве хранилищ, в которые записываются произвольные данные: например, настройки программы, её данные. Они предоставляют возможность хранить данные даже после завершения работы программы, что может использоваться для передачи данных другим программам или различными запусками одной и той же программы. К тому же, данные, с которыми работает программа, могут быть очень большими и размера ОЗУ может не хватить, но файлы помогают решить эту проблему.
Инструменты для работы с файлами есть практически во всех языках программирования, и Ассемблер не исключение, пусть и инструментов меньше, и работать с ними намного сложнее.
Файлы в основном бывают 2 видов: текстовые и бинарные. В данной статье рассматривается работа именно с текстовыми файлами.
Операции по работе с файлами
Создание файла осуществляется с помощью функции 3с H прерывания 21 h . В регистр DX должен лежать путь до файла в формате строки, которая заканчивается нулевым байтом (например,“ C :\путь\файл”,0). Важно замечание: если файл уже существует, то он будет полностью очищен. В регистр CX можно указать атрибуты файла, но не обязательно. При возникновении ошибки создания Carry Flag примет значение единицы, а в AX будет код ошибки. Если ошибки нет, то в регистре AX будет храниться дескриптор (идентификатор) файла.
Открытие файла осуществляется с помощью функции 3 dH прерывания 21 h . Как и при создании файла, путь до открываемого файла должен лежать в DX . В AL записывается режим открытия файла(0 – только чтение, 1-только запись, 2 – чтение и запись). Закрытие файла, дескриптор которого находится в BX , производится функцией 3 eH .
С помощью функции 40 h осуществляется запись данных в файл. В BX должен храниться дескриптор файла, в DX - адрес буфера, содержащего записываемые данные, в CX - число записываемых байт. После записи в регистре AL будет храниться число считанных байт.
Функция 3 FH отвечает за чтение данных из файла. Данные на вход аналогичны тем, что подаются для записи: в DX - адрес буфера для чтения данных, в CX – число считываемых байт. В результате в AX будет храниться число прочитанных байт.
Пример программы
Для демонстрации функций предположим, что имеется программа, которая позволяет работать с личными электроприборами. Пользователь вводит устройства: название, мощность, количество, время работы. Данные хранятся в оперативной памяти, и после выключение программы все данные исчезнут. Чтобы избежать этой проблемы, нужно хранить введенные пользователем устройства в файле. Рассмотрим программную реализацию ранее описанных операций с файлами в контексте данной программы:
data segment ;сегмент данных
device struc ;структура прибор
device _ name db 30 dup ('$') ;название прибора
power dw ?;мощность прибора
num db ?;количество таких приборов
time db ?;время работы устройства в день
;необходимые данные для операции с файлами
filename db ' database . txt ',0;название файла
handle dw ?;дескриптор файла
buffer dw ?;буфер для записи
code segment;сегмент кода
mov ax , data ;инициализация сегмента данных
mov dl,filename; названиефайла
mov cx ,0;без атрибутов
mov [ handle ], ax ;в handle хранится дескриптор созданного файла
;запись данных в файл
mov si , buffer ;запишем в файл
mov lamp . power , si ;мощность лампы
mov dx , buffer ;записываемые данные
mov bx ,[ handle ]; в bx дескриптор файла,в которой будем записывать данные
mov cx ,2;размер данных(мощность имеет тип dw -2 байта)
mov bx ,[ handle ];дескриптор закрываемого файла
mov dl , filename ;название файла
mov cx ,0;атрибутов нет
mov al ,0;режим открытия - только чтение
mov [ handle ], ax
mov bx ,[ handle ];дескриптор считываемого файла
mov dx , buffer ;буффер для данных
mov cx ,4;количество считываемых байт
mov ax , buffer ;считали мощность лампы
mov lamp.power,ax;из файла
;снова закроем файл
mov ax ,4 c 00 h ;выход из программы
Организацию работы с файлами на Ассемблере непросто освоить, ведь она гораздо сложнее, чем на языках высокого уровня . Однако оно того стоит, ведь это дает множество бесценных возможностей. Без использования файлов практически любая программа не имеет практического смысла. Практически все, что написано на ассемблере – драйвера, вирусы, антивирусы, элементы операционной системы - используют файлы для самых различных целей. Таким образом, любой программист, использующий язык Ассемблер для написания программ, должен владеть навыком работы с файлами.
Читайте также: