home *** CD-ROM | disk | FTP | other *** search
- ;----------------------------------------------------------
- ; Set the PC/AT alarm to user-specified time. Points alarm
- ; vector to BEEPER procedure which remains resident.
- ;-----------------------------------------------------------
- ; (c) Copyright Leo J. Scanlon, 1986
- .286c
-
- PRINT$ MACRO STRING ; Macro that prints a string
- LEA DX,STRING
- MOV AH,9
- INT 21H ;Function 9: display string
- ENDM
-
- PROGRAM SEGMENT PARA PUBLIC 'CODE'
- ASSUME CS:PROGRAM,DS:PROGRAM,ES:PROGRAM,SS:PROGRAM
- ORG 100H ;designed as .COM file
-
- BEGINING:
- JMP MAIN ;jump around procs and data
-
- START_RESIDENT:
-
- BEEPER PROC
- PUSHA ;Save the user's registers
- MOV CX,5 ;Beep five times
- BEEP: MOV AL,7 ;Beep for one second
- MOV AH,0EH
- INT 10H ;Video EH: write char as TTY
- LOOP BEEP
- POPA ;Restore the registers
- IRET
- BEEPER ENDP
-
- END_RESIDENT:
- RESIDENT_LENGTH EQU END_RESIDENT - START_RESIDENT
- RESIDENT_OFFSET EQU START_RESIDENT - BEGINING + 100H
-
- ;----------------------------------------------------------------
- ; See if BEEPER proc is already resident. Sets FIRST_TIME?=0 if
- ; alarm vector 4AH points to beeper routine, else leaves it 1
- ;----------------------------------------------------------------
- FIRST_TIME? DB 1
- CHECK_BEEPER PROC
- MOV AH, 35H
- MOV AL, 4AH
- INT 21H ;function 35H (get interrupt vector)
- MOV DI,BX ; set up ES:DI
- MOV SI,[RESIDENT_OFFSET] ; address BEEPER
- ; with DS:SI
- MOV CX,[RESIDENT_LENGTH] ; set length for CMPS
- REPE CMPSB
- JZ ALREADY_THERE ; ZF set means match
- RET
- ALREADY_THERE: MOV FIRST_TIME?,0
- RET
- CHECK_BEEPER ENDP
-
- ;------------------------------------------------------
- ; data area: messages, prompts, and keystroke buffer.
- ;------------------------------------------------------
-
- CRLF DB 13,10,'$'
- BAD_DATA DB 'Digits must be between 0 and 9',13,10,'$'
- BAD_HRS DB 'Hours must be between 0 and 23',13,10,'$'
- BAD_MINS DB 'Minutes must be between 0 and 59',13,10,'$'
- BAD_SECS DB 'Seconds must be between 0 and 59',13,10,'$'
-
- PROMPT DB 'Set the alarm time.',13,10
- DB 'Enter values or press Enter for zero'
- DB 13,10,'$'
- ASK_HRS DB 'Hour (0-23): $'
- ASK_MINS DB 'Minute (0-59): $'
- ASK_SECS DB 'Second (0-59): $'
- USER$ DB 3,4 DUP(?)
- ; User's response in 5 byte buffer
- ; <length of buffer> <chars read> <char1> <char2> <ret>
-
- ;---------------------------------------------------------------
- ; GET_TIME reads up to two keys into string buffer USER$,
- ; then converts them into a packed BCD number in BL.
- ; If either key is invalid, it prints an error message and sets
- ; CF to 1.
- ;---------------------------------------------------------------
-
- GET_TIME PROC
- LEA DX,USER$ ;Read user's response
- MOV AH,0AH
- INT 21H ; function AH (get keyboard input)
- stop1: PRINT$ CRLF ;Advance to next line
- CMP USER$+1,1 ;Check key count
- JAE CONVERT
- SUB BL,BL ;User pressed Enter
- RET
- CONVERT: MOV AL,USER$+2 ;Get first key
- CALL CHECK ;Check this character
- JC LEAVE ;If it is valid,
- AND AL,0FH ; convert it to BCD
- MOV BL,AL
- CMP USER$+1,2 ;Is there another key?
- JB CLR_CF
- SHL BL,4 ;Yes. Put first digit in high bits
- MOV AL,USER$+3 ;Get second key
- CALL CHECK ;Check this character
- JC LEAVE ;If it is valid,
- AND AL,0FH ; convert it to BCD
- OR BL,AL
- CLR_CF: CLC
- LEAVE: RET
- GET_TIME ENDP
-
- ;-----------------------------------------------------------
- ; CHECK makes sure an entry value is between 0 and
- ; 9. If not, it displays an error message and sets CF to 1.
- ;-----------------------------------------------------------
-
-
- CHECK PROC
- CMP AL,'0' ;If entry is < 0
- JB ERROR
- CMP AL,'9' ; or > 9,
- JA ERROR ; print message
- CLC ;Otherwise, clear CF and return
- RET
- ERROR: PRINT$ BAD_DATA ;Display error message
- STC ;Set CF and return
- RET
- CHECK ENDP
-
- MAIN PROC NEAR
- MOV AH,7 ;Reset the alarm
- INT 1AH ; AT BIOS interrupt 1AH (reset alarm)
- CALL CHECK_BEEPER
- CMP FIRST_TIME?, 1
- JNE USER_INPUT
- MOV AL,4AH ;Make the 4A vector point to BEEPER
- LEA DX,BEEPER
- MOV AH,25H
- INT 21H ;function 25H (set interrupt vector)
-
- USER_INPUT:
- PRINT$ PROMPT ;Ask for alarm hour
- HOUR: PRINT$ ASK_HRS
- CALL GET_TIME ;Convert it to BCD
- JC HOUR
- CMP BL,23H ;Make sure it's < 24
- JNA HRS2CH
- PRINT$ BAD_HRS
- JMP HOUR
- HRS2CH: MOV CH,BL ; and put it in CH
-
- MIN: PRINT$ ASK_MINS ;Ask for alarm minutes
- CALL GET_TIME ;Convert it to BCD
- JC MIN
- CMP BL,59H ;Make sure it's < 60
- JNA MIN2CL
- PRINT$ BAD_MINS
- JMP MIN
- MIN2CL: MOV CL,BL ; and put it in CL
-
- SEC: PRINT$ ASK_SECS ;Ask for alarm seconds
- CALL GET_TIME ;Convert it to BCD
- JC SEC
- CMP BL,59H ;Make sure it's < 60
- JNA SEC2DH
- PRINT$ BAD_SECS
- JMP SEC
- SEC2DH: MOV DH,BL ; and put it in DH
- MOV AH,6
- INT 1AH ;AT BIOS interrupt 1AH (set alarm)
- CMP FIRST_TIME?, 1
- JNE CLEAR_OUT
- MOV DX, RESIDENT_OFFSET + RESIDENT_LENGTH
- ;first invocation - leave BEEPER resident
- INT 27H ;interrupt 27H (terminate, stay resident)
-
- CLEAR_OUT:
- RET ;BEEPER already in place so
- ;exit normally
- MAIN ENDP
- PROGRAM ENDS
- END BEGINING
-