Good Day,
This messageboard has helped me so very much, and I wanted to return a little something. I am posting a Copy Files routine. This routine will copy files using filename.ext and wildcards while filtering out the folders, and this proc is easy to manipulate into a movefiles routine.
I hope that this contribution helps people struggling with this topic.
;================ How to use Copy_Files PROC ===============
;Copy_Files PROTO :DWORD, :DWORD
;.data
;FilesPattern db "*.*",0
;DestinationDir db "c:\",0
;BackSlash db "\",0
;invoke Copy_Files,addr FilesPattern,addr DestinationDir
;================= Required Data In Main File ================
.data?
FHandle dd ?
hSearch dd ?
Win32FindData WIN32_FIND_DATA<>
;=================================================
Copy_Files proc Pattern:DWORD, DestFolder:DWORD
LOCAL tmpbuf:BYTE
LOCAL CmpByte:BYTE
invoke lstrcpy,addr tmpbuf,DestFolder
invoke lstrlen,addr tmpbuf
dec eax
lea ebx, tmpbuf
mov cl, BYTE PTR
.if cl != '\'
invoke lstrcat,addr tmpbuf,addr BackSlash
.endif
invoke FindFirstFile,Pattern,addr Win32FindData
.if eax != INVALID_HANDLE_VALUE
mov hSearch,eax
xor edi,edi
.while eax!=ERROR_NO_MORE_FILES
invoke lstrcat,ADDR tmpbuf,ADDR Win32FindData.cFileName
invoke CopyFile,addr Win32FindData.cFileName, addr tmpbuf,0
invoke FindNextFile,hSearch,addr Win32FindData
invoke GetLastError
.endw
invoke FindClose,hSearch
.endif
ret
Copy_Files endp
;=================================================
I am always looking to improve procs, so feel free to optimize this...;)
This messageboard has helped me so very much, and I wanted to return a little something. I am posting a Copy Files routine. This routine will copy files using filename.ext and wildcards while filtering out the folders, and this proc is easy to manipulate into a movefiles routine.
I hope that this contribution helps people struggling with this topic.
;================ How to use Copy_Files PROC ===============
;Copy_Files PROTO :DWORD, :DWORD
;.data
;FilesPattern db "*.*",0
;DestinationDir db "c:\",0
;BackSlash db "\",0
;invoke Copy_Files,addr FilesPattern,addr DestinationDir
;================= Required Data In Main File ================
.data?
FHandle dd ?
hSearch dd ?
Win32FindData WIN32_FIND_DATA<>
;=================================================
Copy_Files proc Pattern:DWORD, DestFolder:DWORD
LOCAL tmpbuf:BYTE
LOCAL CmpByte:BYTE
invoke lstrcpy,addr tmpbuf,DestFolder
invoke lstrlen,addr tmpbuf
dec eax
lea ebx, tmpbuf
mov cl, BYTE PTR
.if cl != '\'
invoke lstrcat,addr tmpbuf,addr BackSlash
.endif
invoke FindFirstFile,Pattern,addr Win32FindData
.if eax != INVALID_HANDLE_VALUE
mov hSearch,eax
xor edi,edi
.while eax!=ERROR_NO_MORE_FILES
invoke lstrcat,ADDR tmpbuf,ADDR Win32FindData.cFileName
invoke CopyFile,addr Win32FindData.cFileName, addr tmpbuf,0
invoke FindNextFile,hSearch,addr Win32FindData
invoke GetLastError
.endw
invoke FindClose,hSearch
.endif
ret
Copy_Files endp
;=================================================
I am always looking to improve procs, so feel free to optimize this...;)
SpEcIeS,
Here is the same code in C from MSDN:
I'm wondering why you translate from C in "C like ASM"
Your code will be slower because of that.
The messageboard will helps you again with Readiosys's advice:
"Personally, I never use these as if I'm writing in assembly, it is to have 100% control over my source code...
Otherwise, it is better to use a HLL language like C with high optimizing compilers."
You can read it here: http://www.asmcommunity.net/board/showthread.php?threadid=9462
Regards,
Lingo
Here is the same code in C from MSDN:
WIN32_FIND_DATA FileData;
HANDLE hSearch;
DWORD dwAttrs;
char szDirPath[] = "c:\;
char szNewPath[MAX_PATH];
char szHome[MAX_PATH];
BOOL fFinished = FALSE;
hSearch = FindFirstFile("*.*", &FileData);
if (hSearch == INVALID_HANDLE_VALUE)
{
ErrorHandler("No files found.");
}
while (!fFinished)
{
lstrcpy(szNewPath, szDirPath);
lstrcat(szNewPath, FileData.cFileName);
if (!CopyFile(FileData.cFileName, szNewPath, FALSE))
{
ErrorHandler("Couldn't copy file.");
}
if (!FindNextFile(hSearch, &FileData))
{
if (GetLastError() == ERROR_NO_MORE_FILES)
{
MessageBox(hwnd, "No more files.",
"Search completed.", MB_OK);
fFinished = TRUE;
}
else
{
ErrorHandler("Couldn't find next file.");
}
}
}
if (!FindClose(hSearch))
{
ErrorHandler("Couldn't close search handle.");
}
I'm wondering why you translate from C in "C like ASM"
Your code will be slower because of that.
The messageboard will helps you again with Readiosys's advice:
"Personally, I never use these as if I'm writing in assembly, it is to have 100% control over my source code...
Otherwise, it is better to use a HLL language like C with high optimizing compilers."
You can read it here: http://www.asmcommunity.net/board/showthread.php?threadid=9462
Regards,
Lingo
Thanks for the input...:grin:
Since I was having difficulties in creating such a procedure, I used a C code template (Not from MSDN) to build such a function. It gets the job done, but I see your point about being slower. I guess I will have to go over this proc and speed things up.
Also, It is difficult to paste information on the board. I have looked over the code that I pasted and have found that not only has the code been drawn in, but a backslash was removed in the if cl != statement. I am not sure why, but it happened...:(
Anyway, thanks again for the imput. :alright:
Since I was having difficulties in creating such a procedure, I used a C code template (Not from MSDN) to build such a function. It gets the job done, but I see your point about being slower. I guess I will have to go over this proc and speed things up.
Also, It is difficult to paste information on the board. I have looked over the code that I pasted and have found that not only has the code been drawn in, but a backslash was removed in the if cl != statement. I am not sure why, but it happened...:(
Anyway, thanks again for the imput. :alright:
Here is an altered version of the original Copy_Files above. Is it really any different that using .IF and .WHILE? Perhaps someone could enlighten me on this subject. <???> :confused:
Revamped Copy_Files:
;======= How to use Copy_Files PROC ===========
;Copy_Files PROTO :DWORD, :DWORD
;.data
;FilesPattern db "*.*",0
;DestinationDir db "c:\",0
;BackSlash db "\",0
;invoke Copy_Files,addr FilesPattern,addr DestinationDir
;======= Required Data In Main File =============
.data?
FHandle dd ?
hSearch dd ?
Win32FindData WIN32_FIND_DATA<>
;========================================
Copy_Files proc Pattern:DWORD, DestFolder:DWORD
LOCAL tmpbuf:BYTE
invoke FindFirstFile,Pattern,addr Win32FindData
cmp eax,INVALID_HANDLE_VALUE
je InvalidHandle
mov hSearch,eax
CheckForFiles:
cmp eax,ERROR_NO_MORE_FILES
je LeaveLoop
invoke lstrcpy,addr tmpbuf,DestFolder
invoke lstrlen,addr tmpbuf
dec eax
lea ebx, tmpbuf
mov cl, BYTE PTR
cmp cl,05ch
je BSOK
invoke lstrcat,addr tmpbuf,addr BackSlash
BSOK:
cmp Win32FindData.dwFileAttributes,FILE_ATTRIBUTE_DIRECTORY
jne NotDir
jmp Continue
NotDir:
invoke lstrcat,ADDR tmpbuf,ADDR Win32FindData.cFileName
invoke CopyFile,addr Win32FindData.cFileName, addr tmpbuf,0
Continue:
invoke FindNextFile,hSearch,addr Win32FindData
invoke GetLastError
jmp CheckForFiles
LeaveLoop:
invoke FindClose,hSearch
InvalidHandle:
ret
Copy_Files endp
;========================================
This proc is tested on Win95 and 98....:)
Revamped Copy_Files:
;======= How to use Copy_Files PROC ===========
;Copy_Files PROTO :DWORD, :DWORD
;.data
;FilesPattern db "*.*",0
;DestinationDir db "c:\",0
;BackSlash db "\",0
;invoke Copy_Files,addr FilesPattern,addr DestinationDir
;======= Required Data In Main File =============
.data?
FHandle dd ?
hSearch dd ?
Win32FindData WIN32_FIND_DATA<>
;========================================
Copy_Files proc Pattern:DWORD, DestFolder:DWORD
LOCAL tmpbuf:BYTE
invoke FindFirstFile,Pattern,addr Win32FindData
cmp eax,INVALID_HANDLE_VALUE
je InvalidHandle
mov hSearch,eax
CheckForFiles:
cmp eax,ERROR_NO_MORE_FILES
je LeaveLoop
invoke lstrcpy,addr tmpbuf,DestFolder
invoke lstrlen,addr tmpbuf
dec eax
lea ebx, tmpbuf
mov cl, BYTE PTR
cmp cl,05ch
je BSOK
invoke lstrcat,addr tmpbuf,addr BackSlash
BSOK:
cmp Win32FindData.dwFileAttributes,FILE_ATTRIBUTE_DIRECTORY
jne NotDir
jmp Continue
NotDir:
invoke lstrcat,ADDR tmpbuf,ADDR Win32FindData.cFileName
invoke CopyFile,addr Win32FindData.cFileName, addr tmpbuf,0
Continue:
invoke FindNextFile,hSearch,addr Win32FindData
invoke GetLastError
jmp CheckForFiles
LeaveLoop:
invoke FindClose,hSearch
InvalidHandle:
ret
Copy_Files endp
;========================================
This proc is tested on Win95 and 98....:)
I find that this proc doesn't work in Win2k, but I could not find the purpose of it :(
Thanks for the input on the win2k angle gaidar :) Perhaps someone else can contribute other information regarding OS performance. I would be very greatful.
As for the use, it is good for copying file(s) from one folder to another using filename.ext and/or wildcards while filtering out the folders.
I have not tested the speed of the proc yet, but I will be on that one soon. :grin:
As for the use, it is good for copying file(s) from one folder to another using filename.ext and/or wildcards while filtering out the folders.
I have not tested the speed of the proc yet, but I will be on that one soon. :grin:
SpEcIeS,
You can substitute:
- "invoke lstrcpy,addr tmpbuf,DestFolder
invoke lstrlen,addr tmpbuf"
with "extended" lstrlen function
from algo section
- "lea ebx, tmpbuf
mov cl, BYTE PTR
cmp cl,05ch"
with cmp byte ptr , 05Ch
- "invoke lstrcat,addr tmpbuf,addr BackSlash"
with sample mov , 05Ch
- "jne NotDir
jmp Continue" with
je Continue
- CopyFile with CopyFileEx
and use lpProgressRoutine
- "FHandle" with nothing
- "hSearch" with esi
- " cmp eax,INVALID_HANDLE_VALUE
je InvalidHandle
mov hSearch, eax " with
mov esi, eax
inc eax
je InvalidHandle
Regards,
Lingo
You can substitute:
- "invoke lstrcpy,addr tmpbuf,DestFolder
invoke lstrlen,addr tmpbuf"
with "extended" lstrlen function
from algo section
- "lea ebx, tmpbuf
mov cl, BYTE PTR
cmp cl,05ch"
with cmp byte ptr , 05Ch
- "invoke lstrcat,addr tmpbuf,addr BackSlash"
with sample mov , 05Ch
- "jne NotDir
jmp Continue" with
je Continue
- CopyFile with CopyFileEx
and use lpProgressRoutine
- "FHandle" with nothing
- "hSearch" with esi
- " cmp eax,INVALID_HANDLE_VALUE
je InvalidHandle
mov hSearch, eax " with
mov esi, eax
inc eax
je InvalidHandle
Regards,
Lingo
Thanks for the input lingo12 ;) I will get right on the modifications.
I have applied speed testings to the last two procs, old and new, and have found that the two are really not that different. I will reapply the testing once the new optimizations are in place.
Thanks again :grin:
I have applied speed testings to the last two procs, old and new, and have found that the two are really not that different. I will reapply the testing once the new optimizations are in place.
Thanks again :grin:
You won't get much speed improvement from a routine who's main bottleneck is the hardware disk IO. So don't bother optimising it for anything other than size.
iblis,
It is just an asm "literate" optimization rather than a speed optimization
If we want a speed optimization we will use additional criteria,
well formulated in A.Fog's book.
From other hand, the question "Why we use unoptimized assembly rather than C/C++"
is still in suspense, because modern C/C++ compilers have optimization options,
ml.exe hasn't. (see my first reply)
So, "the bottleneck is the hardware disk IO" is not important in our case, because it
doesn't depend on us and as a programmers we must improve our programming style
rather than be lazy.
Regards,
Lingo
It is just an asm "literate" optimization rather than a speed optimization
If we want a speed optimization we will use additional criteria,
well formulated in A.Fog's book.
From other hand, the question "Why we use unoptimized assembly rather than C/C++"
is still in suspense, because modern C/C++ compilers have optimization options,
ml.exe hasn't. (see my first reply)
So, "the bottleneck is the hardware disk IO" is not important in our case, because it
doesn't depend on us and as a programmers we must improve our programming style
rather than be lazy.
Regards,
Lingo
Huh?
I was not talking to you. I was responding to SpEcIeS' post where he said he was testing his procedure for speed. Speed is not important here. Focus on size.
That's all. ;)
I was not talking to you. I was responding to SpEcIeS' post where he said he was testing his procedure for speed. Speed is not important here. Focus on size.
That's all. ;)
I am with Iblis here, get it to work first, get it as small as you can be bothered and keep it ready to use with your asm code where you need file copy.
Having it already written in C/C++/VB/Delphi etc ... is not much use to you if your main source is in asm.
With regard to the posted code, I don't see the point of memory copy in the code when the file IO API function write to a buffer and read back from a buffer. Just allocate the buffer size from the file that has been opened, write the data to it and then read it back with WriteFile() to the location on disk.
Regards,
hutch@movsd.com
Having it already written in C/C++/VB/Delphi etc ... is not much use to you if your main source is in asm.
With regard to the posted code, I don't see the point of memory copy in the code when the file IO API function write to a buffer and read back from a buffer. Just allocate the buffer size from the file that has been opened, write the data to it and then read it back with WriteFile() to the location on disk.
Regards,
hutch@movsd.com
"...C/C++/VB/Delphi etc.. "
I'm wondering why Power Basic isn't included
Regards,
Lingo
I'm wondering why Power Basic isn't included
Regards,
Lingo
Lingo12,
"I'm wondering why Power Basic isn't included"
Probably because it cannot be used in asm either. :grin:
Regards,
hutch@movsd.com
"I'm wondering why Power Basic isn't included"
Probably because it cannot be used in asm either. :grin:
Regards,
hutch@movsd.com
Thanks for all the excellent input from all :)
I am still unclear about a few things. One of which is the line from lingo12: mov , 05Ch. I have not had any success with this, and I am really not clear how to setup CopyFileEx with lpProgressRoutine. However, the other lines of code were great and appreciated :) Perhaps someone could help me out with this CopyFileEx lpProgressRoutine issue? I have only been using the CopyFile function up to this point.
Here is the CopyFiles so far:
CopyFiles proc Pattern:DWORD, DestFolder:DWORD
LOCAL tmpbuf:BYTE
invoke FindFirstFile,Pattern,addr Win32FindData
mov esi, eax
inc eax
je InvalidHandle
CheckForFiles:
cmp eax,ERROR_NO_MORE_FILES
je LeaveLoop
invoke lstrcpy,addr tmpbuf,DestFolder
invoke lstrlen,addr tmpbuf
dec eax
cmp byte ptr ,05Ch
je BSOK
invoke lstrcat,addr tmpbuf,addr BackSlash
BSOK:
cmp Win32FindData.dwFileAttributes,FILE_ATTRIBUTE_DIRECTORY
je Continue
invoke lstrcat,addr tmpbuf,ADDR Win32FindData.cFileName
invoke CopyFile,addr Win32FindData.cFileName,addr tmpbuf,NULL
Continue:
invoke FindNextFile,esi,addr Win32FindData
invoke GetLastError
jmp CheckForFiles
LeaveLoop:
invoke FindClose,esi
InvalidHandle:
ret
CopyFiles endp
I must admit that this looks a lot better that the first example :grin:
Thanks again for all of the help.
I am still unclear about a few things. One of which is the line from lingo12: mov , 05Ch. I have not had any success with this, and I am really not clear how to setup CopyFileEx with lpProgressRoutine. However, the other lines of code were great and appreciated :) Perhaps someone could help me out with this CopyFileEx lpProgressRoutine issue? I have only been using the CopyFile function up to this point.
Here is the CopyFiles so far:
CopyFiles proc Pattern:DWORD, DestFolder:DWORD
LOCAL tmpbuf:BYTE
invoke FindFirstFile,Pattern,addr Win32FindData
mov esi, eax
inc eax
je InvalidHandle
CheckForFiles:
cmp eax,ERROR_NO_MORE_FILES
je LeaveLoop
invoke lstrcpy,addr tmpbuf,DestFolder
invoke lstrlen,addr tmpbuf
dec eax
cmp byte ptr ,05Ch
je BSOK
invoke lstrcat,addr tmpbuf,addr BackSlash
BSOK:
cmp Win32FindData.dwFileAttributes,FILE_ATTRIBUTE_DIRECTORY
je Continue
invoke lstrcat,addr tmpbuf,ADDR Win32FindData.cFileName
invoke CopyFile,addr Win32FindData.cFileName,addr tmpbuf,NULL
Continue:
invoke FindNextFile,esi,addr Win32FindData
invoke GetLastError
jmp CheckForFiles
LeaveLoop:
invoke FindClose,esi
InvalidHandle:
ret
CopyFiles endp
I must admit that this looks a lot better that the first example :grin:
Thanks again for all of the help.
lingo12,
I finally figured out the mov , 05Ch code. It took a while to sink in :rolleyes: Here is the code change to the CopyFiles proc:
invoke lstrlen,addr tmpbuf
dec eax
cmp byte ptr ,05Ch
je BSOK
inc eax
mov byte ptr,05Ch
inc eax
mov byte ptr,0
BSOK:
Thanks again for the eye opener...:grin:
I finally figured out the mov , 05Ch code. It took a while to sink in :rolleyes: Here is the code change to the CopyFiles proc:
invoke lstrlen,addr tmpbuf
dec eax
cmp byte ptr ,05Ch
je BSOK
inc eax
mov byte ptr,05Ch
inc eax
mov byte ptr,0
BSOK:
Thanks again for the eye opener...:grin:
"I must admit that this looks a lot better that the first example"
CopyFiles proc Pattern:DWORD, DestFolder:DWORD
LOCAL tmpbuf[MAX_PATH]:BYTE
; Job for you
; if destination folder exists OK, else create it
; FilesPattern must be db "c:\MyFiles\*.*", 0 rather then db "*.*",0
; change source directory to "c:\MyFiles\"
invoke FindFirstFile,Pattern,addr Win32FindData
mov esi, eax
inc eax
je InvalidHandle
invoke lstrcpy, addr tmpbuf, DestFolder
invoke lstrlen, addr tmpbuf
lea ebx, [eax+offset tmpbuf]
cmp byte ptr [ebx-1], 05Ch
je IsDir
mov byte ptr [ebx], 05Ch
inc ebx
IsDir: mov eax, Win32FindData.dwFileAttributes
and eax, FILE_ATTRIBUTE_DIRECTORY
je Continue
invoke lstrcpy, ebx, addr Win32FindData.cFileName
invoke CopyFile, addr Win32FindData.cFileName, addr tmpbuf, 0
Continue: invoke FindNextFile, esi, addr Win32FindData
test eax, eax
jne IsDir
invoke FindClose, esi
InvalidHandle: ret
CopyFiles endp
Wow, now that is nice work :)
SpEcIeS,
I meant to say thanks in the first place for posting your code for other people to use. The source code forum is a good place for code to be beaten to death and I think with Lingo's help that you have both produced a good fast piece of code.
Regards,
hutch@movsd.com
I meant to say thanks in the first place for posting your code for other people to use. The source code forum is a good place for code to be beaten to death and I think with Lingo's help that you have both produced a good fast piece of code.
Regards,
hutch@movsd.com
There is a lot of excellent feedback on this code....:)
This is where I left off after lingo's reply:
CopyFiles PROTO :DWORD,:DWORD
DirExist PROTO :DWORD
data?
Win32FindData WIN32_FIND_DATA<>
CopyFiles proc Pattern:DWORD, DestFolder:DWORD
LOCAL tmpbuf:BYTE
invoke DirExist,DestFolder
invoke FindFirstFile,Pattern,addr Win32FindData
mov esi, eax
inc eax
je InvalidHandle
CheckForFiles:
cmp eax,ERROR_NO_MORE_FILES
je LeaveLoop
invoke lstrcpy,addr tmpbuf,DestFolder
invoke StrLen,addr tmpbuf
dec eax
cmp byte ptr ,05Ch
je BSOK
inc eax
mov byte ptr,05Ch
inc eax
mov byte ptr,0
BSOK:
cmp Win32FindData.dwFileAttributes,FILE_ATTRIBUTE_DIRECTORY
je Continue
invoke lstrcat,addr tmpbuf,addr Win32FindData.cFileName
invoke CopyFile,addr Win32FindData.cFileName, addr tmpbuf,0
Continue:
invoke FindNextFile,esi,addr Win32FindData
invoke GetLastError
jmp CheckForFiles
LeaveLoop:
invoke FindClose,esi
InvalidHandle:
ret
CopyFiles endp
DirExist proc DestFolder:DWORD
;If Directory does not exist then create it
LOCAL CurDir:BYTE
invoke GetCurrentDirectory,MAX_PATH,addr CurDir
invoke SetCurrentDirectory,DestFolder
test eax,eax
jne @F
invoke CreateDirectory,DestFolder,NULL
@@:
invoke SetCurrentDirectory,addr CurDir
ret
DirExist endp
How is this? :)
This is where I left off after lingo's reply:
CopyFiles PROTO :DWORD,:DWORD
DirExist PROTO :DWORD
data?
Win32FindData WIN32_FIND_DATA<>
CopyFiles proc Pattern:DWORD, DestFolder:DWORD
LOCAL tmpbuf:BYTE
invoke DirExist,DestFolder
invoke FindFirstFile,Pattern,addr Win32FindData
mov esi, eax
inc eax
je InvalidHandle
CheckForFiles:
cmp eax,ERROR_NO_MORE_FILES
je LeaveLoop
invoke lstrcpy,addr tmpbuf,DestFolder
invoke StrLen,addr tmpbuf
dec eax
cmp byte ptr ,05Ch
je BSOK
inc eax
mov byte ptr,05Ch
inc eax
mov byte ptr,0
BSOK:
cmp Win32FindData.dwFileAttributes,FILE_ATTRIBUTE_DIRECTORY
je Continue
invoke lstrcat,addr tmpbuf,addr Win32FindData.cFileName
invoke CopyFile,addr Win32FindData.cFileName, addr tmpbuf,0
Continue:
invoke FindNextFile,esi,addr Win32FindData
invoke GetLastError
jmp CheckForFiles
LeaveLoop:
invoke FindClose,esi
InvalidHandle:
ret
CopyFiles endp
DirExist proc DestFolder:DWORD
;If Directory does not exist then create it
LOCAL CurDir:BYTE
invoke GetCurrentDirectory,MAX_PATH,addr CurDir
invoke SetCurrentDirectory,DestFolder
test eax,eax
jne @F
invoke CreateDirectory,DestFolder,NULL
@@:
invoke SetCurrentDirectory,addr CurDir
ret
DirExist endp
How is this? :)