home *** CD-ROM | disk | FTP | other *** search
-
- Title 'Wolfware Assembler Sample Program', 'Resident Time Display'
-
- ;=============================================================================
- ; Resident Time Display
- ;
- ; 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 inactive when first
- ; installed. 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 program should be compatible with with most other programs, resident or
- ; not, but be warned that memory resident programs exist in a world of hazy
- ; definitions (i.e. they might not work even when they ought to). This utility
- ; uses about 1065 bytes of memory.
- ;
- ; For simplicity, the program assumes that there are 65535 ticks in an hour,
- ; which is not accurate, as there are actually 65543. This means that the
- ; displayed time is 8 ticks fast for each hour past midnight. The most that
- ; the clock is in error 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.
- ;
- ; RTIME does not check for graphics modes. If your computer is in graphics
- ; mode, rather than showing the time, RTIME with show a bunch of random dots.
- ; You should probably disable RTIME before going into a graphics mode.
-
- Proc Far
- Jmp Install ;skip to installation routine
-
- ;--- version number
-
- Ver_Hi Equ 1 ;ones digit of version
- Ver_Lo Equ 11 ;decimal digit of version
-
- ;================================================
- ; 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
-
- ;================================================
- ; 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
-
- ;================================================
- ; 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 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
-
- ;================================================
- ; 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
-
- ;================================================
- ; 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
-
- ;--- numbers 00 to 60, though the minutes and seconds should only reach
- ;--- 59, due to slightly inaccurate rounding, the times tend to get to 60
-
- Numbers Label Byte
- Db '00010203040506070809'
- Db '10111213141516171819'
- Db '20212223242526272829'
- Db '30313233343536373839'
- Db '40414243444546474849'
- Db '50515253545556575859'
- Db '60'
- Endp ;Number_Con
-
- ;================================================
- ; 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
-
- End Label Byte ;end of code and data, start of stack space
-
- ;================================================
- ; 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 activated!)
-
- ;--- 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 13,10
- Db '[-------------------------------------------]', 13, 10
- Db '[ Resident time display utility installed ]', 13, 10
- Db '[----------------- Ver '
- Db Ver_Hi+'0', '.', Ver_Lo/10+'0', Ver_Lo\10+'0'
- Db ' ----------------]', 13, 10
- Db '[ press ALT-1 to activate/deactivate ]', 13, 10
- Db '[-------------------------------------------]', 13, 10,'$'
- Endp ;Install
-
- Endp ;main program
-
-