This algo gets a file name from a full path by overwriting the buffer with the full path with just the file name.


; ?????????????????????????????????????????????????????????????????????????

; 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
Posted on 2003-04-02 22:49:07 by hutch--
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
Posted on 2003-04-03 01:53:48 by Jibz
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
Posted on 2003-04-03 05:17:32 by JohnFound
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
Posted on 2003-04-03 06:58:56 by hutch--

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.
Posted on 2003-04-03 07:01:35 by Starless
starless,

Its a plot, particularly as I am not a fast typist along side some people I have seen.

Regards,

hutch@movsd.com
Posted on 2003-04-03 07:47:50 by hutch--
Sorry. :stupid:
Posted on 2003-04-03 22:04:40 by JohnFound
Can i ask a question here...

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:
Posted on 2003-04-03 23:21:31 by 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
Posted on 2003-04-04 02:13:51 by hutch--

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.
Posted on 2003-04-04 03:10:29 by Maverick
What is aim speed or size?
Or maybe speed + size if size optimization doesn't harm speed?
Posted on 2003-04-04 14:13:41 by The Svin
NaN, it is shorter:


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
Posted on 2003-04-05 15:07:16 by lingo12
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 "\".


; ?????????????????????????????????????????????????????????????????????????

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
Posted on 2003-04-06 07:09:58 by hutch--
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.
Posted on 2003-04-07 01:43:56 by JohnFound
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
Posted on 2003-04-07 03:47:39 by hutch--
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
Posted on 2003-04-07 10:04:07 by stormix
: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:
Posted on 2003-04-07 16:30:02 by 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
Posted on 2003-04-07 16:52:54 by stormix
IMHO, it may be worth optimizing for speed.
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.
Posted on 2003-04-07 18:55:34 by Starless
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.
Posted on 2003-04-07 20:11:08 by bitRAKE