home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 15 / CDACTUAL15.iso / cdactual / program / asm / MISC_ASM.ZIP / CLOK4.ASM < prev    next >
Encoding:
Assembly Source File  |  1988-03-03  |  25.2 KB  |  610 lines

  1. ; RESIDENT TIME CLOCK DISPLAY with optional chime
  2. ;
  3. ;       Original author unidentified
  4. ;
  5. ;       Revised by Thomas A. Lundin
  6. ;                  Graphics Unlimited Inc.
  7. ;                  3000 Second St. No.
  8. ;                  Minneapolis, MN 55411
  9. ;                  (612) 588-7571
  10. ;
  11. ; usage: clok [/c /d /x /r]
  12. ;              /c to toggle chiming. No chimes by default.
  13. ;              /d to suppress display, but allow chimes to sound
  14. ;              /x to deactivate program
  15. ;              /r for reverse video toggle
  16. ;
  17. ; Clock display can be toggled on and off by repeating 'clok'.
  18. ;
  19. ;     The clock sould be deactivated when using heavy interrupt-driven
  20. ;     software such as communications to avoid losing characters or
  21. ;     hanging the system.
  22. ;
  23. ; 9/4/87 note:
  24. ;        This version uses the clock tick to regulate the duration of the
  25. ;        chimes, meaning that the chimes should be the same length from
  26. ;        one system to another, no matter what the CPU speed.
  27. ;        Also modified start-up routines to automatically set the time
  28. ;        display background to color or monochrome.
  29. ;
  30. ; 9/21/87 note:
  31. ;        This version alterates a date display with the time display, every
  32. ;        1.5 seconds.  The date display is static, i.e., it is not updated
  33. ;        at midnight (it would be inefficient to check every hour for an 
  34. ;        event which occurs once every 24 hours).
  35. ;        Typing clok anytime again at the command line will update the date.
  36. ;
  37. ; 3/2/88 note:
  38. ;        This version adds an option to deactivate the display, but to
  39. ;        allow the chimes to sound. This is handy if you want an audible
  40. ;        reminder of the time once in a while without burning out your
  41. ;        screen. Also made some alts to option calling conventions. Added
  42. ;        reverse video toggle.
  43. ;
  44.  
  45. TICKS   EQU     27              ; number of ticks between updates (1.5 sec)
  46. BEEPS   EQU     6               ; duration of beeps in clock ticks
  47. TONE1   EQU     7f1h            ; first chime tone
  48. TONE2   EQU     54ch            ; second chime tone
  49. TONE3   EQU     3f7h            ; third chime tone
  50.  
  51. interrupts segment at 0h
  52.           org      1ch*4          ; This is to use INT 1Ch
  53. timer_int label    dword          ; which is the timer interupt
  54. interrupts ends
  55.  
  56. screen    segment at 0b000h       ; A dummy segment to use
  57. screen    ends                    ; as the Extra Segment
  58.  
  59. code_seg  segment
  60.           assume   cs:code_seg
  61.           org      100h           ; org = 100 to make this into
  62.                                   ; a .COM file
  63. first:    jmp      load_clock
  64.  
  65. old_time_int dd    ?              ; The address INT 1Ch normally uses
  66. count500  dw       TICKS          ; Used to update clock every nnn counts
  67. beepticks dw       0              ; number of ticks for a BEEP
  68. beepsleft db       0              ; number of beeps to output
  69. cursor    dw       0              ; Location of the cursor on the screen
  70. beept     db       0              ; have-we-beeped flag
  71. inbeep    db       0              ; beep-in-progress flag
  72. flash     db       1              ; flashing colon flag
  73. spkrstat  db       0              ; old speaker status
  74. video_port         dw   ?         ; Video status port - check for scanning
  75.  
  76. hh        dw       0              ; hours
  77. mm        dw       0              ; minutes
  78. sc        dw       0              ; seconds
  79. hhdiv     dw       32771          ; hours divisor (65543/2)
  80. mmdiv     dw       546            ; minutes divisor (1092/2)
  81. ssdiv     dw       9              ; second divisor (18/2)
  82.  
  83. display   dw            (7020h)   ; leading space
  84.           dw       5 dup(703ah)   ; Initial value for the clock
  85.           dw       2 dup(7020h)   ; Add 2 ' 's for am/pm.
  86.  
  87. chim_only dw       0                 ; chimes on, display off
  88. day_of_wk dw       0                 ; day of the week
  89. month     dw       0                 ; month
  90. day       dw       0                 ; day
  91. chimon    dw       0                 ; flag for chime in use or not
  92. clokon    dw       1                 ; flag for clok in use or not
  93.  
  94. clock     proc     near           ; The timer INT will now come here
  95.  
  96.           cmp      cs:clokon,1    ; is this interrupt silent ?
  97.           jz       newint         ; no, go execute it
  98.           jmp      dword ptr old_time_int ; silent, just execute old int
  99. newint:
  100.           pushf                   ; First call old time interrupt to update count
  101.           call     dword ptr old_time_int
  102.  
  103.           call     needbeep       ; need to continue beep ?
  104.           dec      cs:count500    ; should recalculate the time ?
  105.           jnz      dont_recalculate
  106.  
  107.           push     ax             ; Save the registers - good form
  108.           push     cx
  109.           push     di
  110.           push     si
  111.           push     es
  112.  
  113.           xor      cs:flash,1     ; toggle the flashing colon
  114.           call     calc           ; Recalculate the time
  115.           mov      cs:count500,TICKS  ; Reset Count500
  116.  
  117.           cmp      cs:chim_only,1 ; need beep only?
  118.           jz       disp_exit      ; yes
  119. ;;dont_recalculate:
  120.           assume   es:screen      ; Set up screen as the Extra Segment
  121.           mov      cx,screen
  122.           mov      es,cx
  123.           mov      dx,video_port  ; This is the screen status port
  124.           mov      di,cursor      ; Set up cursor on screen as destination
  125.           lea      si,display     ; Set up the display in memory as source
  126.           mov      cx,16          ; To move char and attributes
  127.  
  128. scan_low:                         ; Start waiting for a new horizontal scan
  129.           in       al,dx          ; i.e. the the vidio controller scan
  130.           test     al,1           ; status is low.
  131.           jnz      scan_low
  132.  
  133.           mov      ah,cs:[si]     ; Move byte to be written into AH
  134.  
  135. scan_high:                        ; After port has gone low, it must go high
  136.           in       al,dx          ; before it is safe to write directly
  137.           test     al,1           ; to the screen buffer in memory
  138.           jz       scan_high
  139.  
  140.           mov      es:[di],ah     ; Move to screen one byte at a time.
  141.           inc      di             ; Position to attribute byte
  142.           inc      si             ; on screen.
  143.  
  144.           loop     scan_low       ; Go back foe next byte
  145. disp_exit:
  146.           pop      es             ; Here are required pops to exit
  147.           pop      si
  148.           pop      di
  149.           pop      cx
  150.           pop      ax
  151.  
  152. dont_recalculate:
  153.           iret                    ; An interrupt needs an IRET
  154.  
  155. clock     endp
  156.  
  157. calc      proc near               ; Here we recalculate the time and store it
  158.           push     ax             ; Puushes to save everytheing that
  159.           push     bx             ; gets destroyed
  160.           push     cx
  161.           push     dx
  162.  
  163.          cmp      cs:flash,1                 ; do date or time?
  164.          jz       dtime                      ; TIME
  165.                                              ; DATE
  166.  
  167.          lea      bx,display     ; Set up BX as pointer to display in memory
  168.          mov      ax,cs:month
  169.          mov      cs:[bx+0],ah   ; Move first month digit into display
  170.          mov      cs:[bx+2],al   ; Then the second digit
  171.          mov      byte ptr cs:[bx+4],'-'  ; a hyphen
  172.          mov      ax,cs:day      ; get day
  173.          mov      cs:[bx+6],ah   ; and move them into the display in memory
  174.          mov      cs:[bx+8],al
  175.          mov      byte ptr cs:[bx+10],' ' ; move space into display
  176.          mov      ax,cs:day_of_wk
  177.          mov      cs:[bx+12],ah  ; move day of the week into display
  178.          mov      cs:[bx+14],al
  179.          jmp      restore
  180.  
  181. dtime:
  182. ; note: Peter Norton p.223 explains that the time formula is more precisely
  183. ; shown as:
  184. ;       hh = clkcount / 65543
  185. ;       mm = hh.remainder / 1092
  186. ;       ss = mm.remainder / 18
  187. ;
  188. ; trouble is, the 65543 value won't work as a single-word divisor,
  189. ; so our trick is to divide the clock count and divisor values in half,
  190. ; which should have no appreciable affect on the accuracy of the time.
  191.  
  192.           xor      ax,ax          ; Set up for clock read.
  193.           INT      1Ah            ; Read the clock.
  194.           mov      bx,dx          ; Save low(minutes) portion.
  195.           mov      dx,cx          ; Move high(hours) portion to AX.
  196.           mov      ax,bx          ; dx:ax = clock count
  197.  
  198.           clc
  199.           rcr      dx,1             ; div count by 2 so we can use a
  200.           rcr      ax,1             ; single precision dividend
  201.  
  202.           div      cs:hhdiv         ; compute hours
  203.           mov      cs:hh,ax         ; save it
  204.           mov      ax,dx            ; prepare remainder for minutes
  205.           xor      dx,dx
  206.           div      cs:mmdiv         ; compute minutes
  207.  
  208.           cmp      ax,60            ; 60 minutes shows up sometimes
  209.           jl       mm_ok            ; mostly it doesn't
  210.           xor      ax,ax            ; but if it does, zero out the minutes
  211.           inc      cs:hh            ; and bump up the hour
  212.  
  213. mm_ok:    mov      cs:mm,ax         ; save it
  214. ;         mov      ax,dx            ; prepare remainder for seconds
  215. ;         xor      dx,dx
  216. ;         div      cs:ssdiv         ; compute seconds
  217. ;         mov      cs:sc,ax         ; save it
  218.  
  219.           lea      bx,display     ; Set up BX as pointer to display in memory
  220.  
  221.           mov      byte ptr cs:[bx],' '    ; blank out first and last positions
  222.           mov      byte ptr cs:[bx+14],' '
  223.           mov      ax,cs:hh
  224.           cmp      ax,12          ; is it am or pm?
  225.           jl       am             ; am
  226. pm:       mov      byte ptr cs:[bx+12],'p' ; Otherwise move 'P' into the display.
  227.           sub      ax,12          ; pm, subtract 12
  228.           jmp      chek12         ; Continue.
  229.  
  230. am:       mov      byte ptr cs:[bx+12],'a' ; Move an 'A' into the display.
  231. chek12:   or       ax,ax          ; Make zero hour...
  232.           jnz      am_pm_done
  233.           mov      ax,12          ; ...a twelve
  234. am_pm_done:
  235.           aam                     ; Convert AX to BCD - a nice command
  236.           add      ax,3030h       ; Add '0' to both bytes in AX to make ASCII
  237.           cmp      ah,'0'         ; Is the 1st digit '0'?
  238.           jne      dont_edit      ; Then don't blank the character.
  239.           mov      ah,' '         ; Otherwise, put a space in AH.
  240. dont_edit:
  241.           mov      cs:[bx+2],ah   ; Move first hours digit into display
  242.           mov      cs:[bx+4],al   ; Then the second digit
  243. ;----------------------------------
  244.           mov      byte ptr cs:[bx+6],':'     ; in which case use a colon
  245.           mov      ax,cs:mm       ; get minutes
  246.           aam                     ; Again convert AX to Binary Coded Decimal
  247.           add      ax,3030h       ; Add to make two ASCII characters
  248.           mov      cs:[bx+8],ah   ; and move them into the display in memory
  249.           mov      cs:[bx+10],al
  250.  
  251. ;---------routine for alarm chime goes here------------------------------------
  252.         cmp     cs:chimon,0             ; chimes off?
  253.         jz      restore                 ; yes, don't beep
  254.         cmp     cs:inbeep,1             ; already in a beep loop?
  255.         jz      restore                 ; yes, don't be redundant
  256.  
  257.         cmp     ax,3030h                ; on the hour
  258.         jz      alarm3
  259.         cmp     ax,3135h                ; on the 1/4 hour
  260.         jz      alarm1
  261.         cmp     ax,3330h                ; on the 1/2 hour
  262.         jz      alarm2
  263.         cmp     ax,3435h                ; on the 3/4 hour
  264.         jz      alarm1
  265.         mov     cs:beept,0              ; we have not beeped
  266. ;------------------------------------------------------------------------------
  267. restore:                                  ; Restore registers
  268.           pop      dx
  269.           pop      cx
  270. imret2:   pop      bx
  271. imret1:   pop      ax
  272.  
  273. imret:    ret
  274. ;-----------------------------------------------------------------------------
  275. needbeep:
  276.          cmp      cs:inbeep,1                ; are we beeping right now ?
  277.          jnz      imret                      ; no, immediate return
  278.          dec      cs:beepticks               ; yes, done beeping?
  279.          jnz      imret                      ; no, immediate return
  280.          push     ax
  281.          mov      al,cs:spkrstat             ; yes, shut off speaker
  282.          out      61h,al
  283.          dec      cs:beepsleft               ; any more beeps waiting?
  284.          jz       nobeeps                    ; no, go home
  285.          push     bx
  286.          cmp      cs:beepsleft,1             ; how many await?
  287.          jz       one_left                   ; one
  288.          mov      bx,TONE2                   ; two
  289.          call     tone                       ; start it beeping
  290.          jmp      imret2                     ; go home
  291. one_left:
  292.          mov      bx,TONE3
  293.          call     tone                       ; start it beeping
  294.          jmp      imret2                     ; go home
  295. nobeeps:
  296.         mov       cs:beept,1                 ; we have beeped
  297.         mov       cs:inbeep,0                ; and we're not in one any more
  298.         jmp       imret1
  299. ;------------------------------------------------------------------------------
  300. alarm3: mov     bx,TONE1                ; send tone 1
  301.         mov     cs:beepsleft,3
  302.         call    tone
  303.         jmp     restore
  304. alarm2: mov     bx,TONE2                ; send tone 2
  305.         mov     cs:beepsleft,2
  306.         call    tone
  307.         jmp     restore
  308. alarm1: mov     bx,TONE3                ; send tone 3
  309.         mov     cs:beepsleft,1
  310.         call    tone
  311.         jmp     restore                 ; join common
  312. ;---------------------------------------
  313. tone:
  314.         cmp     cs:beept,1              ; do nothing if chime has been beeped
  315.         jz      notone                  ; earlier in this clock update
  316.         mov     cs:beepticks,BEEPS      ; this long on beeps
  317.         MOV     AL,0B6H                 ; else condition the timer
  318.         OUT     43H,AL
  319.         MOV     AX,BX                   ; this is the freq
  320.         OUT     42H,AL
  321.         MOV     AL,AH
  322.         OUT     42H,AL                  ; out you all go
  323.         IN      AL,61H                  ; read spkr port
  324.         MOV     cs:spkrstat,AL
  325.         OR      AL,3
  326.         OUT     61H,AL                  ; send a beep
  327.         mov     cs:inbeep,1
  328. notone: ret
  329. ;------------------------------------------------------------------------------
  330. calc      endp
  331.  
  332. ;******************************************************************************
  333. load_clock proc near              ; This procedure initializes everything
  334.           assume   ds:interrupts  ; The Data Segment will be the interrupt area
  335.           mov      ax,interrupts
  336.           mov      ds,ax
  337.  
  338.         MOV     SI,0081H        ; addr of command line arguments
  339. NEXT:   MOV     AL,CS:[SI]      ; get command line char
  340.         CMP     AL,0DH          ; Return ends it.
  341.         JZ      again
  342.         CMP     AL,'/'          ; switch char
  343.         JZ      getswitch       ; see what it is
  344. next1:  INC     SI              ; else point to next char
  345.         JMP     NEXT            ; and loop
  346. getswitch:
  347.         inc     si
  348.         mov     al,cs:[si]
  349.         cmp     al,'c'          ; chime toggle switch ?
  350.         jz      sw_c
  351.         cmp     al,'d'          ; force-chime switch ?
  352.         jz      sw_d
  353.         cmp     al,'x'          ; activate/deactivate ?
  354.         jz      sw_x
  355.         cmp     al,'r'          ; reverse video ?
  356.         jz      sw_r
  357.  
  358.         jmp     next1
  359.  
  360. sw_c:   mov     cs:togchim,1    ; toggle them chimes
  361.         jmp     next1           ; get next switch if there is one
  362.  
  363. sw_d:   mov     cs:forchim,1    ; make the chimes ring
  364.         jmp     next1
  365.  
  366. sw_x:   mov     cs:actdeact,1   ; toggle activation mode
  367.         jmp     next1
  368.  
  369. sw_r:   mov     cs:revvid,1     ; toggle reverse video
  370.         jmp     next1
  371.  
  372. again:    mov      ax,cs:sig_vector     ; get signature vector
  373.           cmp      ax,5fh               ; if less than 0x60
  374.           jg       vok
  375.           jmp      noload               ; forget it
  376. vok:      add      ax,3500h
  377.           int      21h
  378.           mov      ax,es
  379.           cmp      ax,434ch             ; are we already loaded ?
  380.           jnz      nosig                ; no
  381.           cmp      bx,4f4bh
  382.           jnz      nosig                ; and no
  383.           mov      bx,word ptr timer_int ; yes
  384.           mov      es,word ptr timer_int+2
  385.           call     gdate                ; get the system date
  386.           cmp      cs:togchim,1
  387.           jnz      no2                  ; no toggle chimes
  388.           call     toglchim             ; go toggle chimes
  389. no2:      cmp      cs:forchim,1
  390.           jnz      no1                  ; no force chimes
  391.           call     forcchim             ; go force chimes
  392. no1:      cmp      cs:revvid,1
  393.           jnz      no0                  ; no video toggle
  394.           call     chvidmode            ; go toggle video
  395. no0:      cmp      cs:actdeact,1
  396.           jnz      exit
  397.           call     xactivate            ; go toggle activation mode
  398.  
  399. exit:                                   ; rundown the modes
  400.           call     rundown
  401.           mov      ax,4c00h             ; return to DOS
  402.           int      21h
  403.  
  404. ;---------------------------------------
  405. nosig:    mov      ax,es                ; no current signature...
  406.           or       ax,bx                ; ...but is it safe to load one?
  407.           jz       setsig               ; yes
  408.           mov      ax,cs:sig_vector     ; no, try another slot
  409.           dec      ax
  410.           mov      cs:sig_vector,ax
  411.           jmp      again
  412. ;---------------------------------------
  413. toglchim:
  414.           mov      ax,es:[bx-4]         ; get the chime flag
  415.           xor      ax,1                 ; toggle it
  416.           mov      word ptr es:[bx-4],ax
  417.           mov      word ptr es:[bx-2],0   ; force clok off for activation
  418.           jmp      xactivate
  419. ;---------------------------------------
  420. xactivate:
  421.           mov      ax,es:[bx-2]
  422.           xor      ax,1                 ; toggle activation mode
  423.           mov      word ptr es:[bx-2],ax
  424.           ret
  425. ;---------------------------------------
  426. chvidmode:
  427.           mov      ax,bx                ; where the video display is
  428.           sub      ax,28
  429.           mov      di,ax
  430.           mov      ax,es:[di]           ; get the first byte of display
  431.           cmp      ax,4f20h             ; if it's color
  432.           jz       vdone                ; no reversal possible
  433.           cmp      ax,7020h             ; is it this kind ?
  434.           jnz      reprev               ; no, so make it so
  435.           mov      ax,0720h             ; reverse std
  436.           jmp      repc
  437. reprev:   mov      ax,7020h
  438. repc:     mov      cx,8                 ; 8 times
  439. putvb:    mov      es:[di],ax
  440.           inc      di
  441.           inc      di
  442.           loop     putvb
  443. vdone:    ret
  444. ;---------------------------------------
  445. forcchim:
  446.           mov      ax,es:[bx-12]        ; get the chime only switch
  447.           xor      ax,1                 ; toggle it
  448.           mov      word ptr es:[bx-12],ax
  449.           mov      word ptr es:[bx-4],0   ; force chimes off for activation
  450.           jmp      toglchim
  451. ;---------------------------------------
  452. noload    label near
  453.           mov      ax,4c01h             ; abort with error
  454.           int      21h
  455.  
  456. setsig:
  457.           cli
  458.           push     ds
  459.           mov      ax,cs:sig_vector
  460.           add      ax,2500h             ; signature reads:
  461.           mov      dx,434ch             ; 'CL'
  462.           mov      ds,dx
  463.           mov      dx,4f4bh             ; 'OK'
  464.           int      21h
  465.           pop      ds
  466.  
  467.           mov      ax,word ptr timer_int       ; Get the old interrupt service routine
  468.           mov      word ptr old_time_int,ax    ; address and put it into our location
  469.           mov      ax,word ptr timer_int+2     ; OLD_TIME_INT so we can still call it
  470.           mov      word ptr old_time_int+2,ax
  471.  
  472.           mov      word ptr timer_int,offset clock ; Now load the address of our clock
  473.           mov      word ptr timer_int+2,cs    ; routine into TIMER_INT so the timer
  474.                                       ; interrupt will call CLOCK
  475.           sti
  476.  
  477.           mov      ah,15              ; Ask for service 15 of INT 10H
  478.           int      10h                ; This tells us how the display is set up
  479.           sub      ah,8               ; Move to eight places before edge
  480.           shl      ah,1               ; Mult by two (char and attribute bytes)
  481.           mov      byte ptr cursor,ah ; Move cursor to it's memory location
  482.           mov      video_port,03bah   ; Assume this is a monochrome display
  483.           test     al,4               ; Is it?
  484.           jnz      get_time           ; Yes - jump out
  485.           add      cursor,8000h       ; No - set up for graphics display
  486.           mov      video_port,03dah
  487.           mov      cx,8
  488.           mov      ax,4f20h
  489.           lea      di,display
  490. color:    mov      cs:[di],ax
  491.           inc      di
  492.           inc      di
  493.           loop     color
  494.  
  495. get_time:
  496.         mov     bx,offset clock ; yes        ; get addr of clok
  497.         mov     ax,cs
  498.         mov     es,ax
  499.         cmp     cs:togchim,1    ; need to toggle ?
  500.         jnz     noct            ; no
  501.         call    toglchim
  502. noct:
  503.         cmp     cs:forchim,1  ; force chimes on, display off?
  504.         jnz     nocf          ; no
  505.         call    forcchim
  506. nocf:
  507.           call    gdate
  508.           call     calc  ; This is to avoid showing 00:00 for first 500 counts
  509.           call    rundown
  510.           mov      dx,offset load_clock   ; Set up for everything but LOAD_CLOCK
  511.           int      27h                ; to stay attached to DOS
  512. ;---------------------------------------
  513. rundown:
  514.           push     ds
  515.           mov      di,cs
  516.           mov      ds,di
  517.           mov      dx,offset hello             ; hello there
  518.           mov      ah,9
  519.           int      21h
  520.           mov      ax,es:[bx-4];
  521.           cmp      ax,1                 ; beep if it's been turned on
  522.           jz       beepmsg
  523.           mov      dx,offset chimoffmsg        ; chimes off
  524.           jmp      print
  525. beepmsg:  mov      dx,offset chimonmsg         ; chimes on
  526. print:    mov      ah,9
  527.           int      21h
  528. ;         pop      ds
  529. ;         push     ds
  530. ;         mov      di,cs
  531. ;         mov      ds,di
  532.           mov      ax,es:[bx-12]
  533.           cmp      ax,1
  534.           jz       cfonmsg
  535.           mov      dx,offset choffmsg
  536.           jmp      printt
  537. cfonmsg:  mov      dx,offset chonmsg         ; display
  538. printt:   mov      ah,9
  539.           int      21h
  540. ;         pop      ds
  541. ;         push     ds
  542. ;         mov      di,cs
  543. ;         mov      ds,di
  544.           mov      ax,es:[bx-2]
  545.           cmp      ax,1
  546.           jz       ckonmsg
  547.           mov      dx,offset cloffmsg
  548.           jmp      printtt
  549. ckonmsg:  mov      dx,offset clonmsg         ; activation
  550. printtt:  mov      ah,9
  551.           int      21h
  552.           pop      ds
  553.           ret
  554. ;----------------------------------------
  555. gdate:
  556.         push    bx
  557.         mov     ah,2ah          ; call DOS GetDate command
  558.         int     21h
  559.         xor     ah,ah           ; make an offset out of the day of the week
  560.         clc
  561.         rcl     ax,1
  562.         mov     si,ax
  563.         lea     bp,days
  564.         mov     ax,[bp+si]      ; get the ASCII day of the week
  565.         pop     bx
  566.         mov     word ptr es:[bx-10],ax  ; save it
  567.         mov     al,dh           ; month
  568.         xor     ah,ah
  569.         aam                     ; Convert AX to BCD - a nice command
  570.         add     ax,3030h        ; Add '0' to both bytes in AX to make ASCII
  571.         cmp     ah,'0'         ; Is the 1st digit '0'?
  572.         jne     gd1            ; Then don't blank the character.
  573.         mov     ah,' '         ; Otherwise, put a space in AH.
  574. gd1:    mov     word ptr es:[bx-8],ax
  575.         mov     al,dl           ; day
  576.         xor     ah,ah
  577.         aam                     ; Convert AX to BCD - a nice command
  578.         add     ax,3030h        ; Add '0' to both bytes in AX to make ASCII
  579.         mov     word ptr es:[bx-6],ax
  580.         ret                     ; go home
  581. ;---------------------------------------
  582. ;
  583. ; HERE BE THE LOCAL VARIABLES, AR!
  584. ;
  585. sig_vector      dw      67h             ; signature vector
  586. actdeact        db      0
  587. togchim         db      0               ; to toggle chimes
  588. forchim         db      0               ; to force chimes
  589. revvid          db      0               ; to toggle reverse video
  590. days            db      'uSoMuTeWhTrFaS'
  591. chimonmsg       db      'Chime   ON',0dh,0ah,'$'
  592. chimoffmsg      db      'Chime   OFF',0dh,0ah,'$'
  593. chonmsg         db      'Display OFF',0dh,0ah,'$'
  594. choffmsg        db      'Display ON',0dh,0ah,'$'
  595. clonmsg         db      'clok    ACTIVATED',0dh,0ah,'$'
  596. cloffmsg        db      'clok    DEACTIVATED',0dh,0ah,'$'
  597. hello           db      'CLOK v.4.0 by Thomas A. Lundin',0dh,0ah
  598.                 db      'usage: clok [/c /d /r /x] (/c: toggle chimes)',0dh,0ah
  599.                 db      '                          (/d: toggle display)',0dh,0ah
  600.                 db      '                          (/r: toggle video mode)',0dh,0ah
  601.                 db      '                          (/x: activate/deactivate clok)',0dh,0ah
  602.                 db      'CURRENT SETTINGS:',0dh,0ah
  603.                 db      '$'
  604.  
  605. load_clock         endp
  606.  
  607.           code_seg ends
  608.  
  609.           end      first ; END FIRST so 8088 will go to FIRST first
  610.