📄 电子琴.txt
字号:
六、源程序
;程序主要功能是电子琴,创新之处:实现了录音,编曲的功能
;当按‘8’是播放系统音乐功能;按‘0’的表示编曲开始,按‘9’表示编曲结束。按‘A’表示播放编曲功能。
STACK SEGMENT
DB 100
STACK ENDS
DATA SEGMENT
IOPORT EQU 0C400H-0280H
PORT0 EQU IOPORT+2B0H ;8279 DATA PORT
PORT1 EQU IOPORT+2B1H ;8279 CTRL PORT
LED DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH,77H,7CH,39H,
DB 5EH,79H,71H,67H,37H,73H,31H,3EH,36H,66H
IO8253A EQU IOPORT+280H
IO8253B EQU IOPORT+283H
IO8255A EQU IOPORT+288H
IO8255B EQU IOPORT+28BH
IO0832A EQU IOPORT+290H
DATA1 DB 80H,96H,0AEH,0C5H,0D8H,0E9H,0F5H,0FDH
DB 0FFH,0FDH,0F5H,0E9H,0D8H,0C5H,0AEH,96H
DB 80H,66H,4EH,38H,25H,15H,09H,04H
DB 00H,04H,09H,15H,25H,38H,4EH,66H ;正弦波数据
TIME DB 120,106,95,89,80,70,63,59 ;发不同音时8253的计数器初值
MSG1 DB 'PLEASE PRESS 0,1,2,3,4,5,6,7,8,R:',0DH,0AH
DB '0=RESET MUSIC AND END WITH 9',0DH,0AH
DB '8=PLAY MUSIC',0DH,0AH
DB 'A=PLAY RECORD MUSIC',0DH,0AH
DB 'R=RETURN TO DOS',0DH,0AH,'$'
MSG2 DB 'INPUT ERROR',0DH,0AH,'$'
MSG3 DB 'INPUT YOUR MUSIC',0DH,0AH,'$'
NUM DB ? ;NUM为8253计数器初值的序号
BUFF DB 3FH
MUSIC DB 80 DUP(?)
MUSIC1 DB 1,2,3,1,1,2,3,1,3,4,5,3,4,5,5,6,5,4,3,1,5,6,5,4,3,1,1,5,1,9
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA,SS:STACK
MAIN PROC NEAR
START: CLI
MOV AX,DATA
MOV DS,AX
MOV AX,CS
MOV DS,AX
MOV DX,PORT1
MOV AL,0D3H
OUT DX,AL ;8279 CLEAR
MOV AL,2AH
OUT DX,AL ;8279 CLOCK
MOV AL,40H
OUT DX,AL ;READ FIFO RAM COMMAND
MOV AL,00H
OUT DX,AL ;KEYBORD DISPLY MODE
MOV AL,80H
OUT DX,AL ;WRITE RAM COMMAND
CALL DISP
RE: LEA DX,MSG1
MOV AH,09H
INT 21H
KEY1: CALL KEY2 ;CALL KEYBORD AND DISPLY AND SOUND
LP0: CMP AL,13H ;'R' COMMAND
JNZ LP1
MOV AX,4C00H ;QUIT TO DOS
INT 21H
LP1: CMP AL,0
JE RES
CMP AL,8
JE MUS1
CMP AL,0AH
JE MUS2
CMP AL,09H
JE RE
CMP AL,1
JB ERR
CMP AL,7
JA ERR
CALL SOUND
JMP KEY1
RES: LEA DX,MSG3
MOV AH,09H
INT 21H
MOV DI,OFFSET MUSIC
RES1: CALL KEY2
CMP AL,1
JB ERR
CMP AL,9
JA ERR
MOV [DI],AL
CMP AL,9
JE RE
CALL SOUND
INC DI
JMP RES1
MUS2: LEA DI,MUSIC
JMP MUSI
MUS1: LEA DI,MUSIC1
MUSI: MOV AL,[DI]
CMP AL,9
JZ RE
MOV BUFF,AL
CALL SOUND
INC DI
JMP MUSI
ERR: LEA DX,MSG2
MOV AH,09H
INT 21H
LEA DX,MSG1
INT 21H
JMP KEY1
MAIN ENDP
KEY2 PROC NEAR
MOV DX,PORT1
MOV AL,0D1H
OUT DX,AL ;CLEAR DISPLAY
WREP: MOV DX,PORT1
IN AL,DX
AND AL,07H
JZ WREP
KEYN: MOV DX,PORT0
IN AL,DX
MOV BL,AL
AND AL,07H
AND BL,38H
MOV CL,03
SHR BL,CL
CMP BL,00H
JNZ LINE1
ADD AL,08H
JMP QUIT1
LINE1:CMP BL,01H
JNZ LINE2
JMP QUIT1
LINE2:ADD AL,10H
QUIT1:MOV BUFF,AL
RET
KEY2 ENDP
DISP PROC NEAR
PUSH AX
MOV AX,DATA
MOV DS,AX
MOV DX,PORT1
MOV AL,80H ;写显示RAM控制字,AI=1,地址自动加
OUT DX,AL
LEA SI,BUFF
LEA BX,LED
DISP1:MOV AL,[SI]
XLAT
MOV DX,PORT0
OUT DX,AL
POP AX
RET
DISP ENDP
SOUND PROC NEAR
CALL DISP
MOV NUM,AL ;求出相应的时间常数的序号
MOV CX,60 ;取60次32个正弦波数据
DDD: MOV SI,0
LLL: MOV AL,DATA1[SI] ;取正弦波数据
MOV DX,IO0832A
OUT DX,AL ;放音
CALL DELAY ;调延时子程序
INC SI
CMP SI,32 ;是否取完32个数据
JL LLL ;若没有,则继续
LOOP DDD ;总循环次数60是否完,没有,则继续
EXIT: RET
SOUND ENDP
DELAY PROC NEAR ;延时子程序
CCC: MOV BX,OFFSET TIME
MOV DX,IO8253B ;置8253通道0为方式0工作
MOV AL,10H
OUT DX,AL
MOV DX,IO8255B ;设8255A口输入
MOV AL,9BH
OUT DX,AL
MOV AL,NUM ;取相应的时间常数
XLAT
MOV DX,IO8253A
OUT DX,AL ;向8253通道0输出
KKK: MOV DX,IO8255A
IN AL,DX ;从8255A口读一字节
TEST AL,01 ;判PA0口是否为1
JZ KKK ;若不为1,则转KKK
RET ;子程序返回
DELAY ENDP
CODE ENDS
END START
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -