Учебник по ассемблеру (ASM)
 

Ассемблер в примерах - Поиск файлов

Вопрос:
Задача следующая: написать программу используя функции 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

   Вперёд
   Содержание
Шикарные девушки devochki-tut помогают расслабиться