Работа с файлами в DOS
Автор: xrnd | Рубрика: Исходники | 25-12-2010 | Распечатать запись
Эта статья лишь небольшой пример того, как можно работать с файлами, используя функции DOS. Я не буду описывать все возможные значения параметров и вдаваться в подробности. Это вы можете найти самостоятельно в справочнике.
Первая программа будет создавать файл и записывать в него данные. Вторая программа — открывать файл, читать данные и выводить их на консоль.
Создание нового файла
Прежде, чем что-то записывать, необходимо создать файл. Для этого используется функция DOS 3Ch.
Имя файла должно быть в формате 8.3 — 8 символов имени и 3 символа расширения. Естественно, можно использовать только английский буквы, цифры и некоторые другие символы. Строка с именем файла должна заканчиваться нулевым байтом. Если файл уже существует, то его содержимое будет удалено.
Об ошибке можно узнать, проверяя значение флага CF (1 — ошибка, 0 — нет ошибки). Аналогично для других функций работы с файлами. Если флаг CF равен 0, то в регистре AX будет находиться дескриптор (или описатель) файла. Дескриптор — это просто специальное число, по которому операционная система отличает один открытый файл от другого.
Запись данных в файл
Запись в файл выполняется функцией DOS 40h. Этой функции нужно передать в регистре BX тот самый дескриптор, который был получен при создании файла.
Если вам требуется записать много данных, можно вызывать эту функцию несколько раз.
Закрытие файла
После работы с файлом нужно его закрыть с помощью функции DOS 3Eh.
Если вы не закроете файл, то он будет закрыт системой при выходе из программы. Однако, хорошим стилем программирования является явное закрытие файла после завершения работы с ним.
Пример первый
Программа создаёт новый файл и записывает в него данные. Так как диск и директория не указаны, то файл создаётся в текущей папке. В данном примере в файл записываются 2 строки, получается текстовый файл. Можно работать с двоичными файлами, записывая любые байты, слова и т.д.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | use16 ;Генерировать 16-битный код org 100h ;Программа начинается с адреса 100h jmp start ;Перепрыгнуть данные ;------------------------------------------------------------------------------- ; Данные file_name db 'hello.txt',0 buffer db 'asmworld.ru',13,10,'Hello!' size db 19 s_error db 'Error!',13,10,'$' s_pak db 'Press any key...$' handle rw 1 ;Дескриптор файла ;------------------------------------------------------------------------------- ; Код start: mov ah,3Ch ;Функция DOS 3Ch (создание файла) mov dx,file_name ;Имя файла xor cx,cx ;Нет атрибутов - обычный файл int 21h ;Обращение к функции DOS jnc @F ;Если нет ошибки, то продолжаем call error_msg ;Иначе вывод сообщения об ошибке jmp exit ;Выход из программы @@: mov [handle],ax ;Сохранение дескриптора файла mov bx,ax ;Дескриптор файла mov ah,40h ;Функция DOS 40h (запись в файл) mov dx,buffer ;Адрес буфера с данными movzx cx,[size] ;Размер данных int 21h ;Обращение к функции DOS jnc close_file ;Если нет ошибки, то закрыть файл call error_msg ;Вывод сообщения об ошибке close_file: mov ah,3Eh ;Функция DOS 3Eh (закрытие файла) mov bx,[handle] ;Дескриптор int 21h ;Обращение к функции DOS jnc exit ;Если нет ошибки, то выход из программы call error_msg ;Вывод сообщения об ошибке exit: mov ah,9 mov dx,s_pak int 21h ;Вывод строки 'Press any key...' mov ah,8 ;\ int 21h ;/ Ввод символа без эха mov ax,4C00h ;\ int 21h ;/ Завершение программы ;------------------------------------------------------------------------------- ; Процедура вывода сообщения об ошибке error_msg: mov ah,9 mov dx,s_error int 21h ;Вывод сообщения об ошибке ret |
В результате работы программы создаётся файл, который можно открыть блокнотом:
Открытие существующего файла
Для открытия файла используется функция DOS 3Dh. В отличие от создания файла, эта функция завершится ошибкой, если файл не существует.
Чтение данных из файла
Чтение из файла выполняется функцией DOS 3Fh.
Размер буфера для данных должен быть больше или равен количеству считываемых байтов. Обратите внимание, что в AX функция возвращает количество реально прочитанных байтов. Это количество может быть меньше требуемого, например, если файл слишком короткий.
Пример второй
Программа читает данные из текстового файла и выводит на консоль. Для того, чтобы вывести данные, нужно добавить символ ‘$’ в конец строки.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | use16 ;Генерировать 16-битный код org 100h ;Программа начинается с адреса 100h jmp start ;Перепрыгнуть данные ;------------------------------------------------------------------------------- ; Данные file_name db 'hello.txt',0 s_error db 'Error!',13,10,'$' s_file db '----[ file "Hello.txt" ]$' endline db 13,10,'$' s_pak db 'Press any key...$' buffer rb 81 ;80 + 1 байт для символа конца строки '$' handle rw 1 ;Дескриптор файла ;------------------------------------------------------------------------------- ; Код start: mov ah,3Dh ;Функция DOS 3Dh (открытие файла) xor al,al ;Режим открытия - только чтение mov dx,file_name ;Имя файла xor cx,cx ;Нет атрибутов - обычный файл int 21h ;Обращение к функции DOS jnc @F ;Если нет ошибки, то продолжаем call error_msg ;Иначе вывод сообщения об ошибке jmp exit ;Выход из программы @@: mov [handle],ax ;Сохранение дескриптора файла mov bx,ax ;Дескриптор файла mov ah,3Fh ;Функция DOS 3Fh (чтение из файла) mov dx,buffer ;Адрес буфера для данных mov cx,80 ;Максимальное кол-во читаемых байтов int 21h ;Обращение к функции DOS jnc @F ;Если нет ошибки, то продолжаем call error_msg ;Вывод сообщения об ошибке jmp close_file ;Закрыть файл и выйти из программы @@: mov bx,buffer add bx,ax ;В AX количество прочитанных байтов mov byte[bx],'$' ;Добавление символа '$' mov ah,9 mov dx,s_file int 21h ;Вывод строки с именем файла mov cx,56 call line ;Вывод линии mov ah,9 mov dx,buffer int 21h ;Вывод содержимого файла mov dx,endline int 21h ;Вывод перехода на новую строку mov cx,80 call line ;Вывод линии close_file: mov ah,3Eh ;Функция DOS 3Eh (закрытие файла) mov bx,[handle] ;Дескриптор int 21h ;Обращение к функции DOS jnc exit ;Если нет ошибки, то выход из программы call error_msg ;Вывод сообщения об ошибке exit: mov ah,9 mov dx,s_pak int 21h ;Вывод строки 'Press any key...' mov ah,8 ;\ int 21h ;/ Ввод символа без эха mov ax,4C00h ;\ int 21h ;/ Завершение программы ;------------------------------------------------------------------------------- ; Процедура вывода сообщения об ошибке error_msg: mov ah,9 mov dx,s_error int 21h ;Вывод сообщения об ошибке ret ;------------------------------------------------------------------------------- ; Вывод линии ; CX - количество символов line: mov ah,2 ;Функция DOS 02h (вывод символа) mov dl,'-' ;Символ @@: int 21h ;Обращение к функции DOS loop @B ;Команда цикла ret |
Результат работы программы:
Некоторые другие функции DOS для работы с файлами
Подробное описание смотрите в справочнике.
- 5Bh — создание нового файла без удаления существующего;
- 5Ah — создание файла с уникальным именем (например, временного файла);
- 41h — удаление файла;
- 42h — установка указателя чтения/записи;
- 56h — переименование файла;
- 43h — получение или изменение атрибутов файла;
- 57h — получение или изменение метки времени файла;
- 39h — создание папки;
- 3Ah — удаление папки;
- 3Bh — изменение текущей папки;
- 47h — получение текущей папки.
25-12-2010 08:14
Вот почему-то у меня эти коды не компилируются выдало 34 ошибки, использую TASM 5.0
25-12-2010 14:01
Эти коды для FASM.
26-12-2010 15:27
У Вас очень замечательный сайт, очень рад, что меня сюда занесло. А то мучался бы до сих пор в tasm. Всем у кого он стоит, рекомендую удалить и поставить FASM, один минус — большие испольняемые файлы. У меня следующий вопрос, как мне заставить программу читать имя файла, который с её помощью пытаются открыть. Вот например я хочу записать в .bat proga.com file.txt ну для примера сохранить имя файла (от корневого каталога) в текстовый файл?
27-12-2010 21:17
Список параметров для программы в DOS находится в блоке PSP.
Этот блок занимает первые 256 байт сегмента COM-программы (кстати, поэтому программа начинается с адреса 100h).
Вот хорошая ссылка, там даже есть пример кода для получения параметров:
http://frolov-lib.ru/books/bsp/v18/ch3_3.html
26-12-2010 19:30
Подскажи, пожалуйста, как здесь передвинуть чтение с первого байта на четвёртый, в tasm, если не ошибаюсь, это знчение помещается в bx?
@@:mov [handle],ax ;Сохранение дескриптора файла
mov bx,ax ;Дескриптор файла
mov ah,3Fh ;Функция DOS 3Fh (чтение из файла)
mov dx,buffer ;Адрес буфера для данных
mov cx,80 ;Максимальное кол-во читаемых байтов
int 21h ;Обращение к функции DOS
jnc @F ;Если нет ошибки, то продолжаем
call error_msg ;Вывод сообщения об ошибке
jmp close_file ;Закрыть файл и выйти из программы
27-12-2010 21:29
В BX помещается дескриптор файла.
Чтобы передвинуть позицию чтения из файла, нужно использовать функцию 42h.
Примерно так:
30-09-2018 17:13
Добрый время суток.
У меня такая проблема. Использую полностью ваш код для открытия, чтения и вывода на консоль, то же имя файла, с той лишь разницей, что сам назначаю регистры, хотя с COM-приложением дело обстоит также. При запуске программы из-под WinXP программа выводит содержимое файла, а при запуске в отладчике(Turbo Debugger с вашего сайта) почему-то CF устанавливается в 1, что приводит к выведению на экран сообщения об ошибке. В AX после попытки открытия заносится 2. Подскажите, пожалуйста, почему так и как решить проблему.