home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast2.iso / asmutil / wasm202.zip / RTIME.ASM < prev    next >
Assembly Source File  |  1986-12-25  |  16KB  |  570 lines

  1.  
  2.  Title 'Wolfware Sample Program', 'Resident Time Display'
  3.  
  4. ;===============================================;
  5. ;      Resident Time Display Version 1.10       ;
  6. ;                                               ;
  7. ; A RAM resident utility which, if active,      ;
  8. ; constantly displays the time in the the       ;
  9. ; upper right corner.  Once the utility is      ;
  10. ; installed, the time is activated or           ;
  11. ; deactivated with Alt-1 (hold down the Alt     ;
  12. ; key and type 1 on the numeric keypad, then    ;
  13. ; release the Alt key).  The program is         ;
  14. ; initially non-activated when first            ;
  15. ; installed.  Once assembled, to install, just  ;
  16. ; type:                                         ;
  17. ;                                               ;
  18. ; RTIME                                         ;
  19. ;                                               ;
  20. ; The time is updated about three times a       ;
  21. ; second, in the backround of whatever program  ;
  22. ; is presently being executed. The time         ;
  23. ; display overwrites whatever is on the screen  ;
  24. ; at that location.  The display can only be    ;
  25. ; activated or deactivated when the foreground  ;
  26. ; program does keyboard I/O via interrupt 16H.  ;
  27. ; This utility uses about 1065 bytes of         ;
  28. ; memory.                                       ;
  29. ;                                               ;
  30. ; For simplicity, the program assumes that      ;
  31. ; there are 65535 ticks in an hour, though      ;
  32. ; there are actually 65543.  This means that    ;
  33. ; the displayed time is 8 ticks fast for each   ;
  34. ; hour past midnight.  The most it is off       ;
  35. ; occurs just before midnight, when it is       ;
  36. ; 8 * 23 = 184 ticks, or about 10 seconds fast. ;
  37. ; As result of this the time actually runs to   ;
  38. ; about 24:00:10 before switching to 00:00:00.  ;
  39. ;                                               ;
  40. ; This program may not be compatible with       ;
  41. ; other RAM resident type programs.             ;
  42. ;===============================================;
  43.  
  44.  Proc Far
  45.  Jmp Install            ;skip to installation routine
  46.  
  47. ;===============================================;
  48. ;                    Equates                    ;
  49. ;===============================================;
  50.  
  51. True Equ -1             ;true flag
  52. False Equ 0             ;false flag
  53.  
  54. ;----- display location, location of first character of 8 byte string
  55.  
  56. Row Equ 1               ;row, 1 to 25
  57. Column Equ 73           ;column, 1 to 80
  58.  
  59. ;----- execution parameters
  60.  
  61. Key Equ 0001h           ;int 16H key code to activate, Alt-1
  62. Attribute Equ 70h       ;display attribute, reverse video
  63. Count_Set Equ 6         ;wait count, updated 18.2/COUNT_SET = 3/sec
  64.  
  65. ;----- BIOS data, at segment 0
  66.  
  67. Equip_Flag Equ 0410h    ;equipment word
  68. Screen_Col Equ 044ah    ;CRT columns
  69.  
  70. ;----- interrupt location, at segement 0
  71.  
  72. Keyboard Equ 58h        ;keyboard fetch, interrupt 16
  73. Timer_Tick Equ 70h      ;timer tick vector location, interrupt 1C
  74.  
  75. ;----- clock information
  76.  
  77. Timer_Low Equ 046ch     ;low word of timer, at segment 0
  78. Timer_High Equ 046eh    ;high word of timer, at segment 0
  79.  
  80. Counts_Sec Equ 18       ;counts in second
  81. Counts_Min Equ 1092     ;counts in minute
  82. Counts_Hor Equ 0ffffh   ;counts in hour
  83.  
  84. ;----- local stack size, stack just has to handle 
  85. ;----- local routines and any hardware interrupts
  86.  
  87. Stack Equ 20 + 20       ;size
  88.  
  89. ;===============================================;
  90. ;                     Int16                     ;
  91. ; Alternate interrupt 16H (keyboard I/O) to     ;
  92. ; handle normal function calls while            ;
  93. ; intercepting display activation/deactivation  ;
  94. ; commands. Check for command only if read key  ;
  95. ; or get keyboard status (functions 0 and 1).   ;
  96. ;===============================================;
  97.  
  98. Int16 Proc Far
  99.  Sti                    ;interrupts on
  100.  Pushf                  ;save entry flags
  101.  
  102. ;----- read next key
  103.  
  104.  Or Ah, Ah              ;check if read key
  105.  Jnz Nonkey             ;jump if not
  106.  
  107. I16get
  108.  Seg Cs                 ;code segment
  109.  Call Old_Int16         ;keyboard interrupt
  110.  Cmp Ax, Key            ;check scan code
  111.  Je Subkey              ;jump if activate key
  112.  Iret
  113.  
  114. ;----- activation key on read
  115.  
  116. Subkey
  117.  Call Toggle_Act        ;toggle present setting
  118.  Sub Sp, 2              ;simulate flags for interrupt call
  119.  Sub Ah, Ah             ;read next key function
  120.  Jmps I16get            ;try again
  121.  
  122. ;----- keyboard status
  123.  
  124. Nonkey
  125.  Cmp Ah, 1              ;check if keyboard status
  126.  Jne Nonstat            ;jump if not
  127.  Popf                   ;restore entry flags
  128.  
  129.  Pushf                  ;flags for interrupt call
  130.  Seg Cs                 ;code segment
  131.  Call Old_Int16         ;keyboard interrupt
  132.  Pushf
  133.  Jnz I16chksk           ;jump if key in buffer
  134.  
  135.  Popf
  136.  Ret 2                  ;throw away flags in stack on return
  137.  
  138. I16chksk
  139.  Cmp Ax, Key            ;check scan code
  140.  Je I16fact             ;jump if activate key
  141.  
  142.  Popf
  143.  Ret 2                  ;throw away flags in stack on return
  144.  
  145. ;----- activation key on status
  146.  
  147. I16fact
  148.  Sub Ah, Ah             ;get key function
  149.  Sub Sp, 2              ;simulate flags for interrupt call
  150.  Seg Cs                 ;code segment
  151.  Call Old_Int16         ;keyboard interrupt, get key
  152.  
  153.  Call Toggle_Act        ;toggle present setting
  154.  
  155.  Mov Ah, 1              ;status function
  156.  Jmps Nonkey            ;try again, flags still on stack
  157.  
  158. ;----- keyboard shift status or unknown function
  159.  
  160. Nonstat
  161.  Seg Cs                 ;code segment
  162.  Call Old_Int16         ;keyboard interrupt, (flags on stack)
  163.  Iret
  164.  Endp                   ;Int16
  165.  
  166. ;===============================================;
  167. ;                  Toggle_Act                   ;
  168. ; Toggle active setting and reset screen info.  ;
  169. ; Clears time display (sets to dashes).         ;
  170. ;===============================================;
  171.  
  172. Toggle_Act Proc Near
  173.  Seg Cs
  174.  Cmp Activated, True    ;check if on
  175.  Je Actoff              ;jump if so, turn off
  176.  
  177. ;----- activate
  178.  
  179.  Seg Cs
  180.  Mov Activated, True    ;activate
  181.  Seg Cs
  182.  Mov Counter, Count_Set ;reset counter
  183.  Jmps Screenres
  184.  
  185. ;----- deactivate
  186.  
  187. Actoff Seg Cs
  188.  Mov Activated, False   ;activate off
  189.  
  190. ;----- reset screen information and clear display
  191.  
  192. ;----- switch to local stack
  193.  
  194. Screenres Seg Cs
  195.  Mov Stack_Seg, Ss      ;save stack segment
  196.  
  197.  Seg Cs
  198.  Mov Temp, Cs
  199.  Seg Cs
  200.  Mov Ss, Temp           ;new stack segment
  201.  
  202.  Seg Cs
  203.  Mov Stack_Off, Sp      ;save stack pointer
  204.  
  205.  Seg Cs
  206.  Mov Sp, Local_Stk      ;new stack
  207.  
  208. ;----- save all registers
  209.  
  210.  Push Ax
  211.  Push Bx
  212.  Push Cx
  213.  Push Dx
  214.  Push Di
  215.  Push Si
  216.  Push Ds
  217.  Push Es
  218.  
  219.  Cld                    ;forward direction
  220.  
  221. ;----- set screen information
  222.  
  223.  Sub Ax, Ax
  224.  Mov Ds, Ax             ;segement 0
  225.  
  226.  Mov Bx, [Screen_Col]   ;screen columns
  227.  Mov Ax, 0b800h         ;graphics segment
  228.  
  229.  Mov Dx, [Equip_Flag]   ;get equipment flag
  230.  And Dx, 30h            ;mask CRT bits
  231.  Cmp Dx, 30h            ;check if BW card
  232.  Jne Notbw              ;jump if not
  233.  
  234.  Mov Ax, 0b000h         ;BW segement
  235.  
  236. Notbw Mov Dx, Cs
  237.  Mov Ds, Dx
  238.  Mov Es, Dx             ;set data segment registers
  239.  
  240.  Mov Screen_Seg, Ax     ;save segment
  241.  
  242. ;----- calculate screen offset
  243.  
  244.  Mov Ax, Bx
  245.  Sub Dx, Dx
  246.  Mul Ax, Time_Row       ;row offset
  247.  Add Ax, Time_Col       ;add for columns
  248.  Shl Ax                 ;times two, account for attribute bytes
  249.  Mov Screen_Off, Ax     ;save
  250.  
  251. ;----- clear time display (set numbers to dashes)
  252.  
  253.  Mov Ax, 2d2dh          ;dashes to clear time and date
  254.  
  255.  Cli                    ;interrupts off while display
  256.  Mov Di, Offset Tdisplay;dislay line
  257.  Stosw                  ;hours
  258.  Inc Di
  259.  Stosw                  ;minutes
  260.  Inc Di
  261.  Stosw                  ;seconds
  262.  
  263.  Call Display           ;display new string
  264.  Sti                    ;interrupts back on
  265.  
  266. ;----- restore registers
  267.  
  268.  Pop Es
  269.  Pop Ds
  270.  Pop Si
  271.  Pop Di
  272.  Pop Dx
  273.  Pop Cx
  274.  Pop Bx
  275.  Pop Ax
  276.  
  277. ;----- restore stack
  278.  
  279.  Seg Cs
  280.  Mov Sp, Stack_Off      ;stack pointer
  281.  
  282.  Seg Cs
  283.  Mov Ss, Stack_Seg      ;stack segment
  284.  Ret
  285.  Endp                   ;Toggle_Act
  286.  
  287. ;===============================================;
  288. ;                     Int1c                     ;
  289. ; Alternate interrupt 1CH (timer tick).         ;
  290. ; Executed every timer tick (about 18.2 times   ;
  291. ; a second).                                    ;
  292. ;                                               ;
  293. ; One out of COUNT_SET cycles the time is       ;
  294. ; displayed to its predetermined location, so   ;
  295. ; the time is actually updated 18.2/COUNT_SET   ;
  296. ; times per second.                             ;
  297. ;                                               ;
  298. ; Each interrupt calls the original timer tick  ;
  299. ; interrupt for the benefit of any other        ;
  300. ; routines that were using it.                  ;
  301. ;===============================================;
  302.  
  303. Int1c Proc Near
  304.  Cli                    ;interrupts off
  305.  
  306. ;----- check if activated
  307.  
  308.  Seg Cs
  309.  Cmp Activated, True    ;check if activated
  310.  Je Redischk            ;jump if so
  311.  
  312. Exit Pushf              ;flags for interrupt call
  313.  Seg Cs
  314.  Call Old_Int1c         ;call original interrupt
  315.  Iret
  316.  
  317. Redischk Seg Cs
  318.  Dec Counter            ;decrement counter
  319.  Jnz Exit               ;jump if not zero
  320.  
  321. ;----- redisplay time
  322.  
  323. ;----- switch to internal stack
  324.  
  325.  Seg Cs
  326.  Mov Activated, False    ;deactivate
  327.  
  328.  Seg Cs
  329.  Mov Stack_Seg, Ss       ;save stack segment
  330.  
  331.  Seg Cs
  332.  Mov Temp, Cs
  333.  Seg Cs
  334.  Mov Ss, Temp            ;new stack segment
  335.  
  336.  Seg Cs
  337.  Mov Stack_Off, Sp       ;save stack pointer
  338.  
  339.  Seg Cs
  340.  Mov Sp, Local_Stk       ;new stack
  341.  
  342. ;----- save all registers
  343.  
  344.  Push Ax
  345.  Push Bx
  346.  Push Cx
  347.  Push Dx
  348.  Push Di
  349.  Push Si
  350.  Push Ds
  351.  Push Es
  352.  
  353.  Cld                    ;forward direction
  354.  
  355. ;----- get time
  356.  
  357.  Sub Ax, Ax
  358.  Mov Ds, Ax             ;segment 0
  359.  
  360.  Mov Dx,[Timer_High]    ;timer high
  361.  Mov Ax,[Timer_Low]     ;timer low
  362.  
  363. ;----- set time
  364.  
  365.  Mov Bx, Cs
  366.  Mov Ds, Bx
  367.  Mov Es, Bx             ;set segment registers
  368.  
  369.  Mov Counter, Count_Set ;reset counter
  370.  
  371.  Mov Di, Offset Tdisplay ;start of time display string
  372.  
  373.  Mov Bx, Counts_Hor     ;counts/hour
  374.  Div Ax, Bx             ;divide
  375.  Call Number_Con        ;convert to ASCII and store
  376.  Inc Di                 ;skip colon
  377.  
  378.  Mov Ax, Dx             ;remainder is new dividend
  379.  Sub Dx, Dx
  380.  Mov Bx, Counts_Min     ;counts/minute
  381.  Div Ax, Bx             ;divide
  382.  Call Number_Con        ;convert to ASCII and store
  383.  Inc Di                 ;skip colon
  384.  
  385.  Mov Ax, Dx             ;remainder is new dividend
  386.  Sub Dx, Dx
  387.  Mov Bx, Counts_Sec     ;counts/second
  388.  Div Ax, Bx             ;divide
  389.  Call Number_Con        ;convert to ASCII and store
  390.  
  391.  Call Display           ;display string to screen
  392.  
  393. ;----- restore registers
  394.  
  395.  Pop Es
  396.  Pop Ds
  397.  Pop Si
  398.  Pop Di
  399.  Pop Dx
  400.  Pop Cx
  401.  Pop Bx
  402.  Pop Ax
  403.  
  404. ;----- restore stack
  405.  
  406.  Seg Cs
  407.  Mov Sp, Stack_Off       ;restore stack pointer
  408.  
  409.  Seg Cs
  410.  Mov Ss, Stack_Seg       ;restore stack segment
  411.  
  412.  Seg Cs
  413.  Mov Activated, True     ;reactivate
  414.  Jmp Exit               ;exit routine
  415.  Endp                   ;Int1c
  416.  
  417. ;===============================================;
  418. ;                  Number_Con                   ;
  419. ; Convert number in AL to two digit ASCII       ;
  420. ; string and store result to DI. Number must    ;
  421. ; be in range 0 to 99.  DI returns pointing to  ;
  422. ; byte after new string.                        ;
  423. ;===============================================;
  424.  
  425. Number_Con Proc Near
  426.  Shl Al
  427.  Sub Ah, Ah              ;AX gets relative offset
  428.  Add Ax, Offset Numbers  ;absolute offset
  429.  Mov Si, Ax
  430.  Movsw                  ;move word (two byte digits)
  431.  Ret
  432.  
  433. ;----- data, 00 to 99
  434.  
  435. Numbers Label Byte
  436.  Db '00010203040506070809'
  437.  Db '10111213141516171819'
  438.  Db '20212223242526272829'
  439.  Db '30313233343536373839'
  440.  Db '40414243444546474849'
  441.  Db '50515253545556575859'
  442.  Db '60616263646566676869'
  443.  Db '70717273747576777879'
  444.  Db '80818283848586878889'
  445.  Db '90919293949596979899'
  446.  Endp                   ;Number_Con
  447.  
  448. ;===============================================;
  449. ;                    Display                    ;
  450. ; Display the time string to the screen by      ;
  451. ; writing it directly to the screen buffer.     ;
  452. ;===============================================;
  453.  
  454. Display Proc Near
  455.  Mov Ah, Attribute       ;display attribute
  456.  Mov Cx, Offset Tdisplay_End - Offset Tdisplay ;length
  457.  Mov Di, Screen_Off      ;offset into screen
  458.  Mov Si, Offset Tdisplay ;start of time string
  459.  Mov Es, Screen_Seg      ;segment of screen
  460.  
  461. ;----- move string to screen buffer
  462.  
  463. Disloop Lodsb           ;load character
  464.  Stosw                  ;store character and attribute
  465.  Loop Disloop           ;loop CX times
  466.  Ret
  467.  Endp                   ;Display
  468.  
  469. ;===============================================;
  470. ;                     Data                      ;
  471. ;===============================================;
  472.  
  473. Activated Db False      ;activation status, initially off
  474. Counter Db ?            ;execution counter, set when activated
  475.  
  476. Time_Row Dw Row - 1     ;display row
  477. Time_Col Dw Column - 1  ;display column
  478.  
  479. Stack_Off Dw ?          ;storage for stack offset
  480. Stack_Seg Dw ?          ;storage for stack segment
  481. Local_Stk Dw Offset End + Stack ;local stack top
  482.  
  483. Screen_Off Dw ?         ;screen offset
  484. Screen_Seg Dw ?         ;screen segment
  485.  
  486. Temp Dw ?               ;temporary storage
  487.  
  488. ;----- display string
  489.  
  490. Tdisplay Label Byte     ;start of string
  491.  Db '--:--:--'
  492. Tdisplay_End Label Byte ;end of string (to calculate length)
  493.  
  494. ;----- original interrupts
  495.  
  496. Old_Int16 Label Dword
  497.  Dw ?                   ;offset
  498.  Dw ?                   ;segment
  499.  
  500. Old_Int1c Label Dword
  501.  Dw ?                   ;offset
  502.  Dw ?                   ;segment
  503.  
  504. End Label Byte          ;end of code and data, start of stack space
  505.  
  506. ;===============================================;
  507. ;                   Install                     ;
  508. ; Install the alternate interrupts.             ;
  509. ;===============================================;
  510.  
  511. Install Proc Near
  512.  
  513. ;----- install new interrupt vectors
  514.  
  515.  Mov Ax, Offset Int16   ;keyboard offset
  516.  Mov Bx, Cs             ;present segement
  517.  Mov Cx, Offset Int1c   ;timer offset
  518.  Mov Dx, Cs             ;present segement
  519.  
  520. ;----- get and save old interrupts
  521.  
  522.  Mov Ax, 3516h          ;function and interrupt 16h
  523.  Int 21h                ;execute
  524.  Mov Word Old_Int16, Bx ;offset
  525.  Mov Word Old_Int16+2, Es ;segment
  526.  
  527.  Mov Ax, 351ch          ;function and interrupt 1ch
  528.  Int 21h                ;execute
  529.  Mov Word Old_Int1c, Bx ;offset
  530.  Mov Word Old_Int1c+2, Es ;segment
  531.  
  532. ;----- set new interrupts
  533.  
  534.  Mov Ax, 2516h          ;function and interrupt 16h
  535.  Mov Dx, Offset Int16   ;keyboard offset
  536.  Int 21h                ;execute
  537.  
  538.  Mov Ax, 251ch          ;function and interrupt 1ch
  539.  Mov Dx, Offset Int1c   ;timer offset
  540.  Int 21h                ;execute (and it's off!)
  541.  
  542. ;----- display message
  543.  
  544.  Mov Dx, Offset Installm ;message location
  545.  Mov Ah, 9              ;print string function
  546.  Int 21h                ;execute
  547.  
  548. ;----- finish up
  549.  
  550.  Mov Dx, Local_Stk      ;end of interrupt, top of local stack
  551.  Mov Cl, 4
  552.  Shr Dx, Cl             ;paragraph form
  553.  Inc Dx                 ;allow for fraction of paragraph
  554.  
  555.  Mov Ax, 3100h          ;exit function (stay resident)
  556.  Int 21h                ;execute
  557.  
  558. ;----- message
  559.  
  560. Installm Db 10
  561.  Db '/-------------------------------------------\', 13, 10
  562.  Db '|  Resident time display utility installed  |', 13, 10
  563.  Db '|----------------- Ver 1.10 ----------------|', 13, 10
  564.  Db '|    press ALT-1 to activate/deactivate     |', 13, 10
  565.  Db '\-------------------------------------------/', 13, 10,'$'
  566.  Endp                   ;Install
  567.  
  568.  Endp                   ;main program
  569.  
  570.