home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / assemblr / mslang / as / alarm.asm next >
Assembly Source File  |  1985-03-26  |  8KB  |  374 lines

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