Category : Assembly Language Source Code
Archive   : WASM201.ZIP
Filename : RTIME.ASM

 
Output of file : RTIME.ASM contained in archive : WASM201.ZIP

Title 'Wolfware Sample Program', 'Resident Time Display'

;===============================================;
; Resident Time Display Version 1.10 ;
; ;
; A RAM resident utility which, if active, ;
; constantly displays the time in the the ;
; upper right corner. Once the utility is ;
; installed, the time is activated or ;
; deactivated with Alt-1 (hold down the Alt ;
; key and type 1 on the numeric keypad, then ;
; release the Alt key). The program is ;
; initially non-activated when first ;
; installed. Once assembled, to install, just ;
; type: ;
; ;
; RTIME ;
; ;
; The time is updated about three times a ;
; second, in the backround of whatever program ;
; is presently being executed. The time ;
; display overwrites whatever is on the screen ;
; at that location. The display can only be ;
; activated or deactivated when the foreground ;
; program does keyboard I/O via interrupt 16H. ;
; This utility uses about 1065 bytes of ;
; memory. ;
; ;
; For simplicity, the program assumes that ;
; there are 65535 ticks in an hour, though ;
; there are actually 65543. This means that ;
; the displayed time is 8 ticks fast for each ;
; hour past midnight. The most it is off ;
; occurs just before midnight, when it is ;
; 8 * 23 = 184 ticks, or about 10 seconds fast. ;
; As result of this the time actually runs to ;
; about 24:00:10 before switching to 00:00:00. ;
; ;
; This program may not be compatible with ;
; other RAM resident type programs. ;
;===============================================;

Proc Far
Jmp Install ;skip to installation routine

;===============================================;
; Equates ;
;===============================================;

True Equ -1 ;true flag
False Equ 0 ;false flag

;----- display location, location of first character of 8 byte string

Row Equ 1 ;row, 1 to 25
Column Equ 73 ;column, 1 to 80

;----- execution parameters

Key Equ 0001h ;int 16H key code to activate, Alt-1
Attribute Equ 70h ;display attribute, reverse video
Count_Set Equ 6 ;wait count, updated 18.2/COUNT_SET = 3/sec

;----- BIOS data, at segment 0

Equip_Flag Equ 0410h ;equipment word
Screen_Col Equ 044ah ;CRT columns

;----- interrupt location, at segement 0

Keyboard Equ 58h ;keyboard fetch, interrupt 16
Timer_Tick Equ 70h ;timer tick vector location, interrupt 1C

;----- clock information

Timer_Low Equ 046ch ;low word of timer, at segment 0
Timer_High Equ 046eh ;high word of timer, at segment 0

Counts_Sec Equ 18 ;counts in second
Counts_Min Equ 1092 ;counts in minute
Counts_Hor Equ 0ffffh ;counts in hour

;----- local stack size, stack just has to handle
;----- local routines and any hardware interrupts

Stack Equ 20 + 20 ;size

;===============================================;
; Int16 ;
; Alternate interrupt 16H (keyboard I/O) to ;
; handle normal function calls while ;
; intercepting display activation/deactivation ;
; commands. Check for command only if read key ;
; or get keyboard status (functions 0 and 1). ;
;===============================================;

Int16 Proc Far
Sti ;interrupts on
Pushf ;save entry flags

;----- read next key

Or Ah, Ah ;check if read key
Jnz Nonkey ;jump if not

I16get
Seg Cs ;code segment
Call Old_Int16 ;keyboard interrupt
Cmp Ax, Key ;check scan code
Je Subkey ;jump if activate key
Iret

;----- activation key on read

Subkey
Call Toggle_Act ;toggle present setting
Sub Sp, 2 ;simulate flags for interrupt call
Sub Ah, Ah ;read next key function
Jmps I16get ;try again

;----- keyboard status

Nonkey
Cmp Ah, 1 ;check if keyboard status
Jne Nonstat ;jump if not
Popf ;restore entry flags

Pushf ;flags for interrupt call
Seg Cs ;code segment
Call Old_Int16 ;keyboard interrupt
Pushf
Jnz I16chksk ;jump if key in buffer

Popf
Ret 2 ;throw away flags in stack on return

I16chksk
Cmp Ax, Key ;check scan code
Je I16fact ;jump if activate key

Popf
Ret 2 ;throw away flags in stack on return

;----- activation key on status

I16fact
Sub Ah, Ah ;get key function
Sub Sp, 2 ;simulate flags for interrupt call
Seg Cs ;code segment
Call Old_Int16 ;keyboard interrupt, get key

Call Toggle_Act ;toggle present setting

Mov Ah, 1 ;status function
Jmps Nonkey ;try again, flags still on stack

;----- keyboard shift status or unknown function

Nonstat
Seg Cs ;code segment
Call Old_Int16 ;keyboard interrupt, (flags on stack)
Iret
Endp ;Int16

;===============================================;
; Toggle_Act ;
; Toggle active setting and reset screen info. ;
; Clears time display (sets to dashes). ;
;===============================================;

Toggle_Act Proc Near
Seg Cs
Cmp Activated, True ;check if on
Je Actoff ;jump if so, turn off

;----- activate

Seg Cs
Mov Activated, True ;activate
Seg Cs
Mov Counter, Count_Set ;reset counter
Jmps Screenres

;----- deactivate

Actoff Seg Cs
Mov Activated, False ;activate off

;----- reset screen information and clear display

;----- switch to local stack

Screenres Seg Cs
Mov Stack_Seg, Ss ;save stack segment

Seg Cs
Mov Temp, Cs
Seg Cs
Mov Ss, Temp ;new stack segment

Seg Cs
Mov Stack_Off, Sp ;save stack pointer

Seg Cs
Mov Sp, Local_Stk ;new stack

;----- save all registers

Push Ax
Push Bx
Push Cx
Push Dx
Push Di
Push Si
Push Ds
Push Es

Cld ;forward direction

;----- set screen information

Sub Ax, Ax
Mov Ds, Ax ;segement 0

Mov Bx, [Screen_Col] ;screen columns
Mov Ax, 0b800h ;graphics segment

Mov Dx, [Equip_Flag] ;get equipment flag
And Dx, 30h ;mask CRT bits
Cmp Dx, 30h ;check if BW card
Jne Notbw ;jump if not

Mov Ax, 0b000h ;BW segement

Notbw Mov Dx, Cs
Mov Ds, Dx
Mov Es, Dx ;set data segment registers

Mov Screen_Seg, Ax ;save segment

;----- calculate screen offset

Mov Ax, Bx
Sub Dx, Dx
Mul Ax, Time_Row ;row offset
Add Ax, Time_Col ;add for columns
Shl Ax ;times two, account for attribute bytes
Mov Screen_Off, Ax ;save

;----- clear time display (set numbers to dashes)

Mov Ax, 2d2dh ;dashes to clear time and date

Cli ;interrupts off while display
Mov Di, Offset Tdisplay;dislay line
Stosw ;hours
Inc Di
Stosw ;minutes
Inc Di
Stosw ;seconds

Call Display ;display new string
Sti ;interrupts back on

;----- restore registers

Pop Es
Pop Ds
Pop Si
Pop Di
Pop Dx
Pop Cx
Pop Bx
Pop Ax

;----- restore stack

Seg Cs
Mov Sp, Stack_Off ;stack pointer

Seg Cs
Mov Ss, Stack_Seg ;stack segment
Ret
Endp ;Toggle_Act

;===============================================;
; Int1c ;
; Alternate interrupt 1CH (timer tick). ;
; Executed every timer tick (about 18.2 times ;
; a second). ;
; ;
; One out of COUNT_SET cycles the time is ;
; displayed to its predetermined location, so ;
; the time is actually updated 18.2/COUNT_SET ;
; times per second. ;
; ;
; Each interrupt calls the original timer tick ;
; interrupt for the benefit of any other ;
; routines that were using it. ;
;===============================================;

Int1c Proc Near
Cli ;interrupts off

;----- check if activated

Seg Cs
Cmp Activated, True ;check if activated
Je Redischk ;jump if so

Exit Pushf ;flags for interrupt call
Seg Cs
Call Old_Int1c ;call original interrupt
Iret

Redischk Seg Cs
Dec Counter ;decrement counter
Jnz Exit ;jump if not zero

;----- redisplay time

;----- switch to internal stack

Seg Cs
Mov Activated, False ;deactivate

Seg Cs
Mov Stack_Seg, Ss ;save stack segment

Seg Cs
Mov Temp, Cs
Seg Cs
Mov Ss, Temp ;new stack segment

Seg Cs
Mov Stack_Off, Sp ;save stack pointer

Seg Cs
Mov Sp, Local_Stk ;new stack

;----- save all registers

Push Ax
Push Bx
Push Cx
Push Dx
Push Di
Push Si
Push Ds
Push Es

Cld ;forward direction

;----- get time

Sub Ax, Ax
Mov Ds, Ax ;segment 0

Mov Dx,[Timer_High] ;timer high
Mov Ax,[Timer_Low] ;timer low

;----- set time

Mov Bx, Cs
Mov Ds, Bx
Mov Es, Bx ;set segment registers

Mov Counter, Count_Set ;reset counter

Mov Di, Offset Tdisplay ;start of time display string

Mov Bx, Counts_Hor ;counts/hour
Div Ax, Bx ;divide
Call Number_Con ;convert to ASCII and store
Inc Di ;skip colon

Mov Ax, Dx ;remainder is new dividend
Sub Dx, Dx
Mov Bx, Counts_Min ;counts/minute
Div Ax, Bx ;divide
Call Number_Con ;convert to ASCII and store
Inc Di ;skip colon

Mov Ax, Dx ;remainder is new dividend
Sub Dx, Dx
Mov Bx, Counts_Sec ;counts/second
Div Ax, Bx ;divide
Call Number_Con ;convert to ASCII and store

Call Display ;display string to screen

;----- restore registers

Pop Es
Pop Ds
Pop Si
Pop Di
Pop Dx
Pop Cx
Pop Bx
Pop Ax

;----- restore stack

Seg Cs
Mov Sp, Stack_Off ;restore stack pointer

Seg Cs
Mov Ss, Stack_Seg ;restore stack segment

Seg Cs
Mov Activated, True ;reactivate
Jmp Exit ;exit routine
Endp ;Int1c

;===============================================;
; Number_Con ;
; Convert number in AL to two digit ASCII ;
; string and store result to DI. Number must ;
; be in range 0 to 99. DI returns pointing to ;
; byte after new string. ;
;===============================================;

Number_Con Proc Near
Shl Al
Sub Ah, Ah ;AX gets relative offset
Add Ax, Offset Numbers ;absolute offset
Mov Si, Ax
Movsw ;move word (two byte digits)
Ret

;----- data, 00 to 99

Numbers Label Byte
Db '00010203040506070809'
Db '10111213141516171819'
Db '20212223242526272829'
Db '30313233343536373839'
Db '40414243444546474849'
Db '50515253545556575859'
Db '60616263646566676869'
Db '70717273747576777879'
Db '80818283848586878889'
Db '90919293949596979899'
Endp ;Number_Con

;===============================================;
; Display ;
; Display the time string to the screen by ;
; writing it directly to the screen buffer. ;
;===============================================;

Display Proc Near
Mov Ah, Attribute ;display attribute
Mov Cx, Offset Tdisplay_End - Offset Tdisplay ;length
Mov Di, Screen_Off ;offset into screen
Mov Si, Offset Tdisplay ;start of time string
Mov Es, Screen_Seg ;segment of screen

;----- move string to screen buffer

Disloop Lodsb ;load character
Stosw ;store character and attribute
Loop Disloop ;loop CX times
Ret
Endp ;Display

;===============================================;
; Data ;
;===============================================;

Activated Db False ;activation status, initially off
Counter Db ? ;execution counter, set when activated

Time_Row Dw Row - 1 ;display row
Time_Col Dw Column - 1 ;display column

Stack_Off Dw ? ;storage for stack offset
Stack_Seg Dw ? ;storage for stack segment
Local_Stk Dw Offset End + Stack ;local stack top

Screen_Off Dw ? ;screen offset
Screen_Seg Dw ? ;screen segment

Temp Dw ? ;temporary storage

;----- display string

Tdisplay Label Byte ;start of string
Db '--:--:--'
Tdisplay_End Label Byte ;end of string (to calculate length)

;----- original interrupts

Old_Int16 Label Dword
Dw ? ;offset
Dw ? ;segment

Old_Int1c Label Dword
Dw ? ;offset
Dw ? ;segment

End Label Byte ;end of code and data, start of stack space

;===============================================;
; Install ;
; Install the alternate interrupts. ;
;===============================================;

Install Proc Near

;----- install new interrupt vectors

Mov Ax, Offset Int16 ;keyboard offset
Mov Bx, Cs ;present segement
Mov Cx, Offset Int1c ;timer offset
Mov Dx, Cs ;present segement

;----- get and save old interrupts

Mov Ax, 3516h ;function and interrupt 16h
Int 21h ;execute
Mov Word Old_Int16, Bx ;offset
Mov Word Old_Int16+2, Es ;segment

Mov Ax, 351ch ;function and interrupt 1ch
Int 21h ;execute
Mov Word Old_Int1c, Bx ;offset
Mov Word Old_Int1c+2, Es ;segment

;----- set new interrupts

Mov Ax, 2516h ;function and interrupt 16h
Mov Dx, Offset Int16 ;keyboard offset
Int 21h ;execute

Mov Ax, 251ch ;function and interrupt 1ch
Mov Dx, Offset Int1c ;timer offset
Int 21h ;execute (and it's off!)

;----- display message

Mov Dx, Offset Installm ;message location
Mov Ah, 9 ;print string function
Int 21h ;execute

;----- finish up

Mov Dx, Local_Stk ;end of interrupt, top of local stack
Mov Cl, 4
Shr Dx, Cl ;paragraph form
Inc Dx ;allow for fraction of paragraph

Mov Ax, 3100h ;exit function (stay resident)
Int 21h ;execute

;----- message

Installm Db 10
Db '/-------------------------------------------\', 13, 10
Db '| Resident time display utility installed |', 13, 10
Db '|----------------- Ver 1.10 ----------------|', 13, 10
Db '| press ALT-1 to activate/deactivate |', 13, 10
Db '\-------------------------------------------/', 13, 10,'$'
Endp ;Install

Endp ;main program



  3 Responses to “Category : Assembly Language Source Code
Archive   : WASM201.ZIP
Filename : RTIME.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/