home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_400 / 428_02 / libsrc / clock.asm < prev    next >
Encoding:
Assembly Source File  |  1994-03-13  |  6.8 KB  |  259 lines

  1. ;-----------------------------------------------------------------------;
  2. ; CLOCK.ASM                                ;
  3. ;                                    ;
  4. ; Pictor, Version 1.51, Copyright (c) 1992-94 SoftCircuits.        ;
  5. ; Redistributed by permission.                        ;
  6. ;-----------------------------------------------------------------------;
  7. %    .MODEL    memmodel,c
  8.  
  9.     EXTRN    atexit:PROC
  10.  
  11.     .DATA
  12.     EXTRN    _PL_segment:WORD,_PL_columns:WORD
  13.     EXTRN    _PL_snowcheck:WORD
  14.  
  15. show_row    DW    0        ;Screen coordinates for clock
  16. show_column    DW    0
  17.  
  18. time_buffer    DB    "0 0 : 0 0 a m "
  19. TIME_BUFFER_LEN    EQU    (($-time_buffer)/2)
  20.  
  21. installed_flag    DB    0        ;1 = handler is installed
  22. registered_flag    DB    0        ;1 = removeclock registered w/atexit
  23. counter        DW    0        ;
  24.  
  25.  
  26.     .CODE
  27. old1C_handler    DD    0        ;Save old handler in code segment
  28.  
  29. ;-----------------------------------------------------------------------;
  30. ; Creates an ASCII time string based on the current time.        ;
  31. ;                                    ;
  32. ; Usage:    This procedure cannot be called directly from C.    ;
  33. ;-----------------------------------------------------------------------;
  34. IFDEF    ??version            ;Turbo Assembler
  35. create_time    PROC    NEAR
  36. ELSE
  37. create_time    PROC NEAR PRIVATE
  38. ENDIF
  39.     mov    time_buffer[10],'a'    ;Assume 'am' for now
  40.     mov    ax,0040h
  41.     mov    es,ax
  42.     mov    ax,es:[006Eh]        ;Read timer high count
  43.     mov    bx,ax            ;Preserve ax
  44.     mov    ax,12            ;Assume midnight
  45.     cmp    bx,0            ;Is it midnight?
  46.     je    set_hours        ;Yes
  47.     mov    ax,bx            ;Else restore ax
  48.     cmp    ax,12            ;Is it before noon?
  49.     jb    set_hours        ;Yes, 'am' okay
  50.     mov    time_buffer[10],'p'    ;Else must be 'pm'
  51.     cmp    al,12            ;Noon?
  52.     je    set_hours        ;Yes
  53.     sub    al,12            ;Else adjust 'pm' hours
  54. set_hours:
  55.     aam                ;Convert al to binary coded decimal
  56.     add    ax,3030h        ;Convert ax to 2 ASCII digits
  57.     cmp    ah,'0'            ;Is leading digit '0'?
  58.     jne    hours_ok        ;No, hours are ok
  59.     mov    ah,' '            ;Else clear leading '0'
  60. hours_ok:
  61.     mov    time_buffer[0],ah    ;Create hour portion of string
  62.     mov    time_buffer[2],al
  63.     mov    al,es:[006Dh]        ;Read timer low count
  64.     mov    dl,60
  65.     mul    dl
  66.     mov    al,ah
  67.     aam                ;Convert al to binary coded decimal
  68.     add    ax,3030h        ;Convert ax to 2 ASCII digits
  69.     mov    time_buffer[6],ah    ;Create minutes portion of string
  70.     mov    time_buffer[8],al
  71.     ret
  72. create_time    ENDP
  73.  
  74. ;-----------------------------------------------------------------------;
  75. ; Displays the time string to the screen.                ;
  76. ;                                    ;
  77. ; Usage:    This procedure cannot be called directly from C.    ;
  78. ;-----------------------------------------------------------------------;
  79. IFDEF    ??version            ;Turbo Assembler
  80. show_time    PROC    NEAR
  81. ELSE
  82. show_time    PROC NEAR PRIVATE
  83. ENDIF
  84.     cld
  85.     mov    si,OFFSET time_buffer    ;ds:si = string, es:di = screen
  86.     mov    es,_PL_segment
  87.     mov    ax,show_row
  88.     mul    BYTE PTR _PL_columns
  89.     add    ax,show_column
  90.     shl    ax,1
  91.     mov    di,ax
  92.     mov    cx,TIME_BUFFER_LEN
  93.     cmp    _PL_snowcheck,0
  94.     je    no_snow_check
  95.     mov    dx,03DAh        ;CGA status port address
  96. snow_check:
  97.     lodsw
  98.     mov    bx,ax
  99. scan_low:
  100.     in    al,dx
  101.     shr    al,1
  102.     jc    scan_low
  103.     cli
  104. scan_high:
  105.     in    al,dx
  106.     shr    al,1
  107.     jnc    scan_high
  108.     xchg    ax,bx
  109.     stosw
  110.     sti
  111.     loop    snow_check
  112.     ret    
  113. no_snow_check:
  114.     rep    movsw
  115.     ret
  116. show_time    ENDP
  117.  
  118. ;-----------------------------------------------------------------------;
  119. ; Timer interrupt handler. If the counter has expired, the time string    ;
  120. ; is updated to reflect the current time. In either case, the time    ;
  121. ; string is written to the screen and this procedure chains to the    ;
  122. ; original timer handler.                        ;
  123. ;                                    ;
  124. ; Usage:    This procedure cannot be called directly from C.    ;
  125. ;-----------------------------------------------------------------------;
  126. IFDEF    ??version            ;Turbo Assembler
  127. int1C_handler    PROC    FAR
  128. ELSE
  129. int1C_handler    PROC FAR PRIVATE
  130. ENDIF
  131.     sti                ;Interrupts on
  132.     push    ax
  133.     push    bx
  134.     push    cx
  135.     push    dx
  136.     push    si
  137.     push    di
  138.     push    bp
  139.     push    ds
  140.     push    es
  141.     mov    ax,@Data        ;ds = data segment
  142.     mov    ds,ax
  143.     dec    counter            ;Decrement counter
  144.     jns    display_time        ;Display only if no underflow
  145.     call    create_time        ;Else update time string
  146.     mov    counter,500        ;Reset timer
  147. display_time:
  148.     call    show_time        ;Display time
  149.     pop    es
  150.     pop    ds
  151.     pop    bp
  152.     pop    di
  153.     pop    si
  154.     pop    dx
  155.     pop    cx
  156.     pop    bx
  157.     pop    ax
  158.     cli                ;Handler expects interrupts off
  159.     jmp    cs:old1C_handler    ;Chain to original handler
  160. int1C_handler    ENDP
  161.  
  162.     PUBLIC    removeclock
  163. ;-----------------------------------------------------------------------;
  164. ; Deactivates the clock by removing the clock interrupt handler. This    ;
  165. ; function fails if the handler has not been installed, or if the    ;
  166. ; interrupt vector has been modified since the handler was installed.    ;
  167. ;                                    ;
  168. ; Usage:    int removeclock(void);                    ;
  169. ; Returns:    0 = success, -1 = error                    ;
  170. ;-----------------------------------------------------------------------;
  171. removeclock    PROC
  172.     mov    ax,-1            ;Return error if we haven't
  173.     cmp    installed_flag,0    ; installed our handler
  174.     je    end_removeclock
  175.     mov    ax,351Ch        ;Get interrupt 1Ch vector
  176.     int    21h
  177.     mov    ax,-1            ;Return error if vector doesn't
  178.     cmp    bx,OFFSET int1C_handler    ; still point to our handler
  179.     jne    end_removeclock
  180.     mov    bx,es
  181.     mov    ax,cs
  182.     cmp    ax,bx
  183.     jne    end_removeclock
  184.     mov    ax,251Ch        ;Restore original vector
  185.     push    ds
  186.     lds    dx,cs:old1C_handler
  187.     int    21h
  188.     pop    ds            ;Restore ds
  189.     mov    installed_flag,0    ;Indicate we're no longer installed
  190.     sub    ax,ax
  191. end_removeclock:
  192.     ret
  193. removeclock    ENDP
  194.  
  195.     PUBLIC    installclock
  196. ;-----------------------------------------------------------------------;
  197. ; Installs an interrupt handler that will display the time at the    ;
  198. ; specified location. It then registers removeclock with the ANSI C    ;
  199. ; library function atexit().                        ;
  200. ;                                    ;
  201. ; Usage:    int installclock(int row,int column,int color);        ;
  202. ; Returns:    0 = success, -1 = error                    ;
  203. ;-----------------------------------------------------------------------;
  204. installclock    PROC USES si, row:WORD,column:WORD,color:WORD
  205.     mov    ax,-1            ;Return error if were already
  206.     cmp    installed_flag,1    ; installed
  207.     je    end_installclock
  208.     mov    ax,row            ;Adjust and save screen coordinates
  209.     dec    ax
  210.     mov    show_row,ax
  211.     mov    ax,column
  212.     dec    ax
  213.     mov    show_column,ax
  214.     mov    ax,color        ;Set attribute bytes of buffer to
  215.     mov    si,OFFSET time_buffer+1    ; specified color
  216.     mov    cx,TIME_BUFFER_LEN
  217. color_loop:
  218.     mov    [si],al
  219.     add    si,2
  220.     loop    color_loop
  221.     mov    ax,351Ch        ;Get old timer interrupt vector
  222.     int    21h
  223.     mov    WORD PTR cs:old1C_handler[0],bx
  224.     mov    WORD PTR cs:old1C_handler[2],es
  225.     push    ds            ;Set new timer interrupt vector
  226.     mov    ax,251Ch
  227.     push    cs
  228.     pop    ds
  229.     mov    dx,OFFSET int1C_handler
  230.     int    21h
  231.     pop    ds
  232.     mov    installed_flag,1    ;Indicate we've been installed
  233.     mov    ax,0
  234.     cmp    registered_flag,1
  235.     je    end_installclock
  236.     mov    registered_flag,1
  237.     IF    @CodeSize        ;Register removeclock with atexit()
  238.     push    cs
  239.     ENDIF
  240.     mov    ax,OFFSET removeclock
  241.     push    ax
  242.     call    atexit
  243.     IF    @CodeSize
  244.     add    sp,4
  245.     ELSE
  246.     inc    sp
  247.     inc    sp
  248.     ENDIF
  249.     cmp    ax,0            ;Was atexit() successful?
  250.     je    end_installclock    ;Yes, return 0
  251.     call    removeclock        ;Else uninstall handler
  252.     mov    registered_flag,0
  253.     mov    ax,-1            ;Return error
  254. end_installclock:
  255.     ret
  256. installclock    ENDP
  257.  
  258.     END
  259.