This algo gets a file name from a full path by overwriting the buffer with the full path with just the file name.
Please feel free to make a faster version.
Regards,
hutch@movsd.com
; ?????????????????????????????????????????????????????????????????????????
; Overwrites the full pathname of a file with its file name
; ?????????????????????????????????????????????????????????????????????????
FileFromPath proc lppath:DWORD
mov ecx, lppath
mov edx, lppath
@@:
mov al, [ecx]
inc ecx
mov [edx], al
inc edx
cmp al, 0 ; test for zero
je @F ; exit if zero
cmp al, "\" ; test for "\"
jne @B ; jump back if not
mov edx, lppath ; else reset edx with buffer address
jmp @B ; then jump back
@@:
ret
FileFromPath endp
; ?????????????????????????????????????????????????????????????????????????
Please feel free to make a faster version.
Regards,
hutch@movsd.com
This avoids the unconditional jump at the end .. btw. if you're going for size, then lodsb and stosb are always an option ..
FileFromPath proc lppath:DWORD
mov ecx, lppath
_reset:
mov edx, lppath
@@:
mov al, [ecx]
inc ecx
cmp al, "\" ; test for "\"
je _reset ; reset if so
mov [edx], al
inc edx
cmp al, 0 ; test for zero
jne @B ; jump back if not
ret
FileFromPath endp
Little mistake correction:
FileFromPath proc lppath:DWORD
mov ecx, lppath
_reset:
[COLOR=red]mov edx, ecx[/COLOR]
@@:
mov al, [ecx]
inc ecx
cmp al, "\" ; test for "\"
je _reset ; reset if so
mov [edx], al
inc edx
cmp al, 0 ; test for zero
jne @B ; jump back if not
ret
FileFromPath endp
Jibz,
Thanks, I like the fall through with the reset, I will have to have a play with it.
John,
Unless I am reading the mod you did incorrectly, copying ecx into edx will give the wrong location into edx which with the original algo design must be reset to the buffers starting address.
Regards,
hutch@movsd.com
Thanks, I like the fall through with the reset, I will have to have a play with it.
John,
Unless I am reading the mod you did incorrectly, copying ecx into edx will give the wrong location into edx which with the original algo design must be reset to the buffers starting address.
Regards,
hutch@movsd.com
Little mistake correction:
FileFromPath proc lppath:DWORD
mov ecx, lppath
_reset:
[COLOR=red]mov edx, ecx[/COLOR]
...
ret
FileFromPath endp
Actually, your "correction" makes this function an implementation of delay() for a few msecs (depending on strlen(lppath)). :)
Duh... Why can't I type faster? :( While typing this post, hutch replied already.
starless,
Its a plot, particularly as I am not a fast typist along side some people I have seen.
Regards,
hutch@movsd.com
Its a plot, particularly as I am not a fast typist along side some people I have seen.
Regards,
hutch@movsd.com
Sorry. :stupid:
Can i ask a question here...
Why are your overwriting your buffer in the first place? Why not simply return an address:
This way, if i have a buffer with:
The return will be 0010000E. Now i have the file name's address (0010000E), and the full path (00100000) to my disposal, and in the same buffer (both will make use of the same NULL).
To me this seems better...
:NaN:
Why are your overwriting your buffer in the first place? Why not simply return an address:
FileFromPath proc lppath:DWORD
mov edx, lppath
mov ecx, edx
xor eax, eax
@@:
mov al, [edx]
inc edx
or eax, eax
jz @F
cmp eax, '\\'
jne @B
mov ecx, edx
jmp @B
@@:
mov eax, ecx
ret
FileFromPath endp
This way, if i have a buffer with:
0010000 "C:\path\files\filename.exe",0
+ =>0 2 4 6 8 A C E
The return will be 0010000E. Now i have the file name's address (0010000E), and the full path (00100000) to my disposal, and in the same buffer (both will make use of the same NULL).
To me this seems better...
:NaN:
NaN,
An interesting idea, the original was to pass an address to the algo and use it as was after, I guess it depends on which is more convenient to you to use.
Regards,
hutch@movsd.com
An interesting idea, the original was to pass an address to the algo and use it as was after, I guess it depends on which is more convenient to you to use.
Regards,
hutch@movsd.com
To me this seems better...
I second, third and fourth that. :grin:
In general, the less destructive one is, the better. We're talking about functions, after all.
What is aim speed or size?
Or maybe speed + size if size optimization doesn't harm speed?
Or maybe speed + size if size optimization doesn't harm speed?
NaN, it is shorter:
I'm wondering why to manage "\" and zero at the same loop
It will be OK if you have one "\" only, but I can't imagine someone to put
his working files in the root directory, can I?
Example: "C:\myworkingfile.exe"
Actually we have:
"C:\windows\myworkingfile.exe"
"C:\windows\system\myworkingfile.dll"
"C:\Program FIles\MyDir\myworkingfile.exe" etc.
So, if we have more "\"'s managing "\" and zero at the same loop might be slower
because we spend additional cycles for more useless "\"'s
Might be faster if we use first part of the fast strlen algo to reach zero (fast part)
and then to search back "\" (slow part)
Regards,
Lingo
FileFromPath proc lppath:DWORD
mov edx,lppath
mov ecx,5Ch ; 5Ch->ASCII of "\"
@0:
mov eax,edx
@1:
cmp [edx],cl
lea edx,[edx+1]
je @0
cmp [edx-1],ch
jne @1
ret
FileFromPath endp
I'm wondering why to manage "\" and zero at the same loop
It will be OK if you have one "\" only, but I can't imagine someone to put
his working files in the root directory, can I?
Example: "C:\myworkingfile.exe"
Actually we have:
"C:\windows\myworkingfile.exe"
"C:\windows\system\myworkingfile.dll"
"C:\Program FIles\MyDir\myworkingfile.exe" etc.
So, if we have more "\"'s managing "\" and zero at the same loop might be slower
because we spend additional cycles for more useless "\"'s
Might be faster if we use first part of the fast strlen algo to reach zero (fast part)
and then to search back "\" (slow part)
Regards,
Lingo
Thinking about the Suggestion by NaN and Maverick, here is the next version, a non destructive algo that returns the address of the beginning of the file name after the last "\".
If doe one MOV that is unneeded as its faster than using a jmp over the MOV and it starts 1 byte up from the start which does not matter in a path.
Regards,
hutch@movsd.com
; ?????????????????????????????????????????????????????????????????????????
FileFromPath2 proc lppath:DWORD
mov ecx, lppath
strt:
mov eax, ecx
@@:
inc ecx
cmp BYTE PTR [ecx], "\"
je strt
cmp BYTE PTR [ecx], 0
jne @B
inc eax
ret
FileFromPath2 endp
; ?????????????????????????????????????????????????????????????????????????
If doe one MOV that is unneeded as its faster than using a jmp over the MOV and it starts 1 byte up from the start which does not matter in a path.
Regards,
hutch@movsd.com
Yes, but what will happen if there is no "\" at all. "something.txt" is valid name (in the current directory), but this proc will return pointer to the second char of the filename.
maybe instead of "inc eax":
cmp byte ptr , "\"
jne @f
inc eax
@@:
Regards.
John,
I just tweaked the formatting as the code was not showing properly.
maybe instead of "inc eax":
cmp byte ptr , "\"
jne @f
inc eax
@@:
Regards.
John,
I just tweaked the formatting as the code was not showing properly.
John,
You are right of course but the proc was designed for stripping file names from full paths so it requires a full path.
I take your point that an algo that handles both would need to be different.
Regards,
hutch@movsd.com
You are right of course but the proc was designed for stripping file names from full paths so it requires a full path.
I take your point that an algo that handles both would need to be different.
Regards,
hutch@movsd.com
this one is small and will just return the start of the string if there are no '\\' in it
FileFromPath@4:
push edi
mov edi,[esp+4+4]
or ecx,-1
xor al,al
repnz scasb
not ecx
mov al,'\\'
std
repnz scasb
pop eax
cld
xchg eax,edi
ret 4
:grin: <lol> :grin:
Do you really need to super optomize a simple routine? Im mean, when are you ever going to get a file path long enough to see the results anyways??
However, for those who like to refine their skills, i can fully understand this. But IMHO, my origion post or hutches latter version will get the job done fine. However Hutch's version will fail if someone uses this improbable string "\filename.exe",0.
One more thing, im not an optomizing person, so i dont know 100%, but it seems to me 32bit comparisons in flat32 mode is better than 8 bit comparisons, due to pipeline issues. This is why i always load the 8 bits into a formated eax register and keep all other code applicable to 32bit registers....
:grin: :grin:
:NaN:
Do you really need to super optomize a simple routine? Im mean, when are you ever going to get a file path long enough to see the results anyways??
However, for those who like to refine their skills, i can fully understand this. But IMHO, my origion post or hutches latter version will get the job done fine. However Hutch's version will fail if someone uses this improbable string "\filename.exe",0.
One more thing, im not an optomizing person, so i dont know 100%, but it seems to me 32bit comparisons in flat32 mode is better than 8 bit comparisons, due to pipeline issues. This is why i always load the 8 bits into a formated eax register and keep all other code applicable to 32bit registers....
:grin: :grin:
:NaN:
Do you really need to super optomize a simple routine? Im mean, when are you ever going to get a file path long enough to see the results anyways??
Agreed so i tried to make mine small
IMHO, it may be worth optimizing for speed.
In essense, the function can be written in C as:
So, the libc strrchr part may be worth optimizing because it can be used as a general purpose function. In fact, if you target for 686 or later, you can make it faster by using CMOVcc, and scan lppath at most once.
29 bytes for C calling convention, 31 bytes for STDCALL.
In essense, the function can be written in C as:
char *
FileFromPath(char *lppath)
{
char * cp;
cp = strrchr(lppath,'\\\');
if (cp)
cp++;
else
cp = lppath;
return cp;
}
So, the libc strrchr part may be worth optimizing because it can be used as a general purpose function. In fact, if you target for 686 or later, you can make it faster by using CMOVcc, and scan lppath at most once.
; need .686 somewhere.
FileFromPath:
mov edx,[esp+4]
; strrchr part
xor ecx,ecx
; one may wish to put
; align 16 here for speed.
@@: mov al,[edx]
cmp al,'\\'
cmove ecx,edx
inc edx
test al,al
jne @B
lea eax,[ecx+1]
test ecx,ecx
cmove eax,[esp+4]
ret
29 bytes for C calling convention, 31 bytes for STDCALL.
fewer dependancies:
; need .686 somewhere.
FileFromPath:
mov edx, [esp+4]
; strrchr part
xor eax, eax
inc edx
; ALIGN 16
_0: cmp BYTE PTR [edx-1], "\"
cmove eax, edx
cmp BYTE PTR [edx-1], 0
lea edx, [edx+1]
jne _0
test eax, eax
cmove eax, [esp+4]
ret
...haven't tested for speed, loop is 16 bytes.