Hi ,
GetPathOnly from m32lib crashes if there's no "\" within the path/filename.
I've altered the code to process even filenames "c:test.dat" or "test.dat".
GetPathOnly proc src:DWORD, dst:DWORD
push esi
push edi
xor ecx, ecx ; zero counter
;-----------------------------------------
mov edx, ecx ; UN : edx=0 if no "\"
;-----------------------------------------
mov esi, src
mov edi, dst
@@:
mov al, [esi] ; read byte from address in esi
inc esi
inc ecx ; increment counter
cmp al, 0 ; test for zero
je gfpOut ; exit loop on zero
cmp al, "\" ; test for "\"
jne nxt2 ; jump over if not
mov edx, ecx ; store counter in ecx = last "\" offset in ecx
jmp nxt1
;-------------------------------------------
nxt2: ; UN test for ":"
cmp al, ":" ; test for "\"
jne nxt1 ; jump over if not
mov edx, ecx ; store counter in ecx = last ":" offset in ecx
;-------------------------------------------
nxt1:
mov [edi], al ; write byte to address in edi
inc edi
jmp @B
gfpOut:
add edx, dst ; add destination address to offset of last "\"
mov [edx], al ; write terminator to destination
pop edi
pop esi
ret
GetPathOnly endp
Ulli
I can't make it "crash" on my system. When no "\" is present it returns with the destination set to the first character of the source. I don't see this as a serious problem, but IMO if no path is present then the procedure should return with the first character of the destination set to zero. Your version does so if the source contains no path and no drive spec, but both versions treat the drive spec as part of the path, which in my view it properly is not.
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
include \masm32\include\masm32rt.inc
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
.data
src1 db "c:\masm32\m32lib\getpth.asm",0
src2 db "c:getpth.asm",0
src3 db "getpth.asm",0
dest db 100 dup(0)
.code
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
_GetPathOnly proc src:DWORD, dst:DWORD
push esi
push edi
xor ecx, ecx ; zero counter
;-----------------------------------------
mov edx, ecx ; UN : edx=0 if no "\"
;-----------------------------------------
mov esi, src
mov edi, dst
@@:
mov al, [esi] ; read byte from address in esi
inc esi
inc ecx ; increment counter
cmp al, 0 ; test for zero
je gfpOut ; exit loop on zero
cmp al, "\" ; test for "\"
jne nxt2 ; jump over if not
mov edx, ecx ; store counter in ecx = last "\" offset in ecx
jmp nxt1
;-------------------------------------------
nxt2: ; UN test for ":"
cmp al, ":" ; test for "\"
jne nxt1 ; jump over if not
mov edx, ecx ; store counter in ecx = last ":" offset in ecx
;-------------------------------------------
nxt1:
mov [edi], al ; write byte to address in edi
inc edi
jmp @B
gfpOut:
add edx, dst ; add destination address to offset of last "\"
mov [edx], al ; write terminator to destination
pop edi
pop esi
ret
_GetPathOnly endp
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
start:
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
invoke GetPathOnly,ADDR src1,ADDR dest
print ADDR dest,13,10
invoke _GetPathOnly,ADDR src1,ADDR dest
print ADDR dest,13,10
invoke GetPathOnly,ADDR src2,ADDR dest
print ADDR dest,13,10
invoke _GetPathOnly,ADDR src2,ADDR dest
print ADDR dest,13,10
invoke GetPathOnly,ADDR src3,ADDR dest
print ADDR dest,13,10
invoke _GetPathOnly,ADDR src3,ADDR dest
print ADDR dest,13,10
inkey "Press any key to exit..."
exit
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
end start
c:\masm32\m32lib\
c:\masm32\m32lib\
c
c:
g
Press any key to exit...
Hi Michael,
IMO EDX is set only, if there's an "/". But its always used as pointer to the terminator.
Set EDX to an arbitrary value (not 0) before calling GetPathOnly.....
Ulli
I have always had the problem with the assertion using file names like "c:test.dat" that it is not a valid path to start with without the drive designator "\"
It is documented in the help file as.
Quote
Description
GetPathOnly reads the path of a complete file path and returns the path portion in the destination buffer.
Later :
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
include \masm32\include\masm32rt.inc
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
comment * -----------------------------------------------------
Build this template with
"CONSOLE ASSEMBLE AND LINK"
----------------------------------------------------- *
.code
start:
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
call main
inkey
exit
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
main proc
LOCAL pbuf :DWORD
LOCAL pdst :DWORD
LOCAL buffer[260]:BYTE
LOCAL dstbuf[260]:BYTE
mov pbuf, ptr$(buffer)
mov pdst, ptr$(dstbuf)
chdir "\" ; set drive root
invoke GetCurrentDirectory,260,pbuf
print pbuf,13,10
invoke GetModuleFileName,NULL,pbuf,260 ; get the apps path and file name
print pbuf,13,10
invoke GetPathOnly,pbuf,pdst ; strip file name and display path.
print pdst,13,10
ret
main endp
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
end start
This outputs the following.
H:\
H:\asm3\apath\pth.exe
H:\asm3\apath\
Press any key to continue ...
Hello Hutch,
I only wanted to say, that EDX has to be initialized!
Try this
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
include \masm32\include\masm32rt.inc
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
.data
src3 db "getpth.asm",0
dest db 100 dup(0)
.code
start:
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
mov edx, 11111111
invoke GetPathOnly,ADDR src3,ADDR dest
print ADDR dest,13,10
inkey "Press any key to exit..."
exit
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
end start
and you get a GPF.
Initialize EDX, and all works fine.
Regards
Ulli
Ulli,
Thanks for the effort, the proc was originally written to handle valid paths only which always have a "\" but the mod you suggested is simple enough and does not slow the algo down so it makes sense to make it a bit more idiot proof. Here is the mod.
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
.486 ; create 32 bit code
.model flat, stdcall ; 32 bit memory model
option casemap :none ; case sensitive
.code
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
GetPathOnly proc src:DWORD, dst:DWORD
push esi
push edi
xor ecx, ecx ; zero counter
mov esi, src
mov edi, dst
xor edx, edx ; zero backslash location
@@:
mov al, [esi] ; read byte from address in esi
inc esi
inc ecx ; increment counter
cmp al, 0 ; test for zero
je gfpOut ; exit loop on zero
cmp al, "\" ; test for "\"
jne nxt1 ; jump over if not
mov edx, ecx ; store counter in ecx = last "\" offset in ecx
nxt1:
mov [edi], al ; write byte to address in edi
inc edi
jmp @B
gfpOut:
add edx, dst ; add destination address to offset of last "\"
mov [edx], al ; write terminator to destination
pop edi
pop esi
ret
GetPathOnly endp
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
end
Just for the record, a valid path may contain no '\', but a full path must. For example "c:test.dat" refers to the file test.dat in the current directory of the C drive.
Check the section on Relative Paths in MSDN: Naming a File (http://msdn2.microsoft.com/en-us/library/aa365247.aspx).