Category : Files from Magazines
Archive   : VOL7N13.ZIP
Filename : QFN.ASM

 
Output of file : QFN.ASM contained in archive : VOL7N13.ZIP
name qfn
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


  3 Responses to “Category : Files from Magazines
Archive   : VOL7N13.ZIP
Filename : QFN.ASM

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. 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/