Category : Batch File Utilities - mostly for DOS
Archive   : DAT13.ZIP
Filename : DAT.ASM

 
Output of file : DAT.ASM contained in archive : DAT13.ZIP
;--------------------------------------------------------------------------;
; Program: DAT .Asm ;
; Purpose: Displays current date and time. ;
; Notes: Compiles under TURBO Assembler, v2.0. Should work on any ;
; machine running MS-DOS, v2.xx or higher. ;
; Status: Released into the public domain. Enjoy! If you use it, ;
; let me know what you think. You don't have to send ;
; any money, just comments and suggestions. ;
; Updates: 06-Mar-90, v1.0, GAT ;
; - initial version. ;
; 13-Mar-90, v1.1, GAT ;
; - added n option to suppress final CR/LF sequence. ;
; 19-Mar-90, GAT ;
; - fixed up on-line help message. ;
; 22-Apr-90, v1.2, GAT ;
; - revised most procedures based on work with ASK. ;
; 05-May-90, GAT ;
; - fixed bug in handling of non-zero return codes. ;
; 12-Jun-90, GAT ;
; - fixed bug in conv_Int2Ascii wrt DI's final value. ;
; 08-Jul-90, GAT ;
; - added macros to push/pop registers. ;
; 28-Aug-90, v1.3a, GAT ;
; - put equates and macros in separate files. ;
; - put common routines in libs. ;
; - added equates for date/time separators. ;
;--------------------------------------------------------------------------;

;--------------------------------------------------------------------------;
; Author: George A. Theall ;
; Phone: +1 215 662 0558 ;
; SnailMail: TifaWARE ;
; 506 South 41st St., #3M ;
; Philadelphia, PA. 19104 USA ;
; E-Mail: [email protected] (Internet) ;
;--------------------------------------------------------------------------;

;--------------------------------------------------------------------------;
; D I R E C T I V E S ;
;--------------------------------------------------------------------------;
DOSSEG
MODEL tiny

IDEAL
LOCALS
JUMPS

;
; This section comes from D:\ASM\INCLUDE\Equates.Inc.
;
EOS EQU 0 ; terminates strings
BELL EQU 7
BS EQU 8
TAB EQU 9
CR EQU 13
LF EQU 10
ESCAPE EQU 27 ; nb: ESC is a TASM keyword
SPACE EQU ' '
KEY_F1 EQU 3bh
KEY_F2 EQU 3ch
KEY_F3 EQU 3dh
KEY_F4 EQU 3eh
KEY_F5 EQU 3fh
KEY_F6 EQU 40h
KEY_F7 EQU 41h
KEY_F8 EQU 42h
KEY_F9 EQU 43h
KEY_F10 EQU 44h
KEY_HOME EQU 47h
KEY_UP EQU 48h
KEY_PGUP EQU 49h
KEY_LEFT EQU 4bh
KEY_RIGHT EQU 4dh
KEY_END EQU 4fh
KEY_DOWN EQU 50h
KEY_PGDN EQU 51h
KEY_INS EQU 52h
KEY_DEL EQU 53h
KEY_C_F1 EQU 5eh
KEY_C_F2 EQU 5fh
KEY_C_F3 EQU 60h
KEY_C_F4 EQU 61h
KEY_C_F5 EQU 62h
KEY_C_F6 EQU 63h
KEY_C_F7 EQU 64h
KEY_C_F8 EQU 65h
KEY_C_F9 EQU 66h
KEY_C_F10 EQU 67h
KEY_C_LEFT EQU 73h
KEY_C_RIGHT EQU 74h
KEY_C_END EQU 75h
KEY_C_PGDN EQU 76h
KEY_C_HOME EQU 77h
KEY_C_PGUP EQU 84h
KEY_F11 EQU 85h
KEY_F12 EQU 86h
KEY_C_F11 EQU 89h
KEY_C_F12 EQU 8ah
DOS EQU 21h ; main MSDOS interrupt
STDIN EQU 0 ; standard input
STDOUT EQU 1 ; standard output
STDERR EQU 2 ; error output
STDAUX EQU 3 ; COM port
STDPRN EQU 4 ; printer

;
; This section comes from D:\ASM\INCLUDE\Macros.Inc.
;
MACRO Pop_M RegList ;; Pops registers off stack.
IRP Reg,
IFIDNI ,
popf
ELSE
pop Reg
ENDIF
ENDM
ENDM
MACRO Push_M RegList ;; Pushes registers onto stack.
IRP Reg,
IFIDNI ,
pushf
ELSE
push Reg
ENDIF
ENDM
ENDM
MACRO Zero Reg ;; Zeros any register.
xor Reg, Reg
ENDM


ERRH equ 1 ; errorlevel if help given
DATE_SEP equ '/' ; date separator
TIME_SEP equ ':' ; time separator


;--------------------------------------------------------------------------;
; C O D E S E G M E N T ;
;--------------------------------------------------------------------------;
CODESEG

ORG 80h ; commandline
LABEL CmdLen BYTE
db ?
LABEL CmdLine BYTE
db 127 dup (?)

ORG 100h ; start of .COM file
STARTUPCODE
jmp main ; skip over data and stack

;--------------------------------------------------------------------------;
; D A T A ;
;--------------------------------------------------------------------------;
LABEL ProgName BYTE
db 'dat: ', EOS
LABEL EOL BYTE
db '.', CR, LF, EOS
LABEL HelpMsg BYTE
db CR, LF
db 'TifaWARE DAT, v1.3a, ', ??Date
db ' - displays the current date and time.', CR, LF
db 'Usage: dat [-options] [msg]', CR, LF, LF
db 'Options:', CR, LF
db ' -d = display date', CR, LF
db ' -n = suppress final newline sequence', CR, LF
db ' -t = display time', CR, LF
db ' -? = display this help message', CR, LF, LF
db 'msg is an optional message to display before '
db 'the date or time.', CR, LF, EOS
LABEL Err1Msg BYTE
db 'illegal option -- '
LABEL OptCh BYTE
db ?
db EOS
LABEL TwoDigits BYTE ; space for two digits
db 2 dup (?), EOS

SwitCh db '-' ; char introducing options
HFlag db 0 ; flag for on-line help
DFlag db 0 ; flag for displaying date
NFlag db 0 ; flag for suppressing CR/LF
TFlag db 0 ; flag for displaying time
MsgLen db 0 ; length of message text
MsgTxt dw ? ; near pointer to message text
RCode db 0 ; program return code


;--------------------------------------------------------------------------;
; L O C A L S T A C K ;
;--------------------------------------------------------------------------;
db 16 dup("STACK ") ; 128 bytes for local stack
StackTop = $


;--------------------------------------------------------------------------;
; P R O C E D U R E S ;
;--------------------------------------------------------------------------;
;---- put_TwoDigits -----------------------------------------------------;
; Purpose: Displays a number between 0 and 99 on STDOUT with a leading ;
; 0 as necessary. ;
; Notes: No validity checks are done. ;
; Entry: AL = number to display. ;
; Exit: n/a ;
; Calls: utoa, putchar, fputs ;
; Changes: [TwoDigits] ;
;--------------------------------------------------------------------------;
PROC put_TwoDigits

Push_M
Zero ah
mov bx, STDOUT
mov di, OFFSET TwoDigits
call utoa ; treat it as unsigned int
cmp al, 9 ; need a leading 0?
ja SHORT @@WriteIt
mov dl, '0'
call putchar
@@WriteIt:
mov dx, di
call fputs
Pop_M

ret
ENDP put_TwoDigits


;---- skip_Spaces -------------------------------------------------------;
; Purpose: Skips past spaces in a string. ;
; Notes: Scanning stops with either a non-space *OR* CX = 0. ;
; Entry: DS:SI = start of string to scan. ;
; Exit: AL = next non-space character, ;
; CX is adjusted as necessary, ;
; DS:SI = pointer to next non-space. ;
; Calls: none ;
; Changes: AL, CX, SI ;
;--------------------------------------------------------------------------;
PROC skip_Spaces

jcxz SHORT @@Fin
@@NextCh:
lodsb
cmp al, ' '
loopz @@NextCh
jz SHORT @@Fin ; CX = 0; don't adjust

inc cx ; adjust counters if cx > 0
dec si

@@Fin:
ret
ENDP skip_Spaces


;---- get_Opt -----------------------------------------------------------;
; Purpose: Get a commandline option. ;
; Notes: none ;
; Entry: AL = option character, ;
; Exit: n/a ;
; Calls: tolower, errmsg ;
; Changes: AX, DX, ;
; [OptCh], [HFlag], [DFlag], [NFlag], [TFlag], ;
;--------------------------------------------------------------------------;
PROC get_Opt

mov [OptCh], al ; save for later
call tolower ; use only lowercase in cmp.
cmp al, 'd'
jz SHORT @@OptD
cmp al, 'n'

jz SHORT @@OptN
cmp al, 't'
jz SHORT @@OptT
cmp al, '?'
jz SHORT @@OptH
mov dx, OFFSET Err1Msg ; unrecognized option
call errmsg ; then *** DROP THRU *** to OptH

;
; Various possible options.
;
@@OptH:
mov [HFlag], 1 ; set help flag
jmp SHORT @@Fin

@@OptD:
mov [DFlag], 1 ; display date
jmp SHORT @@Fin

@@OptN:
mov [NFlag], 1 ; no final CR/LF
jmp SHORT @@Fin

@@OptT:
mov [TFlag], 1 ; display time

@@Fin:
ret
ENDP get_Opt


;---- get_Arg -----------------------------------------------------------;
; Purpose: Gets a non-option from the set of commandline arguments. ;
; Notes: Anything left on the commandline is user's message text. ;
; Entry: CX = count of characters left in commandline, ;
; DS:SI = pointer to argument to process. ;
; Exit: CX = zero ;
; DS:SI = points to CR after commandline. ;
; Calls: none ;
; Changes: CX, SI ;
; [MsgLen], [MsgTxt] ;
;--------------------------------------------------------------------------;
PROC get_Arg

mov [MsgLen], cl ; for safekeeping
mov [MsgTxt], si
add si, cx ; adjust so nothing's left
Zero cl
mov [BYTE PTR si], EOS ; finish off string

ret
ENDP get_Arg


;---- process_CmdLine ---------------------------------------------------;
; Purpose: Processes commandline arguments. ;
; Notes: A switch character by itself is ignored. ;
; No arguments whatsoever causes help flag to be set. ;
; Entry: n/a ;
; Exit: n/a ;
; Calls: skip_Spaces, get_Opt, get_Arg ;
; Changes: AX, CX, SI, ;
; DX (get_Opt), ;
; [DFlag], [TFlag], ;
; [OptCh], [NFlag] (get_Opt), ;
; [MsgLen], [MsgTxt] (get_Arg), ;
; Direction flag is cleared. ;
;--------------------------------------------------------------------------;
PROC process_CmdLine

cld ; forward, march!
Zero ch, ch
mov cl, [CmdLen] ; length of commandline
mov si, OFFSET CmdLine ; offset to start of commandline

call skip_Spaces ; check if any args supplied
or cl, cl
jnz SHORT @@ArgLoop ; yep
mov [DFlag], 1 ; nope, so display date ...
mov [TFlag], 1 ; and time
jmp SHORT @@Fin

;
; For each blank-delineated argument on the commandline...
;
@@ArgLoop:
lodsb ; next character
dec cl
cmp al, [SwitCh] ; is it the switch character?
jnz SHORT @@NonOpt ; no

;
; Isolate each option and process it. Stop when a space is reached.
;
@@OptLoop:
jcxz SHORT @@Fin ; abort if nothing left
lodsb
dec cl
cmp al, ' '
jz SHORT @@NextArg ; abort when space reached
call get_Opt
jmp @@OptLoop

;
; Process the current argument, which is *not* an option.
; Then, *drop thru* to advance to next argument.
;
@@NonOpt:
dec si ; back up one character
inc cl
call get_Arg

;
; Skip over spaces until next argument is reached.
;
@@NextArg:
call skip_Spaces
or cl, cl
jnz @@ArgLoop

@@Fin:
ret
ENDP process_CmdLine


;--------------------------------------------------------------------------;
; E N T R Y P O I N T ;
;--------------------------------------------------------------------------;
;---- main --------------------------------------------------------------;
; Purpose: Main section of program. ;
; Notes: none ;
; Entry: Arguments as desired ;
; Exit: Return code as follows: ;
; 0 => program ran successfully ;
; 1 => on-line help requested ;
; Calls: process_CmdLine, fputs, putchar, getdate, put_TwoDigits, ;
; gettime ;
; Changes: n/a ;
;--------------------------------------------------------------------------;
main:
mov sp, OFFSET StackTop ; set up local stack

;
; Process commandline arguments. If the variable HFlag is set, then
; on-line help is displayed and the program immediately terminates.
;
call process_CmdLine ; process commandline args

cmp [HFlag], 0 ; is help needed?
jz SHORT @@NoHelp ; no
mov [RCode], ERRH ; yes, so set return code
mov bx, STDERR
mov dx, OFFSET HelpMsg ; point to help message
call fputs ; display it
jmp SHORT @@Fin ; and jump to end of program

;
; Display any message from commandline then get keypress from user.
;
@@NoHelp:
mov bx, STDOUT ; everything to stdout
cmp [MsgLen], 0 ; anything to print out?
jz SHORT @@Date? ; nope
mov dx, [MsgTxt] ; display message text
call fputs
mov dl, ' ' ; and a space
call putchar

@@Date?:
cmp [DFlag], 0
jz SHORT @@Time?

call getdate
mov al, dh ; dh = month
call put_TwoDigits
mov al, dl ; dl = day
mov dl, DATE_SEP ; now we can use dl for DATE_SEP
call putchar
call put_TwoDigits
call putchar ; dl still holds DATE_SEP
mov ax, cx ; cx = year
sub ax, 1900 ; assume 20th century
call put_TwoDigits
mov dl, ' '
call putchar

@@Time?:
cmp [TFlag], 0 ; display time?
jz SHORT @@FinalEOL? ; no

call gettime
mov al, ch ; ch = hour
call put_TwoDigits
mov dl, TIME_SEP
call putchar
mov al, cl ; cl = minutes
call put_TwoDigits

@@FinalEOL?:
cmp [NFlag], 0 ; suppress final CR/LF?
jnz SHORT @@Fin ; no

mov dx, OFFSET EOL+1
call fputs

;
; Ok, let's terminate the program and exit with proper return code.
;
@@Fin:
mov al, [RCode]
mov ah, 4ch
int DOS

EVEN
;-------------------------------------------------------------------------;
; Purpose: Gets current system date, based on DOS's internal clock.
; Notes: none
; Requires: 8086-class CPU and DOS v1.0 or better.
; Entry: n/a
; Exit: AL = day of week (0 = Sunday)
; DL = day (1 to 31)
; DH = month (1 to 12)
; CX = year (1980 to 2099)
; Calls: none
; Changes: AX, CX, DX
;-------------------------------------------------------------------------;
PROC getdate

mov ah, 2ah ; MS-DOS get system date function
int DOS
ret

ENDP getdate


EVEN
;-------------------------------------------------------------------------;
; Purpose: Gets current system time, based on DOS's internal clock.
; Notes: none
; Requires: 8086-class CPU and DOS v1.0 or better.
; Entry: n/a
; Exit: CL = minutes (0 - 59)
; CH = hour (0 - 23)
; DL = hundredths of seconds (0 - 99)
; DH = seconds (0 - 59)
; Calls: none
; Changes: CX, DX
;-------------------------------------------------------------------------;
PROC gettime

push ax
mov ah, 2ch ; MS-DOS get system time function
int DOS
pop ax
ret

ENDP gettime


EVEN
;-------------------------------------------------------------------------;
; Purpose: Writes an ASCIIZ string to specified device.
; Notes: A zero-length string doesn't seem to cause problems when
; this output function is used.
; Requires: 8086-class CPU and DOS v2.0 or better.
; Entry: BX = device handle,
; DS:DX = pointer to string.
; Exit: Carry flag set if EOS wasn't found or handle is invalid.
; Calls: strlen
; Changes: none
;-------------------------------------------------------------------------;
PROC fputs

IF @DataSize EQ 0
Push_M
ELSE
Push_M
mov ax, ds
mov es, ax
ENDIF
mov di, dx
call strlen ; set CX = length of string
jc SHORT @@Fin ; abort if problem finding end
mov ah, 40h ; MS-DOS raw output function
int DOS
@@Fin:
IF @DataSize EQ 0
Pop_M
ELSE
Pop_M
ENDIF
ret

ENDP fputs


EVEN
;-------------------------------------------------------------------------;
; Purpose: Writes a character to STDOUT device.
; Notes: none
; Requires: 8086-class CPU and DOS v1.0 or better.
; Entry: DL = character to display.
; Exit: n/a
; Calls: none
; Changes: none
;-------------------------------------------------------------------------;
PROC putchar

push ax
mov ah, 2
int DOS
pop ax
ret

ENDP putchar


EVEN
;-------------------------------------------------------------------------;
; Purpose: Writes an error message to stderr.
; Notes: none
; Requires: 8086-class CPU and DOS v2.0 or better.
; Entry: DS:DX = pointer to error message.
; Exit: n/a
; Calls: fputs
; Changes: none
;-------------------------------------------------------------------------;
PROC errmsg

Push_M
push dx ; save again calling parameters
mov bx, STDERR
mov dx, OFFSET ProgName ; display program name
call fputs
pop dx ; recover calling parameters
call fputs ; display error message
mov dx, OFFSET EOL
call fputs
Pop_M
ret

ENDP errmsg


EVEN
;-------------------------------------------------------------------------;
; Purpose: Converts an *unsigned* integer in range [0, 65535] to
; an ASCIIZ string of digits.
; Notes: No checks are made to ensure storage area is big enough.
; A terminating null is added.
; Requires: 8086-class CPU.
; Entry: AX = unsigned integer value,
; ES:DI = pointer to string storage area.
; Exit: ES:DI = pointer to start of string.
; Calls: none
; Changes: DI
;-------------------------------------------------------------------------;
PROC utoa

Push_M
mov bx, 10 ; conversion factor
Zero cx ; track # digits in string

@@NewDigit: ; for each character
Zero dx ; dx:ax is dividend so make dx 0
div bx ; ax = dx:ax / 10
push dx ; dx = dx:ax mod 10
inc cl ; one more digit processed
or ax, ax ; anything left?
jnz @@NewDigit

@@NextChar: ; for each power of ten
pop ax
add al, '0'
mov [BYTE PTR di], al
inc di
loop @@NextChar
mov [BYTE PTR di], EOS ; don't forget to end it!

Pop_M
ret

ENDP utoa


EVEN
;-------------------------------------------------------------------------;
; Purpose: Converts character to lowercase.
; Notes: none
; Requires: 8086-class CPU.
; Entry: AL = character to be converted.
; Exit: AL = converted character.
; Calls: none
; Changes: AL
; flags
;-------------------------------------------------------------------------;
PROC tolower

cmp al, 'A' ; if < 'A' then done
jb SHORT @@Fin
cmp al, 'Z' ; if > 'Z' then done
ja SHORT @@Fin
or al, 20h ; make it lowercase
@@Fin:
ret

ENDP tolower


EVEN
;-------------------------------------------------------------------------;
; Purpose: Calculates length of an ASCIIZ string.
; Notes: Terminal char is _not_ included in the count.
; Requires: 8086-class CPU.
; Entry: ES:DI = pointer to string.
; Exit: CX = length of string,
; cf = 0 and zf = 1 if EOS found,
; cf = 1 and zf = 0 if EOS not found within segment.
; Calls: none
; Changes: CX,
; flags
;-------------------------------------------------------------------------;
PROC strlen

Push_M
cld ; scan forward only
mov al, EOS ; character to search for
mov cx, di ; where are we now
not cx ; what's left in segment - 1
push cx ; save char count
repne scasb
je SHORT @@Done
scasb ; test final char
dec cx ; avoids trouble with "not" below

@@Done:
pop ax ; get original count
sub cx, ax ; subtract current count
not cx ; and invert it
popf ; restore df
dec di
cmp [BYTE PTR es:di], EOS
je SHORT @@Fin ; cf = 0 if equal
stc ; set cf => error

@@Fin:
Pop_M
ret

ENDP strlen


END


  3 Responses to “Category : Batch File Utilities - mostly for DOS
Archive   : DAT13.ZIP
Filename : DAT.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/