Category : Files from Magazines
Archive   : VOL7N13.ZIP
Filename : QFN.ASM
title QFN.ASM --- qualify file name
page 55,132
;
;
; QFN.ASM -- Qualify File Name
;
; Copyright (C) 1988 Ziff Davis
; by Ray Duncan Feb. 1988
;
; Call with: DS:SI = filename address
; AX = length
;
; Returns: Carry = clear if filename OK
; DS:SI = qualified filename
; AX = length
; or
; Carry = set if bad filename
;
; Registers other than DS:SI
; and AX are preserved.
;
DGROUP group _DATA
_DATA segment word public 'DATA'
cdrive db 0 ; current drive
cpath db '\',64 dup (0) ; current directory
tbuff db 64 dup (0) ; target directory
qbuff db 'X:\' ; qualified pathname
db 64 dup (0)
fname dw ? ; filename address
flen dw ? ; filename length
_DATA ends
_TEXT segment word public 'CODE'
assume cs:_TEXT,ds:DGROUP
public qfn ; make visible to Linker
qfn proc near ; qualify file name
push bx ; save registers
push cx
push dx
push di
push es
mov flen,ax ; save length and
mov fname,si ; address of filename
mov ax,ds ; make DGROUP addressable
mov es,ax ; with ES register
; save current drive...
mov ah,19h ; fxn 19h = get drive
int 21h ; transfer to MS-DOS
mov cdrive,al ; save it
; save current directory...
; DS:SI = buffer
mov si,offset DGROUP:cpath+1
mov ah,47h ; fxn 47h = get directory
mov dl,0 ; drive = current
int 21h ; transfer to MS-DOS
; did caller specify drive?
mov di,fname ; get address of name
mov cx,flen ; get length of name
cmp cx,2 ; if drive, length must
; be >= 2 chars.
jl qfn2 ; too short, no drive
; check for drive delimiter
cmp byte ptr [di+1],':'
jne qfn2 ; no delimiter, jump
mov dl,[di] ; get ASCII drive code
or dl,20h ; fold to lower case
sub dl,'a' ; convert it to binary
mov ah,0eh ; fxn 0eh = select drive
int 21h ; transfer to MS-DOS
; get current drive to
; make sure drive selected
mov ah,19h ; fxn 19h = get current drive
int 21h ; transfer to MS-DOS
cmp dl,al ; current = requested?
je qfn1 ; jump if select succeeded
jmp qfn8 ; exit, select failed
qfn1: add di,2 ; bump pointer past drive
sub cx,2 ; and decrement length
qfn2: ; save current directory
; again for new drive...
; DS:SI = buffer
mov si,offset DGROUP:cpath+1
mov ah,47h ; fxn 47h = get directory
mov dl,0 ; drive = current
int 21h ; transfer to MS-DOS
; scan off path if any
push di ; save start of path
mov al,'\' ; path delimiter
qfn3: mov fname,di ; save path pointer
mov flen,cx ; save path length
jcxz qfn4 ; jump if none left
repne scasb ; any '\' left in path?
je qfn3 ; loop if '\' found
qfn4: pop si ; recover starting address
; of path portion
; copy path to local buffer
; and make it ASCIIZ...
mov di,offset DGROUP:tbuff
mov cx,fname ; calculate path length
sub cx,si
jz qfn6 ; jump, no path at all
cmp cx,1 ; root directory?
je qfn5 ; jump if root
dec cx ; else discard last '\'
qfn5: rep movsb ; transfer path and
xor al,al ; append null byte
stosb
; now make target directory
; the current directory...
mov dx,offset DGROUP:tbuff
mov ah,3bh ; fxn 3BH = select directory
int 21h ; transfer to MS-DOS
jc qfn8 ; jump, no such directory
qfn6: ; build up full pathname...
mov ah,19h ; get current drive
int 21h ; transfer to MS-DOS
add al,'A' ; convert binary to ASCII
mov qbuff,al ; store ASCII drive code
; get current directory
mov dl,0 ; DL = 0 for default drive
; DS:SI = buffer address
mov si,offset DGROUP:qbuff+3
mov ah,47h ; fxn 47h = get current dir
int 21h ; transfer to MS-DOS
jc qfn8 ; jump if error
; point to path component
mov di,offset DGROUP:qbuff+3
cmp byte ptr [di],0 ; is current directory
; the root directory?
je qfn7 ; yes, jump
xor al,al ; scan for null byte at
mov cx,-1 ; end of path name
repne scasb ; and append backslash
mov byte ptr [di-1],'\'
qfn7: ; now append filename
; to drive and path...
mov si,fname ; filename address
cmp byte ptr [si],'.'
je qfn8 ; exit if directory alias
mov cx,flen ; filename length
rep movsb ; copy it
; set DS:SI = address
mov si,offset DGROUP:qbuff
mov ax,di ; and AX = length of
sub ax,si ; fully qualified filename
call makelc ; fold filename to lower
; case to make it pretty
clc ; Carry = false to
; indicate success
jmp qfn9 ; jump to common exit
qfn8: ; come here if any
; error detected...
stc ; Carry = true to
; indicate error
qfn9: pushf ; save Carry flag
push ax ; save final length
; restore original directory
mov dx,offset DGROUP:cpath
mov ah,3bh ; fxn 3BH = select directory
int 21h ; transfer to MS-DOS
mov dl,cdrive ; restore original drive
mov ah,0eh ; fxn 0EH = set drive
int 21h ; transfer to MS-DOS
pop ax ; restore length
popf ; and Carry flag
pop es ; restore other affected
pop di ; registers
pop dx
pop cx
pop bx
ret ; back to caller
qfn endp
makelc proc near ; string -> lower case
; DS:SI = address
; AX = length
push bx ; save BX contents
xor bx,bx ; BX will be pointer
mlc1: ; change A-Z to a-z
cmp byte ptr [bx+si],'A'
jb mlc2
cmp byte ptr [bx+si],'Z'
ja mlc2
or byte ptr [bx+si],20h
mlc2: inc bx ; advance through string
cmp bx,ax ; done with string yet?
jne mlc1 ; no, check next char.
pop bx ; restore BX and
ret ; return to caller
makelc endp
_TEXT ends
end
Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!
This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.
But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/