News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

FileName from Path

Started by jckl, March 15, 2006, 03:03:16 AM

Previous topic - Next topic

zooba

Quote from: jckl on March 16, 2006, 05:29:01 AM
I use the full path aswell as teh file name alone so i would need both which is why i saved the file name to a new string. Thx for all the different ideas though. This helps me go back and look at the different methods and i can learn more from this. I think i am doing pretty well for starting MASM less than 1 month ago  :U

You only need to create a new string if you intend to modify them. The string quite literally starts from where the pointer points to and ends at the first null-character. For example:

.data
    szString "This is my string", 0

.code

Main:
    ; The PrintString macro takes the address of a
    ; string and displays it on the console.

    Print OFFSET szString       ; displays "This is my string"
   
    lea   esi, szString
    Print esi                   ; displays "This is my string"

    add   esi, 5
    Print esi                   ; displays "is my string"
   
    mov   edi, OFFSET szString
    Print edi                   ; displays "This is my string"
    Print esi                   ; displays "is my string"


As you can see, after we add 5 to esi it still points to a string. If we modify the string pointed to by esi the string pointed to by edi will also be modified, since it is the same string. So as you can see, unless you plan to modify the file name without changing the full path, you can find the last backslash in the full path and from there on use that address (plus one) to use the filename.

Also, if you want to separate the path from the name, you can replace the last '\' with a null character. That way, the original pointer now points at the path without the filename (or trailing backslash) and you can store a pointer to the file name. :bg

lingo

Hi Ray, :wink
Thanks for sharing!
Here is your short code in memory:

00401677 55              push        ebp 
00401678 8B EC           mov         ebp,esp
0040167A 57              push        edi 
0040167B 8B 7D 08        mov         edi,dword ptr [ebp+8]
0040167E 33 C0           xor         eax,eax
00401680 B9 FF FF FF FF  mov         ecx,0FFFFFFFFh
00401685 F2 AE           repne scas  byte ptr [edi]
00401687 4F              dec         edi 
00401688 F7 D9           neg         ecx 
0040168A 49              dec         ecx 
0040168B B0 5C           mov         al,5Ch
0040168D FD              std             
0040168E F2 AE           repne scas  byte ptr [edi]
00401690 FC              cld             
00401691 75 01           jne         00401694
00401693 47              inc         edi 
00401694 47              inc         edi 
00401695 8B C7           mov         eax,edi
00401697 5F              pop         edi 
00401698 C9              leave           
00401699 C2 04 00        ret         4     ;total:  37 bytes


If you rewrite your code in this way it will be 6 bytes shorter...  
OPTION PROLOGUE:NONE; turn it off
OPTION EPILOGUE:NONE
NameFromPath proc src:DWORD
pop eax ; return address
pop ecx ; ecx->src
push eax
push edi
mov edi, ecx
xor eax,eax
or ecx, -1  ;mov ecx,-1 is 5 bytes long->or ecx,-1 is 3 bytes

repnz scasb
dec edi 
neg ecx 
dec ecx 
mov     al, "\"
std           
repnz scasb
cld
jne @f
inc edi
@@:
inc edi
mov eax,edi
pop edi
ret
NameFromPath endp
OPTION PROLOGUE:PROLOGUEDEF; turn back on the defaults
OPTION EPILOGUE:EPILOGUEDEF

in memory:

0040169C 58               pop         eax 
0040169D 59               pop         ecx 
0040169E 50               push        eax 
0040169F 57               push        edi 
004016A0 8B F9            mov         edi,ecx
004016A2 33 C0            xor         eax,eax
004016A4 83 C9 FF         or          ecx,0FFFFFFFFh
004016A7 F2 AE            repne scas  byte ptr [edi]
004016A9 4F               dec         edi 
004016AA F7 D9            neg         ecx 
004016AC 49               dec         ecx 
004016AD B0 5C            mov         al,5Ch
004016AF FD               std             
004016B0 F2 AE            repne scas  byte ptr [edi]
004016B2 FC               cld             
004016B3 75 01            jne         004016B6
004016B5 47               inc         edi 
004016B6 47               inc         edi 
004016B7 8B C7            mov         eax,edi
004016B9 5F               pop         edi 
004016BA C3               ret         ; total: 31 bytes


Regards,
Lingo

hutch--

hmmmm,

Quote
Hi Hutch,
So this means you do not have a problem with him calling Vortex's code Garbage?

No, I have a problem with anyone who tries to start an argument in the forum and this is why I ask members if comments get a bit heated to give it a rest and try and keep things friendly. This forum is not the Bureau of Morality and it will not be used that way by anyone.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

GregL

 
QuoteThe usage of the high level garbage is a big shame for every  ASSEMBLY programmer

lingo,

To each his own.

I prefer the high-level MASM syntax. It's easier to write, easier to read, easier to maintain and is more productive. I also don't hesitate calling C run-time functions from assembly if they fit the need. I also program in C, PowerBASIC and even C# [gasp]. You have a right to your "assembly extremist" view, but I would say that most of the people in this forum don't agree with that view.


Vortex

 :P

lingo,

You can be sure that M$'s bloated code is much more successfull than your little optimized codes, they make a lot of money with that bloated code you don't like :bdg

jckl

it may be required that my filename changes so again my solution was my best choice for my situation. The thing is i am adding files to a pff file which is kind of like a zip file. The pff file holds many other files and i do not want duplicate names so i may need to change the file name alone without changing the path when the file is added if there is already a file with that same name.

as i said thanks for all the different ideas and such, just this fits my solution the best i know of :toothy

lingo

Hi Greg, :lol

" It's easier to write, easier to read, easier to maintain and is more productive."

It is not my business, so you can use what you want...
It is just my opinion and I don't want to offend anybody with it
When I talk about garbage it is a garbage ( I proofed it)  and for it is guilty the
stupid compiler, not the high level language  programmers
On the other hand it doesn't matter who and why use functions with garbage in them;
Hutch, me , Vortex, you  or somebody else...
I will respect all the people again but the final exe file will be non "garbage" free...
Obviously this topic is ready for The Colosseum.... :lol

"..but I would say that most of the people in this forum don't agree with that view.
I don't believe that you have a right to talk from the others' people name

"I also don't hesitate calling C run-time functions from assembly if they fit the need.
I prefer to read ""I also don't hesitate calling m32lib functions  if they fit the need"..he..he.. :lol

"I also program in C, PowerBASIC and even C#
Some years ago I earned a good money with C/C++ too... :lol



Vortex,

"You can be sure that M$'s bloated code is much more successfull than your little optimized codes, they make a lot of money with that bloated code you don't like

Of course I'm sure but would you be so kind to tell me what is your connection
with others' money...It is very strange argument for me
On the other hand Intel created better C/C++ compiler with more optimized  functions and with
usage of the new registers... but it is other story

Regards,
Lingo

Vortex

I am not forced to have any connections. Also, a lot of newspapers and magazines, they are not supposed to have connections with M$ when they are talking about M$'s yearly income.

Vortex

Hutch,

Like me, Paul wanted just to support the API function to extract the file name. The individual who disassemled the API function thinks that it's bloatware. I wonder if it's allowed to post here the disassembly output of M$'s copyrighted code.

hutch--

I know all of you guys and these things are just a matter of personal choice, Lingo is probably right that a hand rolled version will be smaller and faster bit it is equally as valid to say "who cares" when its hardly a speed critical task. In fact most operating system code is well off the pace in speed terms but many use various bits of it to do the job.

I don't want to have to split this thread into bits so all I have asked is that it be kept friendly so that no-one ends up offended.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

vitsoft

Quote from: Timbo on March 15, 2006, 03:18:24 AM
That's pretty much the way to do it without using API (like you, I don't know of one either).  Walk the string backwards stuffing each character into a buffer until you hit '\' at which point you know you are finished.

It shouldn't be forgotten that D:filename.ext is a valid path, too. I always scan the string backwards until any of the folllowing character is encountered: slash, backslash, colon.

hutch--

Two things, in Windows most file name operations will fail with a path that is a drive letter and a colon followed by a file name. It was a valid path on FCB dos 1 technology but most Windows versions from 3.0 upwards require at least a backslash and with later versions, they will often handle a unix style forwards slash as well, mainly for network paths.

As far asa the technique, scanning a string backwards is a poor technique and it is easier to scan it forward and store the last location of a slash(forward or back) or a colon if there is one. If there is none of these characters it may just be a bare filename.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

jckl

well i am getting the path from the GetOpenFileName api call so i would assume it to always have a \ but i am not sure on that.