471 lines
13 KiB
NASM
471 lines
13 KiB
NASM
|
;***************************************
|
|||
|
;* MS-DOS Utilities *
|
|||
|
;* *
|
|||
|
;* (C) Copyright 1984,1985 by Texas *
|
|||
|
;* Instruments Incorporated. *
|
|||
|
;* All rights reserved. *
|
|||
|
;* *
|
|||
|
;* Date Written: 21 June 1984 *
|
|||
|
;* Last Modification: 9 June 1986 *
|
|||
|
;***************************************
|
|||
|
|
|||
|
MSDOS equ 021h ; MS-DOS interrupt number
|
|||
|
GETTIME equ 02Ch ; "get_time" function request id
|
|||
|
READ equ 0
|
|||
|
WRITE equ 1
|
|||
|
SELDISK equ 0EH ; select disk
|
|||
|
CURDISK equ 019H ; get the current disk
|
|||
|
SETADDR equ 01AH ; set disk transfer address
|
|||
|
CHNGDIR equ 03BH ; change the current directory
|
|||
|
CRFILE equ 03CH ; create a file
|
|||
|
OPENFILE equ 03DH ; open a file
|
|||
|
CLFILE equ 03EH ; close a file
|
|||
|
RFILE equ 03FH ; read from a file
|
|||
|
WFILE equ 040H ; write to a file
|
|||
|
DELFILE equ 041H ; delete a file function request id
|
|||
|
MOVPTR equ 042H ; move file pointer
|
|||
|
CURRDIR equ 047H ; return text of current directory
|
|||
|
FINDFILE equ 04EH ; find match file
|
|||
|
FINDNEXT equ 04FH ; step through a directory, matching files
|
|||
|
CHGNAME equ 056H ; move a directory entry
|
|||
|
|
|||
|
DGROUP group data
|
|||
|
data segment word public 'DATA'
|
|||
|
assume DS:DGROUP
|
|||
|
curdrv db 0
|
|||
|
db 3AH ; ':'
|
|||
|
db 5CH ; '\'
|
|||
|
curdir db 64 dup (0)
|
|||
|
dta db 43 dup (0)
|
|||
|
filespec db 13 dup (0)
|
|||
|
data ends
|
|||
|
|
|||
|
XGROUP group progx
|
|||
|
progx segment byte public 'PROGX'
|
|||
|
assume CS:XGROUP,DS:DGROUP
|
|||
|
;;;
|
|||
|
;;; Delete a file
|
|||
|
;;;
|
|||
|
del_arg struc
|
|||
|
dw ? ; caller's BP
|
|||
|
dd ? ; return address (long)
|
|||
|
dw ? ; original return address (short)
|
|||
|
filename dw ? ; file name
|
|||
|
del_arg ends
|
|||
|
|
|||
|
dos%del proc far
|
|||
|
push BP
|
|||
|
mov BP,SP
|
|||
|
mov DX,[BP].filename ; DX points to ASCIZ pathname
|
|||
|
mov AH,DELFILE ; delete a file
|
|||
|
int MSDOS
|
|||
|
jc del_ret
|
|||
|
xor AX,AX ; carry not set, return zero
|
|||
|
del_ret: pop BP
|
|||
|
ret
|
|||
|
dos%del endp
|
|||
|
;;;
|
|||
|
;;; Copy a file
|
|||
|
;;;
|
|||
|
copy_arg struc
|
|||
|
handle1 dw ? ; source file handle
|
|||
|
handle2 dw ? ; destination file handle
|
|||
|
copy_buf db 128 dup (0) ; temporary buffer for copy
|
|||
|
copy_BP dw ? ; caller's BP
|
|||
|
dd ? ; return address
|
|||
|
dw ? ; original return address
|
|||
|
file1 dw ? ; source file name
|
|||
|
file2 dw ? ; destination file name
|
|||
|
copy_arg ends
|
|||
|
|
|||
|
dos%copy proc far
|
|||
|
push BP
|
|||
|
sub SP,offset copy_BP ; allocate local storage
|
|||
|
mov BP,SP
|
|||
|
mov DX,[BP].file1
|
|||
|
mov AH,OPENFILE ; open a file (source)
|
|||
|
mov AL,READ ; access mode: read
|
|||
|
int MSDOS
|
|||
|
jc copy_ret ; carry set, return
|
|||
|
mov [BP].handle1,AX
|
|||
|
mov DX,[BP].file2
|
|||
|
mov CX,0 ; file attribute
|
|||
|
mov AH,CRFILE ; create a file (destination)
|
|||
|
int MSDOS
|
|||
|
jc copy_ret
|
|||
|
mov [BP].handle2,AX
|
|||
|
; copy bytes from source file to destination file
|
|||
|
copy_01: lea DX,[BP].copy_buf
|
|||
|
mov CX,128
|
|||
|
mov BX,[BP].handle1
|
|||
|
mov AH,RFILE ; read from file
|
|||
|
int MSDOS
|
|||
|
cmp AX,0 ; end of file?
|
|||
|
je copy_10 ; yes, jump
|
|||
|
mov CX,AX ; number of bytes to move
|
|||
|
lea DX,[BP].copy_buf
|
|||
|
mov BX,[BP].handle2
|
|||
|
mov AH,WFILE ; write to a file
|
|||
|
int MSDOS
|
|||
|
jmp copy_01
|
|||
|
; close source file and destination file
|
|||
|
copy_10: mov BX,[BP].handle1
|
|||
|
mov AH,CLFILE ; close a file
|
|||
|
int MSDOS
|
|||
|
mov BX,[BP].handle2
|
|||
|
mov AH,CLFILE ; close a file
|
|||
|
int MSDOS
|
|||
|
xor AX,AX
|
|||
|
copy_ret: add SP,offset copy_BP ; release local storage
|
|||
|
pop BP
|
|||
|
ret
|
|||
|
dos%copy endp
|
|||
|
;;;
|
|||
|
;;; Rename files under current directory
|
|||
|
;;;
|
|||
|
ren%mov proc near
|
|||
|
cmp byte ptr [DI],2ah ; an '*'
|
|||
|
je renmv1
|
|||
|
cmp byte ptr [DI],3fh ; a '?'
|
|||
|
je renmv1
|
|||
|
mov AL,byte ptr [DI] ; otherwise move in the new file char
|
|||
|
renmv1: mov byte ptr [BX],AL
|
|||
|
ret
|
|||
|
ren%mov endp
|
|||
|
|
|||
|
ren_arg struc
|
|||
|
ren_BP dw ? ; caller's BP
|
|||
|
dd ? ; return address
|
|||
|
dw ? ; original return address
|
|||
|
oldfile dw ? ; old file name
|
|||
|
newfile dw ? ; new file name
|
|||
|
ren_arg ends
|
|||
|
|
|||
|
dos%ren proc far
|
|||
|
push BP
|
|||
|
mov BP,SP
|
|||
|
|
|||
|
mov DX,offset DGROUP:dta
|
|||
|
mov AH,SETADDR ; set disk transfer address
|
|||
|
int MSDOS
|
|||
|
|
|||
|
mov DX,[BP].oldfile
|
|||
|
mov CX,0 ; search attribute
|
|||
|
mov AH,FINDFILE ; find match file
|
|||
|
int MSDOS
|
|||
|
jc ren_ret
|
|||
|
|
|||
|
ren_01: mov SI,offset DGROUP:dta
|
|||
|
add SI,29 ; points to filespec
|
|||
|
mov DI,[BP].newfile
|
|||
|
mov BX,offset DGROUP:filespec
|
|||
|
|
|||
|
ren_02: inc SI
|
|||
|
cmp byte ptr ES:[SI],00h ; end of the string
|
|||
|
je ren_03
|
|||
|
cmp byte ptr ES:[SI],2eh ; an '.'?
|
|||
|
je ren_03
|
|||
|
mov AL,byte ptr ES:[SI]
|
|||
|
call ren%mov
|
|||
|
inc DI
|
|||
|
inc BX
|
|||
|
cmp byte ptr [DI-1],2ah
|
|||
|
jne ren_02
|
|||
|
cmp byte ptr [SI+1],2eh ;next char a '.'?
|
|||
|
je ren_02
|
|||
|
dec DI
|
|||
|
jmp ren_02
|
|||
|
;
|
|||
|
ren_03:
|
|||
|
cmp byte ptr [DI],00h ; end of the string
|
|||
|
je ren_04
|
|||
|
cmp byte ptr [DI],3fh ; a '?'
|
|||
|
je ren_04
|
|||
|
cmp byte ptr [DI],2ah ; an '*'
|
|||
|
je ren_04
|
|||
|
cmp byte ptr [DI-1],2eh ; previous character a '.'?
|
|||
|
je ren_02
|
|||
|
mov AL,byte ptr ES:[SI-1]
|
|||
|
call ren%mov
|
|||
|
inc DI
|
|||
|
inc BX
|
|||
|
jmp ren_03
|
|||
|
;
|
|||
|
; rename the file
|
|||
|
;
|
|||
|
ren_04: mov byte ptr [BX],0
|
|||
|
mov DI,offset DGROUP:filespec
|
|||
|
mov DX,offset DGROUP:dta
|
|||
|
add DX,30
|
|||
|
mov AH,CHGNAME ; move a directory entry
|
|||
|
int MSDOS
|
|||
|
|
|||
|
mov AH,FINDNEXT ; find next match file
|
|||
|
int MSDOS
|
|||
|
jnc ren_01 ; carry not set, do next file
|
|||
|
ren_100: xor AX,AX
|
|||
|
ren_ret: pop BP
|
|||
|
ret
|
|||
|
dos%ren endp
|
|||
|
|
|||
|
;;;
|
|||
|
;;; Get the file size
|
|||
|
;;;
|
|||
|
size_arg struc
|
|||
|
dw ? ; caller's BP
|
|||
|
dd ? ; caller's return address
|
|||
|
dw ?
|
|||
|
file dw ?
|
|||
|
size_arg ends
|
|||
|
|
|||
|
dos%size proc far
|
|||
|
push BP
|
|||
|
mov BP,SP
|
|||
|
mov DX,offset DGROUP:dta
|
|||
|
mov AH,SETADDR ; set disk transfer address
|
|||
|
int MSDOS
|
|||
|
mov DX,[BP].file
|
|||
|
mov CX,0 ; search attribute
|
|||
|
mov AH,FINDFILE ; find match file
|
|||
|
int MSDOS
|
|||
|
jnc size_01
|
|||
|
xor BX,BX ; return 0 for invalid access
|
|||
|
xor AX,AX
|
|||
|
jmp size_ret
|
|||
|
size_01: mov DI,offset DGROUP:dta
|
|||
|
mov AX,word ptr [DI+28] ; high word of file size
|
|||
|
mov BX,word ptr [DI+26] ; low word of file size
|
|||
|
size_ret: pop BP
|
|||
|
ret
|
|||
|
dos%size endp
|
|||
|
;;;
|
|||
|
;;; Change the current directory
|
|||
|
;;;
|
|||
|
cd_arg struc
|
|||
|
cd_BP dw ? ; caller's BP
|
|||
|
dd ? ; caller's return address
|
|||
|
dw ?
|
|||
|
dir dw ?
|
|||
|
cd_arg ends
|
|||
|
dos%cd proc far
|
|||
|
push BP
|
|||
|
mov BP,SP
|
|||
|
mov AH,CURDISK ; current disk
|
|||
|
int MSDOS
|
|||
|
inc AL
|
|||
|
mov DL,AL ; drive number
|
|||
|
add AL,40H ; drive character
|
|||
|
mov curdrv,AL
|
|||
|
mov SI,offset DGROUP:curdir
|
|||
|
mov AH,CURRDIR ; return current directory
|
|||
|
int MSDOS
|
|||
|
mov DX,[BP].dir
|
|||
|
mov AH,CHNGDIR ; change the current directory
|
|||
|
int MSDOS
|
|||
|
mov AX,offset DGROUP:curdrv
|
|||
|
cd_ret: pop BP
|
|||
|
ret
|
|||
|
dos%cd endp
|
|||
|
;;;
|
|||
|
;;; Change the current drive
|
|||
|
;;;
|
|||
|
drv_arg struc
|
|||
|
dw ? ; caller's BP
|
|||
|
dd ? ; caller's return address
|
|||
|
dw ?
|
|||
|
drive db ?
|
|||
|
drv_arg ends
|
|||
|
dos%drv proc far
|
|||
|
push BP
|
|||
|
mov BP,SP
|
|||
|
mov DL,[BP].drive
|
|||
|
mov AH,CURDISK ; current disk
|
|||
|
int MSDOS
|
|||
|
mov [BP].drive,AL
|
|||
|
sub DL,41H ; get the drive number
|
|||
|
cmp DL,0
|
|||
|
jl drv_ret
|
|||
|
cmp DL,10 ; maximum nuber of drive?
|
|||
|
jg drv_ret
|
|||
|
mov AH,SELDISK ; select disk
|
|||
|
int MSDOS
|
|||
|
cmp DL,AL ; AL = number of drives
|
|||
|
jl drv_01
|
|||
|
mov DL,[BP].drive ; get the current disk
|
|||
|
mov AH,SELDISK ; select disk
|
|||
|
int MSDOS
|
|||
|
jmp drv_ret
|
|||
|
drv_01: xor AX,AX
|
|||
|
jmp drv_ret1
|
|||
|
drv_ret: mov AX,-1 ; error
|
|||
|
drv_ret1: pop BP
|
|||
|
ret
|
|||
|
dos%drv endp
|
|||
|
;;;
|
|||
|
;;; Move the file pointer right before EOF character and overwrite it
|
|||
|
;;; to fix the bug in open-extend-file
|
|||
|
;;;
|
|||
|
mov_arg struc
|
|||
|
m_buffer dw 0
|
|||
|
mov_BP dw ? ; caller's BP
|
|||
|
dd ? ; caller's return address
|
|||
|
dw ?
|
|||
|
fhandle dw ? ; file handle
|
|||
|
mov_arg ends
|
|||
|
|
|||
|
mov%fptr proc far
|
|||
|
push BP
|
|||
|
sub SP,offset mov_BP ; allocate for local variable
|
|||
|
mov BP,SP
|
|||
|
mov AL,2 ; move the pointer to end of file
|
|||
|
mov DX,-128 ; and with offset (one record size)
|
|||
|
mov CX,-1
|
|||
|
mov AH,MOVPTR
|
|||
|
mov BX,[BP].fhandle ; file handle
|
|||
|
int MSDOS
|
|||
|
jc mov_ret
|
|||
|
cmp DX,0 ; small file?
|
|||
|
jge mov_001
|
|||
|
mov AL,0
|
|||
|
xor CX,CX
|
|||
|
xor DX,DX
|
|||
|
mov AH,MOVPTR
|
|||
|
int MSDOS
|
|||
|
jc mov_ret
|
|||
|
mov_001: lea DX,[BP].m_buffer ; address of buffer
|
|||
|
mov_01: mov CX,1 ; read one character at a time
|
|||
|
mov AH,RFILE ; read it
|
|||
|
int MSDOS
|
|||
|
jc mov_ret
|
|||
|
mov CL,byte ptr [BP].m_buffer
|
|||
|
cmp CL,1AH ; reach eof character?
|
|||
|
je mov_05 ; yes, go overwrite it
|
|||
|
cmp AX,0 ; at eof, but no eof char?
|
|||
|
je mov_ret ; Yes, return
|
|||
|
jmp short mov_01 ; No, loop
|
|||
|
; file pointer right after the EOF character
|
|||
|
mov_05: mov AL,1 ; move the pointer to the current
|
|||
|
mov DX,-1 ; location plus offset
|
|||
|
mov CX,-1
|
|||
|
mov AH,MOVPTR
|
|||
|
int MSDOS
|
|||
|
jc mov_ret
|
|||
|
; file pointer points to EOF character
|
|||
|
mov CX,1 ; write one byte
|
|||
|
mov BX,[BP].fhandle ; file handle
|
|||
|
mov [BP].m_buffer,0
|
|||
|
lea DX,[BP].m_buffer ; address of buffer
|
|||
|
mov AH,WFILE ; write it
|
|||
|
int MSDOS
|
|||
|
jc mov_ret
|
|||
|
mov AL,1 ; move the pointer to the current
|
|||
|
mov DX,-1 ; location plus offset
|
|||
|
mov CX,DX
|
|||
|
mov AH,MOVPTR
|
|||
|
mov BX,[BP].fhandle ; file handle
|
|||
|
int MSDOS
|
|||
|
jc mov_ret
|
|||
|
xor AX,AX
|
|||
|
mov_ret: add SP,offset mov_BP ; release local storage
|
|||
|
pop BP
|
|||
|
ret
|
|||
|
mov%fptr endp
|
|||
|
progx ends
|
|||
|
|
|||
|
PGROUP group prog
|
|||
|
prog segment byte public 'PROG'
|
|||
|
assume CS:PGROUP
|
|||
|
|
|||
|
get_args struc
|
|||
|
dw ? ; caller's BP
|
|||
|
dw ? ; return address
|
|||
|
get_ary dw ? ; pointer to result array
|
|||
|
get_args ends
|
|||
|
|
|||
|
time_fmt struc ; format of data returned by get_time()
|
|||
|
tim_hour dw ? ; hour
|
|||
|
tim_min dw ? ; minute
|
|||
|
tim_sec dw ? ; seconds
|
|||
|
tim_hnds dw ? ; hundredths
|
|||
|
time_fmt ends
|
|||
|
|
|||
|
public get_time
|
|||
|
get_time proc near
|
|||
|
push BP ; save caller's BP
|
|||
|
mov BP,SP ; establish operand addressability
|
|||
|
|
|||
|
mov AH,GETTIME ; load "get_time" service call id
|
|||
|
int MSDOS ; request service from MS-DOS
|
|||
|
mov BX,[BP].get_ary ; load pointer to result array
|
|||
|
xor AX,AX ; clear AX
|
|||
|
mov AL,CH ; copy hours
|
|||
|
mov [BX].tim_hour,AX ; and store into result array
|
|||
|
mov AL,CL ; copy minutes
|
|||
|
mov [BX].tim_min,AX ; and store into result array
|
|||
|
mov AL,DH ; copy seconds
|
|||
|
mov [BX].tim_sec,AX ; and store into result array
|
|||
|
mov AL,DL ; copy hundredths
|
|||
|
mov [BX].tim_hnds,AX ; and store into result array
|
|||
|
|
|||
|
pop BP
|
|||
|
ret
|
|||
|
get_time endp
|
|||
|
;*************************************************************************
|
|||
|
; Link to Delete a file support
|
|||
|
;*************************************************************************
|
|||
|
public delete
|
|||
|
delete proc near
|
|||
|
call dos%del
|
|||
|
ret
|
|||
|
delete endp
|
|||
|
;*************************************************************************
|
|||
|
; Link to Copy a file support
|
|||
|
;*************************************************************************
|
|||
|
public copy_fil
|
|||
|
copy_fil proc near
|
|||
|
call dos%copy
|
|||
|
ret
|
|||
|
copy_fil endp
|
|||
|
;*************************************************************************
|
|||
|
; Link to Rename a file support
|
|||
|
;*************************************************************************
|
|||
|
public rename
|
|||
|
rename proc near
|
|||
|
call dos%ren
|
|||
|
ret
|
|||
|
rename endp
|
|||
|
;*************************************************************************
|
|||
|
; Link to file size support
|
|||
|
;*************************************************************************
|
|||
|
public filesize
|
|||
|
filesize proc near
|
|||
|
call dos%size
|
|||
|
ret
|
|||
|
filesize endp
|
|||
|
;*************************************************************************
|
|||
|
; Link to Change directory support
|
|||
|
;*************************************************************************
|
|||
|
public chgdir
|
|||
|
chgdir proc near
|
|||
|
call dos%cd
|
|||
|
ret
|
|||
|
chgdir endp
|
|||
|
;*************************************************************************
|
|||
|
; Link to Change drive support
|
|||
|
;*************************************************************************
|
|||
|
public chgdrv
|
|||
|
chgdrv proc near
|
|||
|
call dos%drv
|
|||
|
ret
|
|||
|
chgdrv endp
|
|||
|
;
|
|||
|
public mov_fptr
|
|||
|
mov_fptr proc near
|
|||
|
call mov%fptr
|
|||
|
ret
|
|||
|
mov_fptr endp
|
|||
|
|
|||
|
|
|||
|
prog ends
|
|||
|
end
|
|||
|
|