 |
Ассемблер в примерах - Поиск файлов
- Вопрос:
- Задача следующая: написать программу используя функции FindFirstFile и FindNextFile для поиска всех файлов с расширением *.txt в текущей директории и под директории ( не знаю как сделать ) с целью записи цифры "74" 20 раз.
- Ответ:
- Чтобы сделать обход поддиректорий, необходимо реализовать рекурсивный вызов. При этом необходимо все данные строить в стеке, а не в сегменте data.
Ваша главная ошибка - неправильный формат данных для поиска.
.386
.model flat, STDCALL ;STDCALL для задания порядка загрузки параметров при вызове call
includelib import32.lib
OPEN_EXISTING = 3
FILE_ATTRIBUTE_NORMAL = 80h
FILE_ATTRIBUTE_DIRECTORY = 10h
GENERIC_READ = 80000000h
GENERIC_WRITE = 40000000h
PAGE_READWRITE = 00000004h
FILE_MAP_WRITE = 02h or 04h
INVALID_HANDLE_VALUE = 0ffffffffh
MAX_PATH = 260
MB_OK = 0
FILETIME struc
lowTime dd ?
highTime dd ?
FILETIME ends
;структура для поиска
FINDDATA struc
dwFileAttributes dd ?
ftCreationTime FILETIME <>
ftLastAccessTime FILETIME <>
ftLastWriteTime FILETIME <>
nFileSizeHigh dd ?
nFileSizeLow dd ?
dwReserved0 dd ?
dwReserved1 dd ?
cFileName db MAX_PATH dup (?)
cAlternateFileName db 16 dup (?)
FINDDATA ends
extrn ExitProcess : proc
extrn CreateFileA : proc
extrn MessageBoxA : proc
extrn CreateFileMappingA : proc
extrn UnmapViewOfFile : proc
extrn CloseHandle : proc
extrn MapViewOfFile : proc
extrn FindFirstFileA : proc
extrn FindNextFileA : proc
extrn FindClose : proc
extrn GetLastError : proc
extrn lstrcpyA : proc
extrn lstrcatA : proc
extrn _wsprintfA : proc
;--------------------------------------
.data
FilesCount dd 0 ;посчитаем число файлов
root db 0 ;для задания текущей директории
string db '74'
len equ $-string
count equ 20 ;зададим число повторов как величину count
FNSearch db '*.txt',0 ;маска для поиска файлов
DNSearch db '*.*',0 ;маска для поиска поддиректорий
sTitle db 'Конец работы',0 ;для MessageBox в конце работы
sFormat db 'Исправлено %d файлов',0
sMessage db 32 dup (?)
;--------------------------------------
.code
_start:
call find, offset root, offset FNSearch, 0 ;ищем в текущей директории файлы *.txt
call find, offset root, offset DNSearch, FILE_ATTRIBUTE_DIRECTORY ;пройдемся по всем поддиректориям
call _wsprintfA, offset sMessage, offset sFormat, [FilesCount] ;подготовим сообщение
call MessageBoxA, 0, offset sMessage, offset sTitle, MB_OK ;выведем
call ExitProcess, 0
;Функция строит строку пути из двух и разделяет '\'
FormName proc NameTo:dword, Name1From:dword, Name2From:dword
uses esi, edi
mov edi, [NameTo]
mov esi, [Name1From]
copy_name1_loop:
mov al, [esi]
cmp al, 0
je insert_slash
inc esi
stosb
jmp copy_name1_loop
insert_slash:
cmp esi, [Name1From]
je copy_name2
mov al, '\'
stosb
copy_name2:
mov esi, [Name2From]
copy_name2_loop:
lodsb
stosb
cmp al, 0
jne copy_name2_loop
ret
FormName endp
;параметры:
;path - путь, начиная с текущей, 0 - текущая директория
;filemask - маска файлов, которые ищем
;attribute - что ищем, файлы или поддиректории
find proc path:dword, filemask:dword, attribute:dword
uses ebx, esi, edi
local hFF:dword, WFD32:FINDDATA, temp:byte:MAX_PATH
;строим в temp маску вместе с путем
lea ebx, [temp]
mov edx, [filemask]
call FormName, ebx, [path], edx
;ищем первый или файл, или каталог
lea eax, WFD32
call FindFirstFileA, ebx, eax
cmp eax,INVALID_HANDLE_VALUE
je find_ret ;не найдено
mov [hFF],eax ;handle поиска
find_next:
;проверим, то ли мы нашли
mov eax, [WFD32.dwFileAttributes] ;атрибут того, что нашли
and eax, FILE_ATTRIBUTE_DIRECTORY ;выделим атрибут директории
xor eax, [attribute] ;равен ли требуемому?
jnz find_continue ;не равен, значит на продолжение поиска
test [WFD32.dwFileAttributes], FILE_ATTRIBUTE_DIRECTORY ;если работаем с директориями, то на отработку директорий
jnz directory_found
;файлы
;формируем имя файла с путем
lea ebx, [temp]
lea edx, [WFD32.cFileName]
call FormName, ebx, [path], edx
;отработаем
call WriteToFile, ebx
find_continue: ;на продолжение поиска
lea eax, WFD32
call FindNextFileA, [hFF], eax
test eax, eax
jnz find_next ;найдено
call FindClose, [hFF] ;не найдено - закрываем поиск
find_ret:
ret
;директории
directory_found:
cmp [WFD32.cFileName], '.' ;обойдем '.' и '..'
je find_continue
;формируем имя поддиректории с путем
lea ebx, [temp]
lea edx, [WFD32.cFileName]
call FormName, ebx, [path], edx
;вызываем рекурсивно для поддиректории
call find, ebx, offset FNSearch, 0 ;ищем файлы *.txt
call find, ebx, offset DNSearch, FILE_ATTRIBUTE_DIRECTORY ;ищем поддиректории
jmp find_continue
find endp
;пишем в начало файла
WriteToFile proc filename:dword
uses esi, edi
local HFile:dword, HFM:dword, addr_of_the_mapped_view:dword
call CreateFileA, [filename], GENERIC_READ or GENERIC_WRITE, \
0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0
cmp eax, INVALID_HANDLE_VALUE
je WTF_ret
mov [HFile], eax
CREATE_MAPPING:
call CreateFileMappingA, eax, 0, PAGE_READWRITE, 0, len*count, 0
test eax, eax
jz CLOSEF
mov [HFM], eax
MAP:
call MapViewOfFile, eax, FILE_MAP_WRITE, 0, 0, len*count
test eax, eax
jz CLOSEMAP
mov [addr_of_the_mapped_view], eax
mov edx, count
mov edi, eax
ACT:
mov esi, offset string
mov ecx, len
rep movsb
dec edx
jnz ACT
inc [FilesCount]
UNMAP:
call UnmapViewOfFile, [addr_of_the_mapped_view]
CLOSEMAP:
call CloseHandle, [HFM]
CLOSEF:
call CloseHandle, [HFile]
WTF_ret:
ret
WriteToFile endp
end _start
|  |