
- •Работа с файловой системой
- •Содержание
- •1. Цель работы
- •2. Порядок выполнения работы
- •3. Структура каталогов файловых систем fat и vfat
- •Структура элемента каталога fat в Windows
- •Структура элемента каталога с длинным именем
- •4. Работа с файловой системой
- •4.1. Создание, открытие, чтение и запись в файл
- •4.2. Поиск файлов в dos
- •4.3. Поиск файлов в Windows
- •4.4. Опрос и изменение свойств файлов
- •4.4.1. Атрибуты
- •4.4.2. Дата и время последней модификации
- •4.5. Перемещение и удаление файлов
- •4.6. Работа с каталогами
- •5. Работа с параметрами командной строки
- •6. Пример
- •Текст программы
- •Библиографический список
- •Поиск файлов по дереву каталогов
- •Варианты заданий
5. Работа с параметрами командной строки
Параметры, которые вводятся после имени программы в командной строке, копируются операционной системой в PSP программы. Сегментный адрес PSP после старта содержится в DS и ES.
По смещению 0080h в PSP находится байт, равный длине строки параметров, сама строка располагаются со смещения 0081h, и оканчивается символом с кодом 0Dh (этот символ не входит в длину строки).
Перед копированием в PSP строка параметров преобразуется в стандартный формат. Она начинается с пробела (20h), между отдельными словами оставляется по одному пробелу, остальные отбрасываются, и отбрасываются пробелы, введенные за последним параметром, таким образом код 0Dh следует сразу за последним словом (рис.1).
Если файл с длинным именем содержит пробелы в имени, то оно передается в командную строку заключенным в кавычки ” (22h).
Вводится с клавиатуры:
С:>PROG.EXE FILE1.TXT FILE2.TXT ENTER
Содержится в PSP:
[0080h]: 14h (20 символов)
[0081h]: 20h ,“FILE1.TXT”, 20h, “FILE2.TXT” , 0Dh
Рис.1. Пример передачи параметров в командной строке
6. Пример
Задача: программе в командной строке передаются два имени файла. Скопировать файл_1 под именем файла_2. Имена файлов длинные.
Для функций создания и открытия надо иметь имена файлов в виде ASCIIZ строки. Символ с кодом 0 записывается в конце имени файла прямо в командной строке.
Для ускорения копирования файла чтение и запись производится блоками по 512 байт (один сектор) в цикле. Обычно последний сектор файла занят не полностью, т.е. число прочитанных байт меньше 512. Это является условием окончания цикла копирования.
Текст программы
code segment para
assume cs:code, ds:code, es:code
CmdSize EQU byte ptr ds:[080h]
CmdLine EQU byte ptr ds:[081h]
org 100h
start:
; Анализ параметров командной строки.
cmp CmdSize,0 ; длина строки параметров =0 ?
jne skip1 ; нет - продолжить
run_format_error:
mov ah,9 ; вывести сообщение об ошибке
lea dx,RunFormatErr
int 21h
jmp Exit ; и выйти
skip1:
; Выделение первого имени (cмещение -> в FNameOfs1)
cld
xor cx,cx
mov cl,CmdSize ; в CX длина командной строки
mov FNameOfs1,82h ; по 81h пробел, имя начинается с 82h
; или с 83h, если оно в кавычках
mov di,FNameOfs1
cmp CmdLine[1],'"' ; первый символ имени - кавычки ?
jne no_space_1 ; нет - перейти
inc FNameOfs1 ; пропустить 1-е кавычки
inc di
mov al,'"' ; поиск закрывающих кавычек
repne scasb ; (в CX длина командной строки)
test cx,cx
jz run_format_error ; кавычки не найдены - ошибка
mov byte ptr [di-1],0 ; заменяем кавычки на 0
; di указывает на пробел или 0Dh, если параметр всего 1
no_space_1:
; имя 1-го файла не содержит пробелов.
; ищем символ окончания имени - пробел или 0Dh
cmp byte ptr [di],20h ; сравниваем с пробелом
je first_name_end ; найден конец имени - переход
cmp byte ptr [di],0Dh ; сравниваем с 0Dh
je run_format_error ; равен: всего 1 параметр - ошибка
inc di
dec cx
jmp short no_space_1 ; переходим на следующий символ
first_name_end:
mov byte ptr [di],0 ; заменить пробел на 0
inc di
; Выделение второго имени (cмещение -> в FNameOfs2)
mov FNameOfs2,di
cmp byte ptr [di],'"' ; первый символ имени - кавычки ?
jne no_space_2 ; нет - перейти
inc FNameOfs2 ; пропустить кавычки
inc di
mov al,'"' ; поиск закрывающих кавычек
repne scasb
test cx,cx
jz run_format_error ; кавычки не найдены - ошибка
mov byte ptr [di-1],0 ; делаем имя в ASCIIZ-формате
no_space_2:
; имя 2-го файла не содержит пробелов. Оно должно
; оканчиваться кодом 0Dh.
; Если оканчивается пробелом, то ошибка.
cmp byte ptr [di],0Dh ; сравниваем символ с 0Dh...
je second_name_end
cmp byte ptr [di],20h ; ... и с пробелом
je run_format_error ; равен - ошибка
inc di
jmp short no_space_2 ; переходим на следующий символ
second_name_end:
mov byte ptr [di],0 ; заменяем 0Dh на код 0
; Открываем и создаем файлы
mov ax,716Ch
mov si,FNameOfs1 ; первый файл ...
mov bx,100B ; ... открыть для чтения
mov dx,00001B ; не существует-возвратить ошибку
int 21h
jnc file_is_open ; ошибок нет - перейти
mov ah,9
lea dx,FileNotFound ; вывести сообщение об ошибке
int 21h
jmp exit ; и выйти
file_is_open:
mov Handler1,ax ; сохранить манипулятор
mov ax,716Ch
mov si,FNameOfs2 ; второй файл...
mov dx, 10000B ; ... создать новый
mov bx,001B ; ... и открыть для записи
mov cx,100000B ; атрибут - архивный
int 21h
jnc file_is_created ; ошибок нет - перейти
mov ah,9
lea dx,CantCreateFile ; вывести сообщение об ошибке
int 21h
jmp exit ; и выйти
file_is_created:
mov Handler2,ax ; сохранить манипулятор
; Копируем из первого файла во второй
lea dx,Buffer ; ds:dx - адрес буфера чтения/записи
next:
mov ah,3Fh ; читаем...
mov bx,Handler1 ; ...из первого файла
mov cx,512 ; по 512 байт
int 21h
jc close_files ; ошибка - прекратить копирование
push cx
mov cx,ax ; в AX число прочитанных байт
mov ah,40h ; записываем...
mov bx,Handler2 ; ... во второй файл (число байт в CX)
int 21h
jc close_files ; ошибка - прекратить копирование
pop cx
cmp ax,cx ; число записанных байт = 512 ?
je next ; да (не конец файла) - продолжить
mov ah,9
lea dx,CopyOk ; вывести сообщ.об успешном копировании
int 21h
close_files:
mov ah,3Eh ; закрыть файл 1
mov bx,Handler1
int 21h
mov bx,Handler2 ; закрыть файл 2
int 21h
exit:mov ax,4C00h ; завершить программу
int 21h
;--------- Область данных---------------
RunFormatErr db "ОШИБКА: Heвepный фopmaт зanycka",0Dh,0Ah,"$"
FileNotFound db "ОШИБКА: Файл не найден",0Dh,0Ah,"$"
CantCreateFile db "ОШИБКА: He moгy coздaть файл",0Dh,0Ah,"$"
CopyOk db "Копирование выполнено",0Dh,0Ah,"$"
align word
FNameOfs1 dw ? ; смещение 1-го имени
FNameOfs2 dw ? ; смещение 2-го имени
Handler1 dw ? ; манипулятор для 1-го файла
Handler2 dw ? ; манипулятор для 2-го файла
Buffer db 512 dup (0) ; буфер чтения/записи
code ends
end start