Meka][Meka Unstopable Posts: 700
| was jus looking around @ asm stuff
Code: | CODE SEGMENT PARA ASSUME CS:CODE, DS:CODE, ES:CODE ORG 100h START: JMP INIT ; JUMP TO INITIALIZATION ROUTINE ;------- DATA STORAGE -------------------------------------------------------- FREQ = 546 ; TIME CHECK FREQUENCY (30 SECS) OLDINT DD ? ; OLD INTERRUPT 1Ch VECTOR COUNT DW FREQ-1 ; INTERRUPT COUNTER MINUTE DB 00 ; ALARM MINUTE HOUR DB 00 ; ALARM HOUR ;------- RESIDENT PART OF PROGRAM -------------------------------------------- NEW_INT PROC FAR ASSUME DS:NOTHING, ES:NOTHING BEGIN: STI ; ENABLE INTERUPTS PUSHF ; SAVE FLAGS ON STACK PUSH AX ; SAVE REGISTERS PUSH BX PUSH CX PUSH DX PUSH DI PUSH SI PUSH DS PUSH ES PUSH CS ; RETRIEVE DATA SEGMENT POP DS INC COUNT ; INCREMENT INTERRUPT COUNTER CMP COUNT,FREQ ; TIME TO CHECK CLOCK? JB EXIT ; EXIT IF NOT ; CHECK TIME CHECK: MOV AH,02h ; GET TIME FROM BIOS INT 1Ah ; CH=HOURS, CL=MINUTES (BCD) CMP CH,HOUR ; COMPARE WITH ALARM HOUR JNE RESET ; RESET IF CURRENT # ALARM HOUR CMP CL,MINUTE ; HOURS ARE SAME, COMPARE MINUTES JE ALARM ; ALARM IF CURRENT = ALARM MINUTE ; OTHERWISE RESET COUNTER RESET: MOV COUNT,0000 ; RESET INTERRUPT COUNTER JMP EXIT ; JUMP TO EXIT ;------- GENERATE ALARM ------------------------------------------------------ ALARM: MOV DI,400 ; SET UP REGISTERS FOR BEEP PROCEDURE MOV BX,20 ; CALL BEEP ; MAKE THE TONE MOV DI,500 ; SET UP REGISTERS FOR BEEP PROCEDURE MOV BX,20 ; CALL BEEP ; MAKE THE TONE MOV DI,600 ; SET UP REGISTERS FOR BEEP PROCEDURE MOV BX,20 ; CALL BEEP ; MAKE THE TONE MOV DI,700 ; SET UP REGISTERS FOR BEEP PROCEDURE MOV BX,10 ; CALL BEEP ; MAKE THE TONE MOV AX,2 ; PAUSE OUTER: MOV CX,0FFFFh ; OUTER LOOP INNER: LOOP INNER ; INNER LOOP DEC AX JA OUTER MOV DI,600 ; SET UP REGISTERS FOR BEEP PROCEDURE MOV BX,20 ; CALL BEEP ; MAKE THE TONE MOV DI,700 ; SET UP REGISTERS FOR BEEP PROCEDURE MOV BX,40 ; CALL BEEP ; MAKE THE TONE ; MOVE JMP INSTRUCTION TO ENTRY POINT (DISABLE THIS PROGRAM) PUSH CS POP ES MOV SI,OFFSET JUMP ; SET SEGMENT TO 0000 MOV DI,OFFSET NEW_INT MOV CX,05 CLD ; DIRECTION = FORWARD CLI ; DISABLE INTERRUPTS REP MOVSB ; COPY JMP INSTRUCTION STI ; ALLOW INTERRUPTS AGAIN ;------- END THIS INTERRUPT ROUTINE ------------------------------------------ EXIT: POP ES POP DS POP SI POP DI POP DX POP CX POP BX POP AX POPF JUMP: JMP CS:OLDINT NEW_INT ENDP ;------- PROCEDURE TO CREATE A SINGLE TONE ----------------------------------- ; DI = FREQUENCY, BX = DURATION BEEP PROC NEAR ASSUME DS:NOTHING, ES:NOTHING PUSH AX ; Save registers PUSH BX PUSH CX PUSH DX PUSH DI MOV AL,0B6h ; Write timer mode register OUT 43h,AL MOV DX,14h ; Timer divisor = MOV AX,4F38h ; 1331000/Frequency DIV DI OUT 42h,AL ; Write timer 2 count low byte MOV AL,AH OUT 42h,AL ; Write timer 2 count high byte IN AL,61h ; Get current Port B setting MOV AH,AL ; and save it in AH OR AL,3 ; Turn speaker on OUT 61H,AL PAUSE: MOV CX,2801 ; Set duration counter SPKRON: LOOP SPKRON ; DEC BX ; Speaker on count expired? JNZ PAUSE ; If not, keep speaker on MOV AL,AH ; Otherwise, restore port OUT 61h,AL POP DI ; Restore registers POP DX POP CX POP BX POP AX RET ; And return BEEP ENDP ;------- INITIALIZATION PART OF PROGRAM (REMOVED BY TSR) --------------------- ASSUME CS:CODE, DS:CODE, ES:CODE INIT: CALL PARSE ; PARSE COMMAND ARGUMENTS FOR TIME CMP AL,0 ; CHECK IF SYNTAX ERROR (AL=1) JE GETVEC ; TERMINATE IF ERROR MOV AH,4Ch ; DOS FUNCTION TO TERMINATE INT 21h ; ; GET TIMER TICK INTERRUPT VECTOR (INT 1Ch) FROM DOS GETVEC: MOV AX,351Ch ; CALL DOS FUNCTION 35h INT 21h ; TO GET OLD VECTOR ; STORE IN "OLDINT" MOV WORD PTR [OLDINT],BX ; VECTOR OFFSET RETURNED IN BX MOV WORD PTR [OLDINT+2],ES ; VECTOR SEGMENT RETURNED IN ES CALL DISPTIME ; DISPLAY TIME ALARM IS SET FOR ; RESET INTERRUPT VECTOR TO POINT TO THIS PROGRAM MOV DX,OFFSET NEW_INT ; PUT OUR OFFSET IN DX MOV AX,251Ch ; CALL DOS FUNCTION 25 HEX TO INT 21h ; RESET TIMER INTERRUPT VECTOR ; TERMINATE BUT STAY RESIDENT USING DOS INTERRUPT 27h MOV DX,OFFSET INIT ; SET AVAILIBLE MEMORY ADDRESS TO "INIT" INT 27h ; CALL DOS INTERUPT 27 HEX TO TERMINATE ;------- PARSE COMMAND LINE TO GET ALARM TIME ------------------------------- PARSE PROC NEAR ASSUME CS:CODE, DS:CODE, ES:CODE CMP BYTE PTR DS:80h,00 ; SEE IF ANY ARGUMENTS JA PARAM ; IF NO, PROMPT FOR IT MOV DX,OFFSET PROMPT ; DISPLAY PROMPT MOV AH,09h INT 21h MOV DX,7Fh ; PUT START OF INPUT BUFFER IN DX MOV BYTE PTR DS:7Fh,128 ; LENGTH OF INPUT BUFFER MOV AH,0Ah ; CALL DOS TO GET INPUT INT 21h MOV DL,10 ; CALL DOS TO DISPLAY LINE FEED MOV AH,02 INT 21h PARAM: CALL UPCASE ; CHANGE ARGUMENTS TO UPPER CASE MOV SI,81h ; SET POINTER TO COMMAND ARGUMENTS AGAIN1: LODSB ; GET NEXT CHAR CMP AL,' ' ; CHECK FOR SPACE JE AGAIN1 ; IF YES, GET ANOTHER CMP AL,'0' ; IS IT A NUMBER? JB ERROR1 ; IF NO, SYNTAX ERROR CMP AL,'9' ; JA ERROR1 ; CALL GETBCD ; GET HOUR IN BCD CMP BL,23h ; MAKE SURE IT'S VALID (<24) JA ERROR2 ; DISPLAY MESSAGE IF NOT MOV HOUR,BL ; STORE HOUR CMP AL,':' ; CHECK FOR COLON JNE PM ; IF NOT CHECK FOR PM LODSB ; GET NEXT CHAR CMP AL,'0' ; IS IT A NUMBER? JB ERROR1 ; IF NO, SYNTAX ERROR CMP AL,'9' ; JA ERROR1 ; CALL GETBCD ; GET MINUTE IN BCD CMP BL,59h ; MAKE SURE IT'S VALID JA ERROR3 ; DISPLAY MESSAGE IF NOT MOV MINUTE,BL ; STORE MINUTE PM: CMP AL,' ' ; CHECK FOR SPACE JNE P ; IF NOT CHECK FOR 'PM' LODSB ; OTHERWISE GET NEXT CHAR JMP PM ; AND CHECK AGAIN P: CMP AL,'P' ; CHECK FOR 'P' JNE OK ; END IF NOT LODSB ; OTHERWISE GET NEXT CHAR CMP AL,'M' ; CHECK FOR 'M' JNE OK ; END IF NOT ; OTHERWISE CHANGE TO 'PM' MOV AL,HOUR ; LOAD HOUR CMP AL,00 ; CHECK IF HOUR = 0 JE OK ; END IF IT IS ( DON'T CHANGE IT ) CMP AL,11h ; CHECK IF HOUR < 12 JA OK ; END IF NOT ADD AL,12h ; OTHERWISE ADD 12 DAA ; ADJUST FOR BCD ADDITION MOV HOUR,AL ; STORE NEW 24 HOUR FORMAT OK: MOV AL,00 ; CLEAR ERROR FLAG JMP ENDSUB1 ; ALL THROUGH ; SYNTAX ERROR : NO OR INCORRECT ALARM TIME WAS ENTERED, PRINT MESSAGE ; AND RETURN ERROR CODE (AL=1) ERROR1: MOV DX,OFFSET MSG1 ; PUT MESSAGE 1 ADDRESS IN DX JMP SHORT PRNT ; JUMP TO PRINT ERROR2: MOV DX,OFFSET MSG2 ; PUT MESSAGE 2 ADDRESS IN DX JMP SHORT PRNT ; JUMP TO PRINT ERROR3: MOV DX,OFFSET MSG3 ; PUT MESSAGE 3 ADDRESS IN DX PRNT: MOV AH, 09h ; CALL DOS PRINT STRING FUNCTION INT 21h ; MOV AL,01 ; AL=1 : SYNTAX ERROR ENDSUB1: RET ; RETURN TO MAIN PROGRAM PARSE ENDP ;------------------------------------------------------------ ;------- CHANGE COMMAND LINE PARAMETERS TO UPPER CASE ----------------------- UPCASE PROC NEAR ASSUME CS:CODE, DS:CODE, ES:CODE MOV CL,BYTE PTR CS:80h ; LOAD LENGTH OF ARGUMENTS MOV CH,00 ; MOV SI,0000 ; SET UP SOURCE INDEX NEXT: CMP CX,SI ; IF SI=CX THEN ARGUMENT LIST HAS JE ENDSUB2 ; BEEN PROCESSED INC SI ; INCREMENT INDEX MOV AL,BYTE PTR [80h+SI] ; LOAD NEXT CHAR CMP AL,'a' ; IS IT A LOWER CASE LETTER JB NEXT ; GET NEXT IF NOT CMP AL,'z' ; JA NEXT ; SUB AL,20h ; CHANGE TO UPPER CASE MOV BYTE PTR [80h+SI],AL ; STORE NEW CHAR JMP NEXT ; GET NEXT CHAR ENDSUB2: RET ; ALL DONE, RETURN UPCASE ENDP ;------------------------------------------------------------ ;------- PROCEDURE TO GET NUMBER FROM COMMAND LINE & CONVERT IT TO BCD ------ GETBCD PROC NEAR XOR BX,BX ; CLEAR BX TO HOLD RESULT SUB AL,30h ; ELSE, SUBTRACT 30H MOV BL,AL ; STORE IT IN BL LODSB ; GET NEXT CHAR CMP AL,30h ; IS IT A NUMBER? JB ENDSUB3 ; IF NO, RETURN CMP AL,39h ; JA ENDSUB3 ; SUB AL,30h ; ELSE, SUBTRACT 30H MOV CL,04 ; SHIFT FIRST NUMERAL LEFT 4 SHL BL,CL OR BL,AL ; OR IN SECOND NUMERAL LODSB ; GET NEXT CHAR AND QUIT ENDSUB3: RET ; RETURN GETBCD ENDP ;------------------------------------------------------------ ;------- DISPLAY ALARM SET MESSAGE ------------------------------------------ DISPTIME PROC NEAR MOV AL,HOUR ; LOAD HOUR (BCD) MOV AH,AL ; STORE IN AH CMP AL,12h ; CHECK IF PM JB AM ; LEAVE MESSAGE AT AM MOV BYTE PTR SETMSG[34],112 ; CHANGE AM TO PM CMP AL,13h ; CHECK IF HOUR NEEDS ADJUSTING JB AM ; NOT IF < 13 (1 pm) SUB AL,12h ; CHANGE TO 12 HOUR TIME DAS ; ADJUST FOR BCD SUBTRACTION MOV AH,AL ; STORE RESULT IN AH AM: MOV CL,4 ; LOAD COUNTER SHR AL,CL ; GET MOST SIGNIFICANT DIGIT CMP AL,0 ; LEAVE MSD BLANK IF ZERO JE NOTENS ; ADD AL,30h ; CHANGE TO ASCII MOV BYTE PTR SETMSG[28],AL ; STORE MSD NOTENS: MOV AL,AH ; GET ADJUSTED HOUR FROM AH AND AL,0Fh ; MASK LEAST SIGNIFICANT DIGIT ADD AL,30h ; CHANGE TO ASCII MOV BYTE PTR SETMSG[29],AL ; STORE LSD MOV AL,MINUTE ; LOAD MINUTE (BCD) MOV CL,4 ; LOAD COUNTER SHR AL,CL ; GET MSD ADD AL,30h ; CHANGE TO ASCII MOV BYTE PTR SETMSG[31],AL ; NO NEED TO CHECK FOR ZERO MOV AL,MINUTE ; RELOAD MINUTE AND AL,0Fh ; MASK LSD ADD AL,30h ; CHANGE TO ASCII MOV BYTE PTR SETMSG[32],AL ; STORE LSD MOV DX,OFFSET SETMSG ; DISPLAY ALARM SET TIME MOV AH, 09h ; CALL DOS PRINT STRING FUNCTION INT 21h ; RET DISPTIME ENDP ;------------------------------------------------------------ MSG1: DB 7,13,10,'The correct syntax is: ALARM hh[:mm] [PM]',13,10,36 MSG2: DB 7,13,10,'The hour can be 0 through 23',13,10,36 MSG3: DB 7,13,10,'The minute can be 0 through 59',13,10,36 SETMSG: DB 13,10,'An alarm has been set for 0:00 am',13,10,36 PROMPT: DB 13,10,'Enter alarm time ( hh[:mm] [PM] ): ',36 CODE ENDS END START |
|