home *** CD-ROM | disk | FTP | other *** search
- ; Protected-Mode Input/Output Procedures.
- ; Version 1.1
- ;
- ; All PMIO procedures assume that the code is resident in a 32-bit segment.
- ;The flat-data model is also assumed, that is, DS = FLATDSEL. If the latter
- ;assumption is unacceptable, then modify the code to load DS at the beginning of
- ;the procedures. A full explanation of each IO procedure is provided above the
- ;procedure. The following is a brief summary:
- ;
- ;Screen Procedures:
- ;
- ; The screen procedures always print at the recorded BIOS cursor position and
- ;update the BIOS position after printing; however, they do not adjust the video
- ;hardware to actually relocate the cursor on the screen. Call UPDATECSR for
- ;this purpose.
- ; The screen procedures avoid all calls to DOS and BIOS. Therefore, they
- ;should function properly within interrupt handlers.
- ; The screen address is assumed to be B8000H, which will be the case for
- ;color monitors. For monochrome monitors, set SCRNBASEADR to B0000H.
- ;
- ;Procedure Description
- ;PCH Print ASCII character in AL
- ;CRLF Issue carriage return and line feed
- ;SCRLUP Scoll screen up
- ;SPC Print AL spaces
- ;CLS Clear screen
- ;PSTR Print zero terminated ASCII string at ES:EBX
- ;PCSSTR Print zero terminated ASCII string at CS:EBX
- ;PHW Print WORD in AX as hexadecimal
- ;PHD Print DWORD in EAX as hexadecimal
- ;PUW Print unsigned WORD in AX as decimal
- ;PUD Print unsigned DWORD in EAX as decimal
- ;PSW Print signed WORD in AX as decimal
- ;PSD Print signed DWORD in EAX as decimal
- ;FPST Print ST of FPU using format in AX. AH = characters to left of
- ; decimal. AL = characters to right of decimal.
- ;
- ;Keyboard Procedures:
- ;
- ;Procedure Description
- ;GETCH Get character from keyboard in AX. AL = either ASCII code or
- ; scan code. If sign bit of AH is set, then scan code. Other bits
- ; in AH define the state of shift and toggle keys (see procedure
- ; for detail). Character is not echoed.
- ;SETCSRPOS Set cursor position. Call with (AH,AL) = (row,column). Rows
- ; range from zero (top) to 24 (bottom). Columns range from zero
- ; (left) to 79 (right).
- ;GETCSRPOS Get cursor position in AX. (AH,AL) = (row,column).
- ;UPDATECSR Physically relocate cursor on screen to current BIOS coordinates.
- ;SETCSRTYPE Set cursor type. Call with AL = 0 for underline, or 1 for block.
- ; Call with sign bit of AL set to disable the cursor.
- ;SETCSR Set cursor position and type. Call with position in DX and type
- ; in CX. CH = start scan line, and CL = end scan line. Scan lines
- ; range from 0 (top) to 7 (bottom).
- ;GETCSR Get cursor position/type in DX/CX (CH/CL = start/end scan line).
- ;
- ;Speaker Procedures:
- ;
- ;Procedure Description
- ;BEEP Produce beep through speaker.
-
- ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- ;TASM Modifications
- ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- ; TASM users should set TASMMODE below to true. These modifications were
- ;tested with TASM 4.0.
-
- TRUE = 1
- FALSE = 0
-
- TASMMODE = FALSE
-
- IF TASMMODE
-
- MASM51
- QUIRKS
- SMART
- NOJUMPS
- LARGESTACK
-
- PUSHW MACRO IMMEDIATE16:REST ;PUSH immediate 16-bit data
- IF (@WordSize EQ 4)
- DB 66H
- ENDIF
- DB 68H
- DW IMMEDIATE16
- ENDM
-
- PUSHD MACRO IMMEDIATE32:REST ;PUSH immediate 32-bit data
- IF (@WordSize EQ 2)
- DB 66H
- ENDIF
- DB 68H
- DD IMMEDIATE32
- ENDM
-
- ENDIF
-
- ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- ;Local Data and Constants
- ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- ALIGN 4
- SCRNBASEADR DD 000B8000H ;Screen address
- CURPOSADR EQU 00000450H ;BIOS address containing cursor position
- TICKCNTADR EQU 0000046CH ;BIOS address containing timer-tick counter
-
- ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- ;Screen Routines
- ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- ;Print ASCII code in AL at cursor.
- PCH PROC NEAR
- PUSH EBX
- PUSH EDX
- MOV EDX,DWORD PTR DS:[CURPOSADR] ;Cursor (row,col) in (DH,DL)
- PUSH EDX ;Push cursor position
- XOR EBX,EBX
- MOV BL,DH
- SHL EBX,5 ;Multiply row by 160
- LEA EBX,[EBX+4*EBX] ;160 = 32 + 4 * 32
- AND EDX,0FFH ;Clear all but column
- LEA EBX,[EBX+2*EDX]
- ADD EBX,CS:SCRNBASEADR
- POP EDX ;POP cursor position
- MOV [EBX],AL
- INC DL ;Increment column
- CMP DL,79
- JBE RCDCURSOR
- XOR DL,DL ;Move to zero column of next row
- INC DH ;Move to next row
- RCDCURSOR: MOV WORD PTR DS:[CURPOSADR],DX ;Assume row is valid
- CMP DH,24
- JA DOSCROLL
- EXIT: POP EDX
- POP EBX
- RET
- DOSCROLL: PUSHD OFFSET EXIT
- JMP SCRLUP
- PCH ENDP
-
- ;Clear cursor to end of line and issue CRLF. Scroll up if necessary.
- CRLF PROC NEAR
- PUSH EAX
- PUSH EBX
- PUSH ECX
- MOV EAX,DWORD PTR DS:[CURPOSADR]
- PUSH EAX ;PUSH cursor position
- XOR EBX,EBX
- MOV BL,AH
- SHL EBX,5 ;Multiply row by 160
- LEA EBX,[EBX+4*EBX] ;160 = 32 + 4 * 32
- AND EAX,0FFH ;Clear all but column
- MOV CL,80
- SUB CL,AL ;Get number of bytes to clear in CL
- LEA EBX,[EBX+2*EAX]
- ADD EBX,CS:SCRNBASEADR
- MOV AL,32
- CLREOL: MOV [EBX],AL ;Clear to end of line
- ADD EBX,2
- DEC CL
- JNZ CLREOL
- POP EAX ;POP cursor position
- INC AH ;Increment row
- CMP AH,24
- JA DOSCROLL
- XOR AL,AL ;Set column to zero
- MOV WORD PTR DS:[CURPOSADR],AX
- EXIT: POP ECX
- POP EBX
- POP EAX
- RET
- DOSCROLL: PUSHD OFFSET EXIT
- JMP SCRLUP
- CRLF ENDP
-
- ;Scroll entire screen up one line and leave cursor at start of line 24.
- SCRLUP PROC NEAR
- PUSH EAX
- PUSH EBX
- PUSH ECX
- MOV EBX,CS:SCRNBASEADR
- MOV ECX,960 ;960 = (80*24*2)/4 (DWORDS to scroll)
- SCROLLLOOP: MOV EAX,[EBX+160]
- MOV [EBX],EAX
- ADD EBX,4
- DEC ECX
- JNZ SCROLLLOOP
- MOV CL,80
- MOV AL,32
- CLR24: MOV [EBX],AL ;Clear line 24
- ADD EBX,2
- DEC CL
- JNZ CLR24
- EXIT: MOV WORD PTR DS:[CURPOSADR],1800H ;Set cursor to bottom line in zero column
- POP ECX
- POP EBX
- POP EAX
- RET
- SCRLUP ENDP
-
- ;Print AL spaces at cursor.
- SPC PROC NEAR
- OR AL,AL
- JZ EXIT
- PUSH EAX
- MOV AH,AL
- MOV AL,32
- PRINTSPC: CALL PCH
- DEC AH
- JNZ PRINTSPC
- POP EAX
- EXIT: RET
- SPC ENDP
-
- ;Clear screen and leave cursor at (0,0) position.
- CLS PROC NEAR
- PUSH EAX
- PUSH EBX
- PUSH ESI
- MOV EBX,CS:SCRNBASEADR
- MOV ESI,1999
- MOV AL,32
- DOCLS: MOV [EBX+2*ESI],AL
- DEC ESI
- JNS DOCLS
- MOV WORD PTR DS:[CURPOSADR],0H
- POP ESI
- POP EBX
- POP EAX
- RET
- CLS ENDP
-
- ;Print ASCIIZ string at address in ES:EBX.
- PSTR PROC NEAR
- PUSH EAX
- PUSH EBX
- CHARLOOP: MOV AL,ES:[EBX]
- OR AL,AL ;See if at end of string
- JZ EXIT
- CALL PCH
- INC EBX
- JMP CHARLOOP
- EXIT: POP EBX
- POP EAX
- RET
- PSTR ENDP
-
- ;Print ASCIIZ string at address CS:EBX.
- PCSSTR PROC NEAR
- PUSH EAX
- PUSH EBX
- CHARLOOP: MOV AL,CS:[EBX] ;See if at end of string
- OR AL,AL
- JZ EXIT
- CALL PCH
- INC EBX
- JMP CHARLOOP
- EXIT: POP EBX
- POP EAX
- RET
- PCSSTR ENDP
-
- ;Print hexadecimal WORD in AX.
- PHW PROC NEAR
- PUSH EAX
- PUSH ECX
- PUSH EDX
- MOV EDX,EAX
- MOV CL,4 ;Print four nibbles
- CALCNIBS: MOV AL,DL
- AND AL,0FH
- ADD AL,48
- CMP AL,57
- JBE PUSHDIGIT
- ADD AL,7
- PUSHDIGIT: PUSH EAX
- SHR EDX,4
- DEC CL
- JNZ CALCNIBS
- MOV CL,4
- PRNTNIBS: POP EAX
- CALL PCH
- DEC CL
- JNZ PRNTNIBS
- POP EDX
- POP ECX
- POP EAX
- RET
- PHW ENDP
-
- ;Print hexadecimal DWORD in EAX.
- PHD PROC NEAR
- PUSH EAX
- PUSH ECX
- PUSH EDX
- MOV EDX,EAX
- MOV CL,8 ;Print eight nibbles
- CALCNIBS: MOV AL,DL
- AND AL,0FH
- ADD AL,48
- CMP AL,57
- JBE PUSHDIGIT
- ADD AL,7
- PUSHDIGIT: PUSH EAX
- SHR EDX,4
- DEC CL
- JNZ CALCNIBS
- MOV CL,8
- PRNTNIBS: POP EAX
- CALL PCH
- DEC CL
- JNZ PRNTNIBS
- POP EDX
- POP ECX
- POP EAX
- RET
- PHD ENDP
-
- ;Print unsigned WORD in AX as decimal.
- PUW PROC NEAR
- PUSH EAX
- PUSH EBX
- PUSH ECX
- PUSH EDX
- AND EAX,0FFFFH
- XOR ECX,ECX
- MOV EBX,10
- CALCDIGS: XOR EDX,EDX
- DIV BX
- PUSH EDX
- INC ECX
- OR EAX,EAX
- JNZ CALCDIGS
- PRNTDIGS: POP EAX
- ADD AL,48
- CALL PCH
- DEC ECX
- JNZ PRNTDIGS
- POP EDX
- POP ECX
- POP EBX
- POP EAX
- RET
- PUW ENDP
-
- ;Print unsigned DWORD in EAX as decimal.
- PUD PROC NEAR
- PUSH EAX
- PUSH EBX
- PUSH ECX
- PUSH EDX
- XOR ECX,ECX
- MOV EBX,10
- CALCDIGS: XOR EDX,EDX
- DIV EBX
- PUSH EDX
- INC ECX
- OR EAX,EAX
- JNZ CALCDIGS
- PRNTDIGS: POP EAX
- ADD AL,48
- CALL PCH
- DEC ECX
- JNZ PRNTDIGS
- POP EDX
- POP ECX
- POP EBX
- POP EAX
- RET
- PUD ENDP
-
- ;Print signed WORD in AX as decimal.
- PSW PROC NEAR
- PUSH EAX
- OR AX,AX
- JNS PABS
- PUSH EAX
- MOV AL,"-"
- CALL PCH
- POP EAX
- NEG AX ;Calculate absolute value
- PABS: CALL PUW ;Print absolute value
- POP EAX
- RET
- PSW ENDP
-
- ;Print signed DWORD in EAX as decimal.
- PSD PROC NEAR
- PUSH EAX
- OR EAX,EAX
- JNS PABS
- PUSH EAX
- MOV AL,"-"
- CALL PCH
- POP EAX
- NEG EAX ;Calculate absolute value
- PABS: CALL PUD ;Print absolute value
- POP EAX
- RET
- PSD ENDP
-
- ;Print ST of FPU using format code in AX. Call with lowest seven bits of AH =
- ;number of high-order digits plus the sign (if negative), and lowest five bits
- ;of AL = number of low-order digits. Fractions are printed with leading zeros
- ;if the sign bit of AH is clear. Will print numbers absolutely smaller than
- ;10 ^ 18 and will print up to 18 decimal places. Will fill entire print field
- ;with "*" if high-order digit field is too small. Will fill entire print field
- ;with ">" if number is absolutely greater than or equal to 10 ^ 18. It is
- ;assumed that ST contains a valid number. AL must not be greater than 18.
- FPST PROC NEAR
- LOCAL NOLEAD0FLAG:DWORD ;If set, then no leading zero is placed in front of fractions
- LOCAL FLDWIDTH:DWORD ;The width of the print field
- LOCAL NOHIDIGITS:DWORD ;Number of high-order digits
- LOCAL NOLODIGITS:DWORD ;Number of low-order digits
- LOCAL OLDCWORD:WORD ;Old FPU control word
- LOCAL NEWCWORD:WORD ;Local FPU control word
- LOCAL HIDIGITS[10]:BYTE ;Storage for high-order digit string
- LOCAL LODIGITS[10]:BYTE ;Storage for low-order digit string
- PUSH EAX
- PUSH EBX
- PUSH ECX
- PUSH EDX
- PUSH ESI
- PUSH EDI
- XOR ECX,ECX ;Assume leading zeros on fractions
- CHKLEADZERO: OR AH,AH ;Test assumption
- JNS SETLEAD0MODE
- INC ECX ;Will not print leading zeros
- SETLEAD0MODE: MOV NOLEAD0FLAG,ECX
- AND AH,7FH ;Mask leading zero flag
- MOV CL,AH ;Set ECX = number of high order digits + sign
- MOV NOHIDIGITS,ECX
- MOV CL,AL ;Set ECX = number of decimal places
- MOV NOLODIGITS,ECX
- ADD AL,AH ;Compute field width in EAX
- AND EAX,0FFH
- OR ECX,ECX
- JZ SETFLDWIDTH
- INC EAX ;Account for decimal point
- SETFLDWIDTH: MOV FLDWIDTH,EAX
- FSTCW OLDCWORD ;Save original control word
- MOV AX,OLDCWORD
- OR AH,0FH ;Set PC to 64 bits and RC to truncate
- MOV NEWCWORD,AX
- FLDCW NEWCWORD
- FLD ST ;See if number of high order digits greater than 18
- FABS
- FCOM CS:FPPOWERTEN[8*18]
- FSTSW AX
- SAHF
- JAE OVERFLOW
- FLD ST(1) ;Compute and save high order digits
- FBSTP TBYTE PTR HIDIGITS[0]
- FLD ST ;Compute and save low order digits
- FRNDINT
- AND BYTE PTR NEWCWORD[1],0F3H ;Set RC to round
- FLDCW NEWCWORD
- FSUB
- FMUL CS:FPPOWERTEN[8*ECX]
- CALCLODIGITS: XOR EAX,EAX
- XOR EDI,EDI
- MOV ESI,8
- FBSTP TBYTE PTR LODIGITS[0]
- GETHIDIGIT: OR AL,HIDIGITS[ESI] ;Find first nonzero digit
- JNZ CALCHIORDER
- DEC ESI
- JNS GETHIDIGIT
- XOR ESI,ESI ;There are no nonzero high order digits
- TEST BYTE PTR NOLEAD0FLAG[0],01H ;See if leading zeros are disabled
- JNZ CHKSIGN
- INC ESI ;Add leading zero
- JMP CHKSIGN
- CALCHIORDER: MOV EDI,ESI
- INC ESI ;Convert ESI to number of high order digits
- ADD ESI,ESI
- AND AL,0F0H ;See if highest digit is in odd position
- JNZ CHKSIGN
- DEC ESI
- CHKSIGN: MOV DL,HIDIGITS[9] ;Get sign byte
- OR DL,DL
- JNS CHKHIFLD
- INC ESI ;Account for "-"
- CHKHIFLD: MOV EAX,NOHIDIGITS
- SUB EAX,ESI ;See if field for high-order digits and sign is large enough
- JB SMALLFLD
- CALL SPC ;Print leading spaces
- PRNTSIGN: OR DL,DL
- JNS PRNTHIDIGITS
- MOV AL,"-"
- CALL PCH
- DEC ESI
- PRNTHIDIGITS: OR ESI,ESI ;See if any high order digits are to be printed
- JZ PRNTDEC
- MOV DL,HIDIGITS[EDI]
- TEST ESI,01H
- JNZ ODDHIDIGIT
- HIDIGITLOOP: MOV AL,DL
- SHR AL,4
- ADD AL,48
- CALL PCH
- ODDHIDIGIT: MOV AL,DL
- AND AL,0FH
- ADD AL,48
- CALL PCH
- DEC EDI
- JS PRNTDEC
- MOV DL,HIDIGITS[EDI]
- JMP HIDIGITLOOP
- PRNTDEC: OR ECX,ECX ;See if any low order digits are to be printed
- JZ EXIT
- MOV AL,"."
- CALL PCH
- MOV EDI,ECX ;Find byte number for first digit
- DEC EDI
- SHR EDI,1
- MOV DL,LODIGITS[EDI]
- TEST CL,01H
- JNZ ODDLODIGIT
- LODIGITLOOP: MOV AL,DL
- SHR AL,4
- ADD AL,48
- CALL PCH
- ODDLODIGIT: MOV AL,DL
- AND AL,0FH
- ADD AL,48
- CALL PCH
- DEC EDI
- JS EXIT
- MOV DL,LODIGITS[EDI]
- JMP LODIGITLOOP
- EXIT: FLDCW OLDCWORD ;Restore calling control word
- POP EDI
- POP ESI
- POP EDX
- POP ECX
- POP EBX
- POP EAX
- RET
- FILLFLD: MOV ECX,FLDWIDTH
- RCDCHAR: CALL PCH ;Print one character even if field width is zero
- SUB ECX,1
- JAE RCDCHAR
- JMP EXIT
- SMALLFLD: MOV AL,"*"
- JMP FILLFLD
- OVERFLOW: FSTP ST ;Pop absolute value of number
- MOV AL,">"
- JMP FILLFLD
- ALIGN 8
- FPPOWERTEN LABEL QWORD
- DQ 1.0E0
- DQ 1.0E1
- DQ 1.0E2
- DQ 1.0E3
- DQ 1.0E4
- DQ 1.0E5
- DQ 1.0E6
- DQ 1.0E7
- DQ 1.0E8
- DQ 1.0E9
- DQ 1.0E10
- DQ 1.0E11
- DQ 1.0E12
- DQ 1.0E13
- DQ 1.0E14
- DQ 1.0E15
- DQ 1.0E16
- DQ 1.0E17
- DQ 1.0E18
- FPST ENDP
-
- ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- ;Keyboard Routines
- ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- ;Get chracter from keyboard without echo. Return ASCII code or scan code in AL.
- ;The sign bit of AH is set if a scan code. The state of the shift keys is also
- ;in AH. Bits of AH are defined: 0 = shift, 1 = ctrl, 2 = alt, 3 = scroll lock,
- ;4 = num lock, 5 = caps lock, 6 = insert. The high word of EAX is cleared.
- ;Interrupts must be enabled.
- GETCH PROC NEAR
- PUSH EDX
- MOV AH,10H ;Remove key from type-ahead buffer. Will wait if no key present
- INT 16H ;Scan code in AH, ASCII code in AL
- MOV EDX,EAX
- MOV AH,12H ;Get state of flags
- INT 16H
- TEST AL,01H ;Combine right and left shift keys
- JZ FIXFLAGS
- OR AL,02H
- FIXFLAGS: SHR AL,1
- AND EAX,07FH
- MOV AH,AL
- MOV AL,DL ;Put ASCII scan code in AL
- CMP AL,0E0H ;See if the character is for non-ASCII enhanced keyboard key
- JE DOSCAN
- OR AL,AL ;See if the character is for a non-ASCII key
- JNZ EXIT
- DOSCAN: MOV AL,DH ;Put scan code in AL
- OR AH,80H ;Set high bit to denote scan code
- EXIT: POP EDX
- RET
- GETCH ENDP
-
- ;Set cursor position at (row,col) = (AH,AL).
- SETCSRPOS PROC NEAR
- PUSH EAX
- PUSH EBX
- PUSH EDX
- CMP AH,24 ;Do not allow row greater than 24
- JBE CHKCOL
- MOV AH,24
- CHKCOL: CMP AL,79 ;Do not allow column greater than 79
- JBE SETCURSOR
- MOV AL,79
- SETCURSOR: MOV EDX,EAX ;Place coordinates in DX
- XOR EBX,EBX ;Use screen zero
- MOV AH,02H ;Function to set cursor position
- INT 10H
- POP EDX
- POP EBX
- POP EAX
- RET
- SETCSRPOS ENDP
-
- ;Get cursor position in (AH,AL) = (row,col)
- GETCSRPOS PROC NEAR
- PUSH EBX
- PUSH ECX
- PUSH EDX
- MOV AH,03H ;Function to get cursor position
- XOR EBX,EBX ;Get position for screen zero
- INT 10H ;Cursor position returned in DX, and type returned in CX
- MOV EAX,EDX
- POP EDX
- POP ECX
- POP EBX
- RET
- GETCSRPOS ENDP
-
- ;Physically relocate the cursor on the screen to the current BIOS coordinates.
- UPDATECSR PROC NEAR
- PUSHD OFFSET SETCSRPOS
- JMP GETCSRPOS
- UPDATECSR ENDP
-
- ;Set cursor type. Call with AL = 1 for block, AL = 0 for underline, and sign
- ;bit of AL set to disable.
- SETCSRTYPE PROC NEAR
- PUSH EAX
- PUSH ECX
- MOV AH,01H
- MOV CX,0607H ;Assume underline cursor
- OR AL,AL
- JZ SETCURLINES
- JS DISABLECSR
- XOR CH,CH ;Set to block cursor
- JMP SETCURLINES
- DISABLECSR: MOV CH,20H ;Disable cursor
- SETCURLINES: INT 10H
- POP ECX
- POP EAX
- RET
- SETCSRTYPE ENDP
-
- ;Get cursor position and type. Position in DX and type in CX.
- GETCSR PROC NEAR
- PUSH EAX
- PUSH EBX
- MOV AH,03H ;Function to get cursor position
- XOR EBX,EBX ;BH = page
- INT 10H ;(start,end) scan line for cursor in (CH,CL)
- POP EBX ;(row/column) for cursor in (DH,DL)
- POP EAX
- RET
- GETCSR ENDP
-
- ;Set cursor position and type. Call with (DH,DL) = (row,col) for cursor and
- ;(CH,CL) = (start,end) scan line for cursor.
- SETCSR PROC NEAR
- PUSH EAX
- PUSH EBX
- MOV AH,02H ;Set cursor position
- XOR EBX,EBX ;Use page zero
- INT 10H
- DEC AH ;Set cursor type
- INT 10H
- POP EBX
- POP EAX
- RET
- SETCSR ENDP
-
- ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- ;Speaker Routines
- ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- ;Produce beep through speaker. Interrupts must be enabled.
- BEEP PROC NEAR
- PUSH EAX
- PUSH EDX
- IN AL,61H
- MOV DX,6818 ;175 cycles/second
- CALL SOUND
- MOV EDX,TICKCNTADR ;Hold sound for four ticks
- PUSH EAX
- MOV EAX,[EDX]
- ADD EAX,4
- DELAY: CMP [EDX],EAX ;Will hang in this loop timer-tick interrupt not enabled
- JNE DELAY
- POP EAX ;Disable sound
- OUT 61H,AL
- POP EDX
- POP EAX
- RET
- BEEP ENDP
-
- ;Activate speaker. Call with frequency divisor in DX. Divisor = 1,193,180
- ;divided by cycles per second.
- SOUND PROC NEAR
- PUSH EAX
- MOV AL,10110110B ;Channel 2, LSB/MSB, mode 3, binary
- OUT 43H,AL ;Program the timer
- MOV EAX,EDX
- OUT 42H,AL
- MOV AL,AH
- OUT 42H,AL
- IN AL,61H
- OR AL,03H ;Enable speaker and use channel 2 for input
- OUT 61H,AL
- POP EAX
- RET
- SOUND ENDP
-