home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / assemblr / asm / wasm / rtime.asm < prev    next >
Assembly Source File  |  1987-05-05  |  15KB  |  550 lines

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