home *** CD-ROM | disk | FTP | other *** search
/ The Unsorted BBS Collection / thegreatunsorted.tar / thegreatunsorted / programming / asm_programming / AS03.ZIP / REMCLK.ASM < prev   
Assembly Source File  |  1985-04-01  |  10KB  |  408 lines

  1. cseg    segment para public 'code'
  2.  
  3.     public      a209,a210,acount,alarm,aleng,ampm,atime,atmcnt,atmsg
  4.     public      atone,color,copyr,dhours,dmins,dsecs,estack
  5.     public      holdsp,holdss,hour,intaddr,jumpval,mfactor,msg1,msg2,msg3
  6.     public      p000,p010,p015,p018,p020,p030,p040a,p040p,p040x
  7.     public      p060,p061,p062,p063,p064,p070,p080,p100,p105
  8.     public      p106,p120,p125,p150,p160,p200,p203,p204,p205
  9.     public      p206,p208,p209,p210,p220,segaddr,signature,state,tstack
  10.     public      wait,whozat
  11. org    100h
  12. alarm    proc far
  13.  
  14. ; Memory-resident program to intercept the timer interrupt and display the
  15. ; system time in the upper right-hand corner of the display.
  16. ; This program is run as 'ALARM hh:mm x', where hh:mm is the alarm time and
  17. ; x is '-' to turn the display off. Any other value of x or no value will
  18. ; turn the clock on
  19.  
  20. intaddr equ 1ch*4        ; interrupt address
  21. segaddr equ 62h*4        ; segment address of first copy
  22. mfactor equ 17478        ; minute conversion factor * 16
  23. whozat    equ 1234h        ; signature
  24. color    equ 14h         ; color attribute
  25.  
  26.     assume cs:cseg,ds:cseg,ss:nothing,es:nothing
  27.     jmp p150        ; start-up code
  28.  
  29. jumpval dd 0            ; address of prior interrupt
  30. signature dw whozat        ; program signature
  31. state    db 0            ; '-' = off, all else = on
  32. wait    dw 18            ; wait time - 1 second or 18 ticks
  33. hour    dw 0            ; hour of the day
  34. atmcnt    dw 0
  35. atime    dw 0ffffh        ; minutes past midnite for alarm
  36.     dw 0ffffh        ; minutes past midnite for alarm
  37.     dw 0ffffh        ; minutes past midnite for alarm
  38.     dw 0ffffh        ; minutes past midnite for alarm
  39.     dw 0ffffh        ; minutes past midnite for alarm
  40. atmsg    db 'Alarm #1                                                     '
  41.     db 'Alarm #2                                                     ' ;60
  42.     db 'Alarm #3                                                     '
  43.     db 'Alarm #4                                                     '
  44.     db 'Alarm #5                                                     '
  45. acount    dw 0            ; alarm beep counter - number of seconds (5)
  46. atone    db 5            ; alarm tone - may be from 1 to 255 - the
  47.                 ; higher the number, the lower the frequency
  48. aleng    dw 8080h        ; alarm length (loop count) may be from 1-FFFF
  49.  
  50. dhours    dw 0            ; display hours
  51.     db ':'
  52. dmins    dw 0            ; display minutes
  53.     db ':'
  54. dsecs    dw 0            ; display seconds
  55.     db '-'
  56. ampm    db 0            ; 'A' or 'P' for am or pm
  57.     db 'm'
  58.  
  59. tstack    db 16 dup('stack   ')   ; temporary stack
  60. estack    db 0            ; end of stack
  61. holdsp    dw 0            ; original sp
  62. holdss    dw 0            ; original ss
  63.  
  64. p000:                ; interrupt code
  65.     push ax         ; save registers
  66.     push ds
  67.     pushf
  68.  
  69.     push cs
  70.     pop ds            ; make ds=cs
  71.     mov ax,wait        ; check wait time
  72.     dec ax            ; zero?
  73.     jz p010         ; yes - 1 second has elapsed
  74.     mov wait,ax        ; not this time
  75.     jmp p080        ; return
  76.  
  77. p010:    cli            ; disable interrupts
  78.     mov ax,ss        ; save stack
  79.     mov holdss,ax
  80.     mov holdsp,sp
  81.     mov ax,ds
  82.     mov ss,ax        ; point to internal stack
  83.     mov sp,offset estack
  84.     sti            ; allow interrupts
  85.  
  86.     push bx         ; save other registers
  87.     push cx
  88.     push dx
  89.     push es
  90.     push si
  91.     push di
  92.     push bp
  93.  
  94.     mov ax,18        ; reset wait time
  95.     mov wait,ax
  96.  
  97.     mov al,state        ; are we disabled?
  98.     cmp al,'-'
  99.     jnz p015        ; no
  100.     jmp p070
  101.  
  102. p015:    mov ah,0        ; read time
  103.     int 1ah         ; get time of day
  104.     mov ax,dx        ; low part
  105.     mov dx,cx        ; high part
  106.     mov cl,4
  107.     shl dx,cl        ; multiply by 16
  108.     mov bx,ax
  109.     mov cl,12
  110.     shr bx,cl        ; isolate top 4 bits of ax
  111.     add dx,bx        ; now in upper
  112.     mov cl,4
  113.     shl ax,cl        ; multiply by 16
  114.     mov bx,mfactor        ; compute minutes
  115.     div bx            ; minutes in ax, remainder in dx
  116.     cmp ax,atime        ; time to sound the alarm?
  117.     jnz p020        ; no
  118.     call p100        ; yes - beep the speaker twice
  119.     push ax
  120.     mov ax,acount        ; get beep count
  121.     dec ax            ; down by 1
  122.     mov acount,ax        ; save beep count
  123.     cmp ax,0        ; is it zero?
  124.     jnz p018        ; no - keep alarm on
  125.     mov ax,0ffffh        ; turn off alarm
  126.     mov atime,ax
  127. p018:    pop ax
  128.  
  129. p020:    mov dsecs,dx        ; save remainder
  130.     mov bx,60        ; compute hours
  131.     xor dx,dx        ; zero it
  132.     div bx            ; hours in ax, minutes in dx
  133.     mov dmins,dx        ; save minutes
  134.  
  135.     cmp ax,0        ; midnight?
  136.     jnz p030        ; no
  137.     mov ax,12        ; yes
  138.     jmp p040a        ; set am
  139.  
  140. p030:    cmp ax,12        ; before noon?
  141.     jb p040a        ; yes - set am
  142.     jz p040p        ; noon - set pm
  143.     sub ax,12        ; convert the rest
  144. p040p:    mov bl,'p'
  145.     jmp p040x
  146.  
  147. p040a:    mov bl,'a'
  148.  
  149. p040x:    mov ampm,bl
  150.     aam            ; fix up hour
  151.     cmp ax,hour        ; top of the hour?
  152.     jz p060         ; no
  153.  
  154.     mov hour,ax
  155.     call p120        ; beep the speaker once
  156.  
  157. p060:    add ax,3030h        ; convert hours to ascii
  158.     xchg ah,al
  159.     mov dhours,ax
  160.  
  161.     mov ax,dmins        ; get minutes
  162.     aam
  163.     add ax,3030h        ; convert to ascii
  164.     xchg ah,al
  165.     mov dmins,ax
  166.  
  167.     mov ax,dsecs        ; get seconds (remainder)
  168.     xor dx,dx
  169.     mov bx,60
  170.     mul bx
  171.     mov bx,mfactor
  172.     div bx            ; seconds in ax
  173.     aam
  174.     add ax,3030h
  175.     xchg ah,al
  176.     mov dsecs,ax
  177.  
  178.     xor ax,ax        ; check monitor type
  179.     mov es,ax
  180.     mov ax,es:[410h]    ; get config byte
  181.     and al,30h        ; isolate monitor type
  182.     cmp al,30h        ; color?
  183.     mov ax,0b000h        ; assume mono
  184.     jz p061         ; its mono
  185.  
  186.     mov ax,0b800h        ; color screen address
  187.  
  188. p061:    mov dx,es:[463h]    ; point to 6845 base port
  189.     add dx,6        ; point to status port
  190.  
  191.     mov es,ax        ; point to monitor
  192.     mov bh,color        ; color in bh
  193.     mov si,offset dhours    ; point to time
  194.     mov di,138        ; row 1, col 69
  195.     cld
  196.     mov cx,11        ; loop count
  197.  
  198. p062:    mov bl,[si]        ; get next character
  199.  
  200. p063:    in al,dx        ; get crt status
  201.     test al,1        ; is it low?
  202.     jnz p063        ; no - wait
  203.     cli            ; no interrupts
  204.  
  205. p064:    in al,dx        ; get crt status
  206.     test al,1        ; is it high?
  207.     jz p064         ; no - wait
  208.  
  209.     mov ax,bx        ; move color & character
  210.     stosw            ; move color & character again
  211.     sti            ; interrupts back on
  212.     inc si            ; point to next character
  213.     loop p062        ; done?
  214.  
  215. p070:    pop bp            ; restore registers
  216.     pop di
  217.     pop si
  218.     pop es
  219.     pop dx
  220.     pop cx
  221.     pop bx
  222.     cli            ; no interrupts
  223.     mov ax,holdss
  224.     mov ss,ax
  225.     mov sp,holdsp
  226.     sti            ; allow interrupts
  227.  
  228. p080:    popf
  229.     pop ds
  230.     pop ax
  231.     jmp cs:[jumpval]
  232.  
  233. p100    proc near        ; beep the speaker twice
  234.     call p120
  235.     push cx
  236.     mov cx,20000
  237. p105:    loop p105        ; wait around
  238.     pop cx
  239.     call p120
  240.     push cx
  241.     mov cx,20000
  242. p106:    loop p106        ; wait around
  243.     pop cx
  244.     call p120
  245.     ret
  246. p100    endp
  247.  
  248. p120    proc near        ; beep the speaker once
  249.     push ax
  250.     push cx
  251.     mov al,182
  252.     out 43h,al        ; setup for sound
  253.     mov al,0
  254.     out 42h,al        ; low part
  255.     mov al,atone        ; get alarm tone
  256.     out 42h,al        ; high part
  257.     in al,61h
  258.     push ax         ; save port value
  259.     or al,3
  260.     out 61h,al        ; turn speaker on
  261.     mov cx,aleng        ; get loop count
  262. p125:    loop p125        ; wait around
  263.     pop ax            ; restore original port value
  264.     out 61h,al        ; turn speaker off
  265.     pop cx
  266.     pop ax
  267.     ret
  268. p120    endp
  269.  
  270. p150:                ; start of transient code
  271.     mov dx,offset copyr
  272.     call p220        ; print copyright
  273.     mov ax,0
  274.     mov es,ax        ; segment 0
  275.     mov di,segaddr+2    ; this program's prior location
  276.     mov ax,es:[di]        ; get prior code segment
  277.     mov es,ax        ; point to prior program segment
  278.     mov di,offset signature
  279.     mov cx,es:[di]        ; is it this program?
  280.     cmp cx,whozat
  281.     jnz p160        ; no - install it
  282.     call p200        ; set state & alarm
  283.     int 20h         ; terminate
  284.  
  285. p160:    mov di,segaddr+2    ; point to int 62h
  286.     mov ax,0
  287.     mov es,ax        ; segment 0
  288.     mov ax,ds        ; get current ds
  289.     mov es:[di],ax        ; set int 62h
  290.     mov si,offset jumpval
  291.     mov di,intaddr        ; point to timer interrupt
  292.     mov bx,es:[di]        ; get timer ip
  293.     mov ax,es:[di+2]    ; and cs
  294.     mov [si],bx        ; save prior ip
  295.     mov [si+2],ax        ; and cs
  296.     mov bx,offset p000
  297.     mov ax,ds
  298.     cli            ; clear interrupts
  299.     mov es:[di],bx        ; set new timer interrupt
  300.     mov es:[di+2],ax
  301.     sti            ; set interrupts
  302.     push ds
  303.     pop es
  304.     call p200        ; set state & alarm
  305.     mov dx,offset p150    ; last byte of resident portion
  306.     inc dx
  307.     int 27h         ; terminate
  308.  
  309. p200    proc near        ; set state & alarm
  310.     mov si,80h        ; point to command line
  311.     mov ax,0
  312.     mov di,0ffffh        ; init hours
  313.     mov bh,0
  314.     mov ch,0
  315.     mov dh,0        ; : counter
  316.     mov es:[state],bh    ; turn clock on
  317.     mov cl,[si]        ; get length
  318.     jcxz p208        ; it's zero
  319.  
  320. p203:    inc si            ; point to next char
  321.     mov bl,[si]        ; get it
  322.     cmp bl,'-'              ; is it a minus?
  323.     jnz p204        ; no
  324.     mov es:[state],bl    ; turn clock off
  325.     push dx
  326.     mov dx,offset msg3    ; print msg
  327.     call p220
  328.     pop dx
  329.     jmp p206
  330. p208:    ret
  331. p204:    cmp dh,2        ; seen 2nd colon?
  332.     jz p206         ; yes - ignore seconds
  333.     cmp bl,':'              ; colon?
  334.     jnz p205        ; no
  335.     inc dh
  336.     cmp dh,2        ; second colon?
  337.     jz p206         ; yes - ignore seconds
  338.     push cx
  339.     push dx
  340.     mov cx,60
  341.     mul cx            ; multiply current ax by 60
  342.     pop dx
  343.     pop cx
  344.     mov di,ax        ; save hours
  345.     mov ax,0
  346.     jmp p206
  347. p205:    cmp bl,'0'
  348.     jb p206         ; too low
  349.     cmp bl,'9'
  350.     ja p206         ; too high - can be a problem
  351.     sub bl,'0'              ; convert it to binary
  352.     push cx
  353.     push dx
  354.     mov cx,10
  355.     mul cx            ; multiply current value by 10
  356.     add ax,bx        ; and add latest digit
  357.     pop dx
  358.     pop cx
  359. p206:    loop p203        ; done yet?
  360.     cmp di,0ffffh        ; any time to set?
  361.     jz p210         ; no
  362.     add ax,di        ; add hours
  363.     cmp ax,24*60
  364.     jb p209         ; ok
  365.     mov dx,offset msg1    ; print error message
  366.     call p220
  367.     jmp p210
  368.  
  369. p209:    mov bx,word ptr es:[atmcnt]     ;get current count
  370.     mov es:[atime+bx],ax    ; save minutes past midnight
  371.     mov ax,5
  372.     mov es:[acount],ax    ; set alarm count
  373.     mov cx,60        ; message length
  374.     mov ax,word ptr es:[atmcnt]     ; get current count
  375.     mul cx            ; ax has offset to message storage
  376.     add ax,offset atmsg
  377.     mov di,ax        ; save offset
  378. a210:    mov al,byte ptr ds:[si] ; move string
  379.     mov byte ptr es:[di],al
  380.     inc si
  381.     inc di
  382.     loop a210
  383.     inc es:[atmcnt]     ; bump count
  384.     cmp es:[atmcnt],4    ; check for rollover
  385.     jnz a209
  386.     mov es:[atmcnt],0
  387. a209:    mov dx,offset msg2    ; print set msg
  388.     call p220
  389. p210:    ret
  390. p200    endp
  391.  
  392. p220    proc near        ; print message
  393.     push ax
  394.     mov ah,9
  395.     int 21h
  396.     pop ax
  397.     ret
  398. p220    endp
  399.  
  400. copyr    db 'Alarm - Clock',10,13,'$'
  401. msg1    db 'Invalid time - must be from 00:00 to 23:59',10,13,'$'
  402. msg2    db 'Setting alarm time',10,13,'$'
  403. msg3    db 'Turning clock display off',10,13,'$'
  404.  
  405. alarm    endp
  406. cseg    ends
  407. end    alarm
  408.