mov disks, al ; занесение данных в переменную disks




Mov ah, 0Eh

mov dl, 02; диск C:

Int 21h

mov disks, al; занесение данных в переменную disks

Для того чтобы узнать номер текущего дисковода, программа может воспользоваться функцией 19h:

На входе: AH = 19h
На выходе: AL = Номер текущего дисковода (0 - А:, 1 - В:, и т.д.).

Функция 3Bh предназначена для установки текущего каталога:

На входе: AH = 3Bh
  DL = Номер дисковода (0 - текущий, 1 - А:, 2 - В:, и т.д.)
  DS:DX = Адрес буфера, содержащего путь каталога, который должен стать текущим.
На выходе: AX = Код ошибки, если CF установлен в 1.

Буфер пути может иметь максимальный размер 64 байта. Он должен содержать путь в формате ASCIIZ, т.е. строку, закрытую двоичным нулем, например: "path\dirname",0. Строка не должна содержать литеры, обозначающие диск. Если текущим должен стать корневой каталог, строка должна состоять только из одного двоичного нуля.

Для того чтобы узнать текущий каталог, можно воспользоваться функцией 47h:

На входе: AH = 47h
DL = Номер дисковода (0 - текущий, 1 - А:, 2 - В:, и т.д.)
DS:SI = Адрес буфера для записи пути текущего каталога.
На выходе: AX = Код ошибки, если флаг переноса CF установлен в 1.


Буфер должен иметь размер не менее 64 байтов, текущий каталог возвращается в формате ASCIIZ без литеры, обозначающей диск. Если текущим является корневой каталог, регистровая пара DS:SI будет указывать на нулевую строку (состоящую из одного двоичного нуля).

Функции MS-DOS могут помочь в получении информации, необходимой для организации доступа к диску на уровне секторов и кластеров. При этом вы будете избавлены от необходимости читать в память и анализированть содержимое загрузочного сектора логического диска.

Информация о таблице размещения файлов FAT для текущего диска может быть получена с помощью функции 1Bh прерывания INT 21h, имеющего следующий формат:

На входе: AH = 1Bh
На выходе: DS:BX = Адрес первого байта FAT. Это байт ID идентификации среды носителя данных, соответствует байту media в блоке параметров BIOS.
  DX = Общее количество кластеров на диске.
  AL = Количество секторов в одном кластере.
  CX = Количество байтов в одном секторе.

Дополнительно эта функция возвращает информацию об общем количестве кластеров на диске, размере кластера в секторах и размере сектора в байтах.

Для получения аналогичной информации не о текущем, а о любом диске, используйте функцию 1Ch. Эта функция полностью аналогична предыдущей, за исключением того, что в регистре DL должен быть указан код дисковода: 0 - текущий, 1 - А:, 2 - В: и т.д.

Размер свободного места на диске можно узнать с помощью функции 36h, имеющей следующий формат:

На входе: AH = 36h
  DL = Номер дисковода (0 - текущий, 1 - А:, 2 - В:, и т.д.)
На выходе: AX = Количество секторов в кластере; 0FFFFh, если был задан неправильный номер дисковода;
  BX = Количество свободных кластеров на диске.
  CX = Количество байтов в одном секторе.
  DX = Общее количество кластеров на диске.

Эта функция возвращает в регистре AX число 0FFFFh, если неправильно указан номер дисковода.

Формат блока управления устройствами (DDCB) для DOS версии 4.х и выше:

(0)   drv_num номер устройства (0 соответствует устройству А:, 1 - В: и т.д.)
(+1)   drv_numd дополнительный номер устройства внутри драйвера
(+2)   sec_size размер сектора в байтах
(+4)   clu_size число, на единицу меньшее количества секторов в кластере
(+5)   clu_base если содержимое этого поля не равно нулю, то для получения общего числа секторов в кластере надо возвести 2 в степень clu_base и получившееся число прибавить к clu_size
(+6)   boot_siz количество зарезервированных секторов (boot-сектора, начало корневого каталога)
(+8)   fat_num количество копий FAT
(+9)   max_dir максимальное число дескрипторов файлов в корневом каталоге (т.е. максимальное число файлов, которое может содержать корневой каталог на этом устройстве)
(+11)   data_sec номер первого сектора данных на диске (номер сектора, соответствующего кластеру номер 2)
(+13)   hi_clust максимальное количество кластеров (равно увеличенному на 1 количеству кластеров данных)
(+15)   fat_size количество секторов, занимаемых одной копией FAT
(+16)   reserv1 зарезервироано
(+17)   root_sec номер первого сектора корневого каталога
(+19)   drv_addr FAR-адрес заголовка драйвера, обслуживающего данное устройство
(+23)   media байт описания среды носителя данных
(+24)   acc_flag флаг доступа, 0 означает, что к устройству был доступ
(+25)   next адрес следующего блока DDCB, для последнего блока в поле смещения находится число FFFF
(+29)   reserv2 зарезервироано
(+31)   built число FFFF в этом поле означает, что блок DDCB был построен

Определение типа DDCB:

/* Блок управления устройством DOS */ #pragma pack(1) typedef struct _DDCB_ { unsigned char drv_num; unsigned char drv_numd; unsigned sec_size; unsigned char clu_size; unsigned char clu_base; unsigned boot_siz; unsigned char fat_num; unsigned max_dir; unsigned data_sec; unsigned hi_clust; unsigned char fat_size; char reserv1; unsigned root_sec; void far *drv_addr; unsigned char media; unsigned char acc_flag; struct _DDCB_ far *next; unsigned reserv2; unsigned built;} DDCB;#pragma pack()

Для получения адреса блока DDCB конкретного дисковода можно воспользоваться недокументированной функцией 32h. Она имеет следующий формат вызова:

На входе: AH = 32h
  DL = Номер дисковода (0 - текущий, 1 - А:, 2 - В:, и т.д.)
На выходе: AL = 0, если был задан правильный номер дисковода; 0FFh, если был задан неправильный номер дисковода;
  DS:BX = Адрес блока DDCB

Для получения адреса блока DDCB текущего диска можно воспользоваться недокументированной функцией 1Fh, которая имеет формат, аналогичный функции 32h, за исключением того, что не надо задавать номер дисковода в регистре DL.

Какая еще полезная информация может быть получена при использовании функций MS-DOS?

С помощью функции 33h программа может проверить или установить флаг Ctrl-Break и узнать номер диска, с которого выполнялась загрузка операционной системы:

На входе: AH = 33h
  AL = Код подфункции: 0 - Проверить текущее состояние флага Ctrl-Break; 1 - Установить флаг Ctrl-Break; 5 - Определить номер диска, который был использован для загрузки операционной системы.
  DL = Значение устанавливаемого флага Ctrl-Break для подфункции 1 (0 - OFF, 1 - ON).
На выходе: DL = Текущее состояние флага Ctrl-Break для подфункции 0; Номер диска, использованного для загрузки операционной системы для подфункции 5 (1 - А:, 2 - В:, и т.д.).

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

Состояние флага Ctrl-Break влияет на возможность прервать выполнение программы нажатием комбинации клавиш Ctrl-Break или Ctrl-C. Если флаг находится в состоянии OFF, DOS проверяет эту комбинацию клавиш только при вызове функций стандартного ввода/вывода на консоль, принтер и последовательный порт. Если флаг установлен в состояние ON, комбинация клавиш проверяется и при вызове других функций MS-DOS. Если операционная система зафиксировала нажатие указанной комбинации клавиш, она выполняет прерывание INT 23h, которое завершает работу текущей программы.

Функция 2Fh возвращает в регистровой паре ES:BX адрес текущей области DTA (Disk Transfer Area), которая используется при поиске файлов в каталогах.

Функция 54h позволяет программе узнать текущее состояние флага проверки записывающейся на диск информации. В регистре AL эта функция возвращает текущее состояние флага. Если содержимое регистра равно 1, операционная система после записи сектора считывает его для проверки. Разумеется, такая проверка снижает скорость работы программы. Если после вызова функции регистр AL содержит 0, проверка записи не выполняется.

Для установки флага проверки записи можно использовать функцию 2Eh. Перед вызовом функции в регистр AL необходимо занести новое значение флага проверки: 0 - проверка не нужна; 1 - должна выполняться проверка записанной информации.

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

Функция _dos_getdiskfree() использует функцию 36h для получения информации о диске. Файл dos.h содержит описание этой функции:

unsigned _dos_getdiskfree(unsigned drive, struct diskfree_t *diskspace);

Параметр drive задает номер используемого дисковода: 0 - текущий, 1 - А:, и т.д.

Информация возвращается в структуре diskfree_t, которая определена в файле dos.h:

struct diskfree_t{ unsigned total_clusters; unsigned avail_clusters; unsigned sectors_per_cluster; unsigned bytes_per_sector;};

В этой структуре:

unsigned total_clusters общее количество кластеров на диске;
unsigned avail_clusters количество свободных кластеров;
unsigned sectors_per_cluster количество секторов, занимаемых кластером;
unsigned bytes_per_sector размер сектора в байтах.

Для получения номера текущего диска и для установки номера текущего диска можно использовать, соответственно, функции _dos_getdrive() и _dos_setdrive().

Функция _dos_getdrive() имеет формат:

void _dos_getdrive(unsigned *drive);

Эта функция пользуется функцией 19h для получения номера текущего диска, который записывается по адресу, задаваемому параметром. Значение 1 соответствует диску А:, 2 - В:, и т.д.

Функция _dos_setdrive() предназначена для установки текущего диска и может быть использована для определения общего числа дисков в системе:

void _dos_setdrive(unsigned drive, unsigned *drivecount);

Параметр drive опеределяет текущий диск (1 - А:, и_т.д.), по адресу, задаваемому вторым параметром, функция записывает общее количество логических дисков, установленных в системе. Функция _dos_setdrive() использует функцию 0Eh прерывания INT 21h.

Для иллюстрации способов использования функций _dos_getdrive(), _dos_setdrive(), _dos_getdiskfree() мы составили следующую программу:

#include <dos.h>#include <bios.h>#include <conio.h>#include <stdio.h> void main(void);void main(void) { struct diskfree_t dinfo; unsigned drive, drivecount; printf(“\n” “\nОпределение параметров” “текущего логического диска" “\n (C)Фролов А., 1991” “\n”); // Определяем номер текущего диска: _dos_getdrive(&drive); // Выводим на экран литеру текущего диска: printf("\nТекущийдиск: %c:\n", 'A' + drive - 1); //Вызываем функцию установки текущего диска.//Мы не изменяем текущий диск, вызов этой //функции нужен нам для определения //количества установленных//в системе логических дисков _dos_setdrive(drive, &drivecount); // Получаем характеристики текущего диска: _dos_getdiskfree(drive, &dinfo); printf(“\nОбщее количество” “кластеров на диске: %d” “\nКоличество свободных” “кластеров: %d” “\nКоличество секторов в” “кластере: %d” “\nКоличество байтов в” “секторе: %d” “\nРазмер диска” “в байтах: %ld" "\n", dinfo.total_clusters, dinfo.avail_clusters, dinfo.sectors_per_cluster, dinfo.bytes_per_sector, (long)dinfo.avail_clusters * dinfo.sectors_per_cluster * dinfo.bytes_per_sector); printf(“\nКоличество логических” “дисков: %d” “\n”, drivecount); }

Создание, удаление и переименование каталогов

После форматирования логический диск содержит корневой каталог. Если диск форматируется как системный, в этом каталоге могут находится дескрипторы файлов операционной системы IO.SYS, MSDOS.SYS, COMMAND.COM.

Операционная система предоставляет программам пользователя удобный сервис для создания, уничтожения и переименования каталогов. Используя сведения, приведенные в этой книге, вы сможете изменять структуру каталогов сами, не прибегая к услугам MS-DOS. Однако это следует делать только тогда, когда операции с каталогами по каким-то причинам нежелательно выполнять с использованием функций операционной системы.

Для создания каталога используйте функцию 39h прерывания INT 21h:

На входе: AH = 39h
  DS:DX = Адрес строки в формате ASCIIZ, содержащей имя создаваемого каталога.
На выходе: AL = Код ошибки, если был установлен в 1 флаг переноса CF.

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

Размер строки с именем каталога не должен превышать по длине 64 байта.

Удалить существующий каталог можно с помощью функции 3Ah. Формат вызова этой функции аналогичен предыдущему:

На входе: AH = 3Ah
  DS:DX =Адрес строки в формате ASCIIZ, содержащей имя удаляемого каталога.
На выходе: AL = Код ошибки, если был установлен в 1 флаг переноса CF.

Необходимо заметить, что удалить можно только пустой каталог. И это понятно, так как если вы в обход операционной системы удалите непустой каталог, то описанные в этом каталоге файлы и каталоги будут потеряны для вас, а занимаемое ими место невозможно будет распределить другим файлам.

Для изменения имени каталогов и файлов предназначена функция 56h:

На входе: AH = 56h
  DS:DX = Адрес строки в формате ASCIIZ, содержащей старое имя каталога или файла.
  ES:DI = Адрес строки в формате ASCIIZ, содержащей новое имя каталога или файла.
На выходе: AL = Код ошибки, если был установлен в 1 флаг переноса CF.

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

Эта функция может перемещать файл из одного каталога в другой, если вы укажете разные пути. Каталоги перемещать нельзя, их можно только переименовывать.

Мы уже рассказывали о функции 3Bh, с помощью которой можно изменить текущий каталог, если это необходимо.

Стандартные библиотеки трансляторов Microsoft QC 2.5 и C 6.0 и Borland содержат несколько функций, предназначенных для работы с каталогами.

Функция getcwd() предназначена для определения текущего каталога. Прототип этой функции описан в файле direct.h:

char *getcwd(char *path, int n);

Первый параметр этой функции - адрес буфера, в который необходимо занести строку, содержащую имя текущего каталога. Размер этого буфера определяется вторым параметром.

Если в качестве первого параметра указать NULL, функция динамически закажет буфер длиной n байтов из области кучи. Эту память впоследствии необходимо будет освободить при помощи функции free(). Функция getcwd() возвращает указатель на буфер, содержащий текущий каталог.

Приведем пример простой программы, которая выводит на экран информацию о текущем каталоге:

#include <stdio.h>#include <direct.h> void main(void);void main(void) { printf("\nТекущий каталог: %s\n", getcwd(NULL,70)); }

Для создания и удаления каталогов, изменения текущего каталога имеются функции mkdir(), rmdir(), chdir().

Все эти функции имеют один параметр - путь каталога, который имеет тип (char_*). В случае успешного выполнения операции функции возвращают 0, при ошибке - 1.

Приведем небольшой пример, использующий перечисленные выше функциии:

#include <direct.h>#include <stdlib.h>#include <stdio.h> void main(void);void main(void) { char current_dir[_MAX_DIR]; // _MAX_DIR - максимальная длина// пути для каталога.// Эта константа описана в файле stdlib.h char test_dir[] = "TEST_DIR"; // Запоминаем текущий каталог: getcwd(current_dir, _MAX_DIR); // Пытаемся создать в текущем каталоге // новый каталог if(!mkdir(test_dir)) { // Если удалось создать каталог, делаем его // текущим chdir(test_dir); printf(“\nКталог создан,” “для удаления нажмите” “\nлюбую клавишу,” “ для сохранения - Ctrl-C”); getch(); // Для удаления только что созданного // каталога возвращаемся в каталог// более высокого уровня: chdir(current_dir); rmdir(test_dir); } // Если каталог с таким именем уже // существует или произошла другая ошибка// при создании каталога, выводим сообщение// о невозможности создания каталога. else printf(“\nНевозможно создать” “каталог!”);}

Для переименования каталогов (и файлов) предназначена функция rename():

int rename(char *oldname, char *newname);

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

Функция может возвращать один из кодов ошибки:

ENOENT Нет такого файла или каталога
EACCES Нет прав доступа
EXDEV Другой диск

Код ошибки EXDEV возвращается в том случае, когда программа указывает разные диски для старого и нового имен файлов или каталогов.

Важное замечание: если вы задаете полный путь, в строке пути повторяйте символ '\' два раза. Это нужно для того, чтобы избежать конфликта с форматом представления констант в языке С. Например:

ret_code = rename("c:\\games","c:\\games_new");

Поиск в каталогах

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

Пара функций 4Eh и 4Fh предназначены для сканирования каталогов. Эти функции используются вместе следующим образом:

· Вызывается функция 4Eh для поиска в каталоге файла, соответствующего образцу. В образце можно использовать символы? и *, которые означают, соответственно, один любой символ и любое количество любых символов. Информация о найденном файле располагается в специальной области, назначенной каждой работающей программе - области DTA.

· Вызывается в цикле функция 4Fh для поиска остальных файлов, удовлетворяющих образцу, заданному при вызове функции 4Eh. Условие завершения цикла - отсутствие в каталоге указанных файлов.

Приведем формат вызова функций 4Eh и 4Fh.

Функция 4Eh:

На входе: AH = 4Eh
  CX = Атрибуты файла, которые будут использованы при поиске. Будут найдены файлы, имеющие заданный в этом регистре атрибут.
  DS:DX = Адрес строки в формате ASCIIZ, содержащей путь каталогаили файла.
На выходе: AL = Код ошибки, если был установлен в 1 флаг переноса CF.

Функция 4Fh:

На входе: AH = 4Fh
На выходе: AL = Код ошибки, если был установлен в 1 флаг переноса CF.

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

Для работы с областью DTA MS-DOS имеет две функции. Это функция 2Fh, позволяющая получить адрес области DTA (она возвращает этот адрес в регистрах ES:BX), и функция 1Ah, предназначенная для установки своей области DTA (адрес новой области DTA должен быть указан в регистрах DS:DX).

Напомним, что по умолчанию область DTA занимает 128 байтов в префиксе сегмента программы PSP со смещением 80h.

В случае успешного поиска функции 4Eh и 4Fh помещают в DTA информацию о найденных файлах в следующем формате:

(0)   Зарезервировано.
(+21)   Атрибуты найденного файла
(+22)   Поле времени последнего обновления фалйла
(+24)   Поле даты последнего обновления файла
(+26)   Длина файла
(+30)   Имя файла и расширение в формате ASCIIZ

Номер начального кластера, распределенного файлу или каталогу, невозможно получить с помощью функций 4Eh и 4Fh.

Стандартные библиотеки трансляторов Microsoft QC 2.5 и C 6.0 содержат две функции, предназначенные для сканирования каталогов - _dos_findfirst() и _dos_findnext().

Приведем прототипы этих функций, описанные в файле dos.h:

int _dos_findfirst(char *pattern, struct find_t *found, unsigned attr);int _dos_findnext(struct find_t *found);

В этих функциях параметр pattern определяет образец для поиска файлов, параметр attr - атрибуты файла - используется в качестве дополнительного критерия поиска. Параметр found представляет собой указатель на структуру, в которую будет записываться информация о найденных файлах. Эта структура определена в файле dos.h:

struct find_t { char reserved[21]; // Зарезервировано для DOS char attrib; // Атрибуты файла unsigned wr_time;// Время изменения файла unsigned wr_date; // Дата изменения файла long size; // Размер файла в байтах char name[13]; // Имя файла и расширение};

Приведем текст программы просмотра содержимого каталога. Программа принимает из командной строки параметр - образец для показа файлов. Если вы укажете параметр *.*, будет выведена информация обо всех файлах. Можно задавать полный путь: c:\*.*.

#include <stdlib.h>#include <stdio.h>#include <dos.h> void main(int argc, char *argv[]);void print_info(struct find_t *find);char *time_conv(unsigned time, char *char_buf);char *date_conv(unsigned date, char *char_buf); void main(int argc, char *argv[]) { struct find_t find; // Находим первый файл, удовлетворяющий // критериям поиска.// В качестве критерия используем образец, // полученный из командной строки.// Для поиска используем файлы с любыми// атрибутами. if(!_dos_findfirst(argv[1], 0xffff, &find)) { printf("\n""\nИмя файла Аттр. Дата Время Размер""\n------------ ----- ------ ------ ------"); // Выводим информацию о первом найденном // файле на экран print_info(&find); } else { printf(“Задайте образец” “ для поиска файлов!”); exit(-1); } // Выводим информацию об остальных найденных // файлах while(!_dos_findnext(&find)) print_info(&find); exit(0);} // Функция для вывода информации о найденных //файлах: void print_info(struct find_t *pfind) { char timebuf[10], datebuf[12]; // Преобразуем формат даты и времени // последнего изменения файла: date_conv(pfind->wr_date, datebuf); time_conv(pfind->wr_time, timebuf); // Выводим содержимое дескриптора файла: printf("\n%-12s",pfind->name); printf(" %02X %8s %8s %8ld ", pfind->attrib, datebuf, timebuf, pfind->size);} // Функция преобразования формата времени: char *time_conv(unsigned t, char *buf) { int h, m; h = (t >> 11) & 0x1f, m = (t >> 5) & 0x3f; sprintf(buf, "%2.2d:%02.2d:%02.2d", h % 12, m, (t & 0x1f) * 2); return buf;} // Функция преобразования формата даты: char *date_conv(unsigned d, char *buf) { sprintf(buf, "%2.2d.%02.2d.%04.2d", d & 0x1f,(d >> 5) & 0x0f, (d >> 9) + 1980); return buf;}

При запуске программы с параметром *.com на экран может быть выведена информация:

Имя файла Аттр. Дата Время Размер------------ ----- ---------- -------- ------CURDIR.COM 20 24.02.1991 08:40:24 5879 DIRCTL.COM 20 24.02.1991 09:10:30 6273 DISKINFO.COM 20 24.02.1991 04:08:42 6075

Работа с файлами

Рассмотрим функции MS-DOS, предназначенные для создания, переименования, удаления и перемещения файлов.

Для создания файла предназначена функция 3Ch прерывания INT 21h. С помощью этой функции может быть создан файл как в текущем, так и в любом другом каталоге. Если файл с указанным именем уже существует, он обрезается до нулевой длины. Будьте осторожны при использовании этой функции - она может уничтожить нужный вам файл.

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

Формат вызова функции создания файла:

На входе: AH = 3Ch
  CX = Атрибуты создаваемого файла: 00h - обычный файл; 01h - только читаемый файл; 02h - скрытый файл; 04h - системный файл.
  DS:DX = Адрес строки, содержащей путь создаваемого файла
На выходе: AX = Код ошибки, если был установлен в 1 флаг переноса CF; Файловый индекс, если флаг переноса сброшен в 0.

При выполнении этой функции возможны следующие ошибки:

· отсутствует какой-либо элемент в пути для создаваемого файла, например, диск или каталог;

· была сделана попытка создать файл в корневом каталоге, но корневой каталог переполнен;

· в указаннном каталоге уже есть файл с таким именем, и этот файл имеет атрибут "Только читаемый";

· пользователь, который работает в сети, не имеет прав доступа для выполнения указанной операции.

Операционная система игнорирует попытки создания с помощью этой функции каталогов или метки диска.

Для того, чтобы случайно не уничтожить содержимое файла с таким же именем, как и создаваемый, программа может использовать функцию 5Bh. Эта функция проверяет заданный путь на предмет наличия указанного файла. Если такой файл уже существует, функция возвращает программе признак ошибки.

Формат вызова функции:

На входе: AH = 5Bh
  CX = Атрибуты создаваемого файла: 00h - обычный файл; 01h - только читаемый файл; 02h - скрытый файл; 04h - системный файл.
  DS:DX = Адрес строки, содержащей путь создаваемого файла
На выходе: AX = Код ошибки, если был установлен в 1 флаг переноса CF; Файловый индекс, если флаг переноса сброшен в 0.

Временный файл можно создать с помощью функции 5Ah:

На входе: AH = 5Ah
  CX = Атрибуты создаваемого файла: 00h - обычный файл; 01h - только читаемый файл; 02h - скрытый файл; 04h - системный файл.
  DS:DX = Адрес буфера, в который функция запишет путь созданного временного файла. Размер этого буфера должен быть по крайней мере 13 байтов.
На выходе: AX = Код ошибки, если был установлен в 1 флаг переноса CF; Файловый индекс, если флаг переноса сброшен в 0.

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

Перед тем, как начать работу с файлом, его нужно открыть. Функции, создающие новые файлы, открывают новые файлы автоматически. Для того, чтобы открыть существующий файл, вы можете воспользоваться функцией 3Dh:

На входе: AH = 3Dh
  AL = Требуемый режим доступа: Бит 7: флаг наследования 0 - файловый индекс наследуется порожденным процессом 1 - файловый индекс не наследуется порожденным процессом Биты 4...6: режим разделения 000 - режим совместимости 001 - запрещение всех видов доступа 010 - запрещение записи 011 - запрещение чтения 100 - разрешение всех видов доступа Бит 3:0 - зарезервировано Биты 0...2: вид доступа 000 - чтение 001 - запись 010 - чтение/запись
  DS:DX = Адрес строки, содержащей путь открываемого файла
На выходе: AX = Код ошибки, если флаг переноса CF был установлен в 1; Файловый индекс, если флаг переноса сброшен в 0.

С помощью функции 3Dh можно открыть любой файл (но не каталог). Если требуется вид доступа "запись", открываемый файл не должен иметь атрибут "Только читаемый".

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

Операционная система MS-DOS имеет в своем составе функцию 6Ch, обладающую расширенными возможностями по созданию и открытию файлов:

На входе: AH = 6Ch
  AL = 00h
  BX = байт флагов расширенного режима открытия файла
  CX = атрибуты создаваемого файла, используется только при создании файлов
  DX = выполняемая функция, если файл существует или не существует: Биты 0-3 регистра DX задают действие, если файл существует: 0000h - если файл существует, вернуть признак ошибки 0001h - если файл существует, открыть его 0002h - если файл существует, заместить и открыть его Биты 4-7 регистра DX задают действие, если файл не существует: 0000h - если файл не существует, вернуть признак ошибки 0001h - если файл не существует, создать и открыть его
  DS:SI = Адрес строки, содержащей путь открываемого файла
На выходе: AX = Код ошибки, если флаг переноса CF был установлен в 1; Файловый индекс, если флаг переноса сброшен в 0.
  CX = Код выполненных действий: 0 - файл был открыт 1 - файл был создан и открыт 2 - файл был замещен и открыт

Регистр BX на входе задает флаги расширенного режима открытия файла в следующем формате:

Биты Назначение
0...2 Режим доступа при чтении/записи
  Зарезервировано, должно быть равно 0
4...6 Режим разделения
  Флаг наследования
8...12 Зарезервировано, должно быть равно 0
  0 - Режим обычного использования обработчика критических ошибок INT 24h 1 - Блокировка обработчика критических ошибок INT 24h. Для того, чтобы узнать причину ошибки, программа должна использовать функцию 59h прерывания INT 21h MS-DOS.
  Управление буферизацией: 0 - Использование стандартной для MS-DOS буферизации. 1 - Отмена буферизации. Использование этого режима замедлит работу с диском, однако вероятность потери информации при аварии в питающей сети уменьшится.

Описанная выше функция является как бы комбинацией функций 3Dh и 3Ch (открытие и создание файла).

Удалить файл можно при помощи функции 41h прерывания INT 21h:

На входе: AH = 41h
  DS:DX = Адрес строки в формате ASCIIZ, содержащей имя удаляемого файла.
На выходе: AL = Код ошибки, если был установлен в 1 флаг переноса CF.

С помощью этой функции нельзя удалить файл, имеющий атрибут "Только читаемый".

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

Стандартные библиотеки трансляторов Microsoft QC 2.5 содержат функции для работы с файлами. Эти функции можно разделить на две группы - функции ввода/вывода низкого уровня и функции ввода/вывода потоком. Вторая группа функций использует буферизацию и будет рассмотрена в разделе, посвященном буферизованному вводу/выводу.

Функции ввода/вывода низкого уровня отображаются на описанные выше функции прерывания INT 21h (и функции этого же прерывания, предназначенные для чтения/записи, позиционирования и т.д.).

Для создания файла можно использовать функцию creat():

int creat(char *filename, int mode);

Эта функция и ее параметры описаны в файлах io.h, sys\types.h, sys\stat.h, errno.h.

Первый параметр определяет путь создаваемого файла и его имя. Если файл с указанным именем существует, и не имеет атрибута "Только читаемый", функция сбрасывает длину файла до нуля. Предыдущее содержимое файла при этом уничтожается.

Второй параметр позволяет задать атрибуты создаваемого файла. Он может иметь следующие значения:

S_IWRITE для создаваемого файла разрешена операция записи;
S_IREAD для создаваемого файла разрешена операция чтения;
S_IREAD | S_IWRITE для создаваемого файла разрешены операции чтения и записи.

В операционных системах MS-DOS и OS/2 невозможно создать файл, в который можно было бы писать, но из которого было бы нельзя читать информацию. Поэтому задание второго параметра как S_IWRITE приведет к созданию такого файла, для которого разрешены как операция записи, так и операция чтения.

После создания файла функция creat() открывает новый файл и возвращает файловый индекс (handle) или код ошибки.

Функция open() предназначена как для открытия существующих файлов, так и для создания новых:

int open(char *filename, int oflag [, int pmode]);

Первый и третий параметры в этой функции аналогичны параметрам функции creat(), причем третий параметр нужен только при создании нового файла. Квадратные скобки указывают на то, что этот параметр является необязательным.

Параметр oflag может являться результатом битовой операции ИЛИ над следующими константами, определенными в файле fcntl.h:

O_APPEN при записи в файл информация будет добавляться в конец файла;
O_BINARY файл открывается для работы в двоичном режиме (игнорируются управляющие символы, такие как конец строки);
O_CREAT создается новый файл и открывается для записи; эта константа игнорируется, если указанный в первом параметре файл уже существует;
O_EXCL используется вместе с O_CREAT; если указанный в первом параметре файл существует, функция возвратит признак ошибки;
O_RDONLY файл открывается только для чтения, попытка записи в файл приведет к тому, что функция записи вернет признак ошибки;
O_RDWR файл открывается как для чтения, так и для записи;
O_TEXT файл открывается в текстовом режиме;
O_TRUNC существующий файл открывается и обрезается до нулевой длины (если для этого файла разрешена операция записи);
O_WRONLY файл открывается только для записи (в операционных системах MS-DOS и OS/2 для файла, открытого с признаком O_WRONLY разрешено выполнение операции чтения).

Для того, чтобы закрыть файл, открытый функциями creat() или open(), нужно использовать функцию close():

int close(int handle);

В качестве параметра функции передается файловый индекс, полученный при открытии или создании файла. Функция возвращает 0 при успешном закрытии файла, или -1 при ошибке.

Код ошибки для этой и других функций cтандартных библиотек трансляторов Microsoft QC 2.5 и C 6.0 записывается в глобальную переменную errno.

3.5. Чтение/запись файлов

После того, как вы открыли файл, можно выполнять над ним операции чтения/записи. Для записи данных в файл предназначена функция 40h прерывания INT 21h. В качестве параметров для этой функции необходимо задать файловый индекс, полученный при открытии существующего файла или создании нового, адрес буфера, содержащего записываемые данные и количество записываемых байтов:

На входе: AH = 40h
  BX = файловый индекс открытого файла
  CX = количество записываемых байтов
  DS:DX = Адрес буфера, содержащего записываемые данные
На выходе: AX = Код ошибки, если был установлен в 1 флаг переноса CF; Количество действительно записанных байтов, если флаг переноса CF сброшен в 0.

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



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2016-02-16 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: