📄 dianziqin.asm
字号:
;载入键在屏幕上的位置
CMP KEYFLAG,00H ;判断是否是低音键
JNZ LOAD_HGH ;继续判断
LEA SI,ST_LX ;载入低音键起始坐标首地址
LEA DI,ED_LX ;载入低音键结束坐标首地址
JMP LOAD_END ;载入结束
LOAD_HGH:
CMP KEYFLAG,02H ;判断是否是高音键
JNZ LOAD_MID ;继续判断
LEA SI,ST_HX ;载入高音键起始坐标首地址
LEA DI,ED_HX ;载入高音键结束坐标首地址
JMP LOAD_END
LOAD_MID:
LEA SI,ST_MX ;载入中音键起始坐标首地址
LEA DI,ED_MX ;载入中音键结束坐标首地址
LOAD_END:
RET
LOAD ENDP
SCAN_KEY PROC NEAR
;检查按键状态,并存入对应的变量和寄存器
MOV SI,100
MOV DI,100
MOV KEYNUM,100 ;赋初值
MOV AH,0 ;读键盘
INT 16H
MOV DL,AH
CALL SCAN_SONG ;判断是否是自动播放键(大键盘数字键1~5)
CALL SCAN_TUNE ;判断是否是C/D调选择键
CALL FREQ_CHANGE ;判断是否按下频率改变键:(+/- 符号)
CMP AH,01H ;是否是结束键
JNE FLAG_SCAN ;若不是继续检测
CALL EXIT ;若是则退出
FLAG_SCAN:
MOV AH,02H ;读键盘状态字节
INT 16H
MOV DH,AL ;判断是否是右shift键
AND DH,01H
CMP DH,01H
JE SLOW ;是则进行低音处理
MOV DH,AL ;不是判断是否是左shift键
AND DH,02H
CMP DH,02H
JE SHGH ;是则进行高音处理
JMP SMID ;都不是进行中音处理
SLOW: ;低音处理
MOV AUDIO,1
MOV KEYFLAG,0
JMP KEY_1 ;跳转到音键处理
SHGH: ;高音处理
MOV AUDIO,3
MOV KEYFLAG,2
JMP KEY_1 ;跳转到音键处理
SMID : ;中音处理
MOV AUDIO,2
MOV KEYFLAG,1
KEY_1:
CMP DL,4FH ;是否是1
JNE KEY_2 ;继续判断
MOV KEYNUM,0 ;不是则保存标志
JMP SCAN_END ;键扫描结束
KEY_2:
CMP DL,50H ; 是否是2
JNE KEY_3
MOV KEYNUM,2
JMP SCAN_END
KEY_3:
CMP DL,51H ; 是否是3
JNE KEY_4
MOV KEYNUM,4
JMP SCAN_END
KEY_4:
CMP DL,4BH ; 是否是4
JNE KEY_5
MOV KEYNUM,6
JMP SCAN_END
KEY_5:
CMP DL,48H ; 是否是5
JNE KEY_6
MOV KEYNUM,8
JMP SCAN_END
KEY_6:
CMP DL,4DH ; 是否是6
JNE KEY_7
MOV KEYNUM,10
JMP SCAN_END
KEY_7:
CMP DL,47H ; 是否是7
JNE SCAN_END
MOV KEYNUM,12
SCAN_END:
RET
SCAN_KEY ENDP
SCAN_SONG PROC NEAR
;判断是否是自动播放键(键1~5),并保存标志变量(song)
;IN: AH 键扫描码
PUSH AX
MOV SONG,100 ;赋初始值
CMP AH,3BH ;与1比较
JB SONG_END ;小于1则结束
CMP AH,3FH ;与5比较
JA SONG_END ;大于则结束
SUB AH,3Bh ;转换成1~5
MOV AL,AH
MOV AH,00H
MOV SONG,AX ;存入标志码
SONG_END:
POP AX
RET
SCAN_SONG ENDP
PLAY_SONG PROC NEAR
;选择并播放音乐
PUSH BP
PUSH SI
PUSH BX
PUSH DI
PUSH AX
CMP SONG,01H ;判断是否是歌1
JNE GO2 ;不是继续判断
CALL SONG_LIGHT_OFF ;灯1~5灭
DRAW 247,42,251,46,0EH ;灯1亮
LEA BP,MUS_TIME1 ;载入延时数据首地址
LEA SI,MUS_FREQ1 ;载入频率数据首地址
JMP FREQ
GO2:
CMP SONG,02H ;判断是否是歌2
JNE GO3
CALL SONG_LIGHT_OFF
DRAW 253,42,257,46,0EH
LEA BP,MUS_TIME2
LEA SI,MUS_FREQ2
JMP FREQ
GO3:
CMP SONG,03H ;判断是否是歌3
JNE GO4
CALL SONG_LIGHT_OFF
DRAW 259,42,263,46,0EH
LEA BP,MUS_TIME3
LEA SI,MUS_FREQ3
JMP FREQ
GO4:
CMP SONG,04H ;判断是否是歌4
JNE GO5
CALL SONG_LIGHT_OFF
DRAW 265,42,269,46,0EH
LEA BP,MUS_TIME4
LEA SI,MUS_FREQ4
JMP FREQ
GO5:
CMP SONG,05H ;判断是否是歌5
JNE FREQ
CALL SONG_LIGHT_OFF
DRAW 271,42,275,46,0EH
LEA BP,MUS_TIME5
LEA SI,MUS_FREQ5
FREQ:
MOV AH,01H ;读键盘缓冲区字符
INT 16H
CMP AH,1CH ;是否是Enter键
JNZ CONTINUE ;不是继续
JMP PLAY_END ;是结自动播放
CONTINUE:
MOV AH,0CH ;清除键盘缓冲区字符
MOV AL,06H
INT 21H
MOV DI,[SI]
CMP DI,-1 ;判断结束否
JE PLAY_END
MOV BX,[BP]
CALL GEN_AUTO ;发声
ADD SI,2
ADD BP,2 ;下一频率
JMP FREQ
PLAY_END:
CALL SONG_LIGHT_OFF
POP AX
POP DI
POP BX
POP SI
POP BP
RET
PLAY_SONG ENDP
LOAD_AUDIO PROC NEAR
;C\D调及对应的低、中、高频率分别载入
;OUT:BX
;IN:TUNE,AUDIO
TUNE_D: ;D大调判断
CMP TUNE,'D'
JNZ TUNE_CL ;不是判断是否是C调
TUNE_DL:
CMP AUDIO,1 ;低频判断
JNE TUNE_CM
LEA BX,LOWDD
JMP AUDIO_END
TUNE_DM:
CMP AUDIO,2 ;中频判断
JNE TUNE_CH
LEA BX,MIDD
JMP AUDIO_END
TUNE_DH:
LEA BX,HGHD ;高频判断
JMP AUDIO_END
TUNE_CL: ;C调处理
CMP AUDIO,1
JNE TUNE_CM
LEA BX,LOWD
JMP AUDIO_END
TUNE_CM:
CMP AUDIO,2
JNE TUNE_CH
LEA BX,MID
JMP AUDIO_END
TUNE_CH:
LEA BX,HGH
AUDIO_END:
RET
LOAD_AUDIO ENDP
SCAN_TUNE PROC NEAR
;C\D调判断及其状态在屏幕上的显示
;IN:DL 键盘扫描码
;OUT:TUNE
CMP DL,2EH ;判断是C否
JNZ NEXT_D ;不是则判断是D否
MOV TUNE,'C'
DRAW 55,38,60,41,0EH ;关D灯
DRAW 65,38,70,41,0AH ;开C灯
JMP TUNE_END ;结束
NEXT_D:
CMP DL,20H ;判断D否
JNZ TUNE_END
MOV TUNE,'D'
DRAW 55,38,60,41,0AH ;开D灯
DRAW 65,38,70,41,0EH ;关C灯
TUNE_END:
RET
SCAN_TUNE ENDP
SHOW_TEXT PROC NEAR
;在屏幕上显示字符
LEA DI,TEXT ;载入字符串首地址
MOV DH,[DI] ;赋行值
INC DI ;取得列
MOV DL,[DI] ;赋列值
MOV START_COL,DL ;保存开始列
MOV AH,2 ;设置光标位置
MOV BH,0 ;0页
INT 10H
INC DI ;取得颜色值
MOV BL,[DI] ;赋颜色值
CHAR_WRITE:
INC DI ;取得要显示的字符
MOV AL,[DI]
CMP AL,0FFH ;行结束否
JE BUMP_ROW ;下一行
CMP AL,0 ;结束否
JZ END_TEXT
CALL SHOW_CHAR ;显示字符
JMP CHAR_WRITE ;下一个字符
END_TEXT:
RET
BUMP_ROW:
INC DH ;下一行
MOV DL,START_COL ;赋开始列值
MOV AH,2 ;设光标位置
MOV BH,0
INT 10H
JMP CHAR_WRITE
SHOW_TEXT ENDP
SHOW_CHAR PROC NEAR
;显示字符
MOV AH,9 ;显示字符
MOV BH,0 ;0页
MOV CX,1
INT 10H
INC DL
MOV AH,2 ;设置光标位置
MOV BH,0 ;0页
INT 10H
RET
SHOW_CHAR ENDP
INIT PROC NEAR
;初始化屏幕:画琴键
MOV AX,DATA
MOV DS,AX
MOV AH,0 ;设置屏幕
MOV AL,0DH
INT 10H
MOV AH,0BH
MOV BH,0
MOV BL,00H ;背景色
INT 10H
CALL SHOW_TEXT ;显示字符串
DRAW 45,30,285,94,05H
DRAWSQRE 45,30,285,94,0DH
DRAWSQRE 49,48,280,49,00H
DRAW 55,38,60,41,0EH ;C调灯
DRAW 65,38,70,41,0AH ;D调灯
CALL SONG_LIGHT_OFF ;自动播放歌指示灯关
LEA SI,ST_LX ;画21个白色键
LEA DI,ED_LX
MOV CX,21
INIT_DRAW:
DRAW [SI],ST_Y,[DI],ED_Y,0FH
DRAW [SI],90,[DI],93,07H ;阴影
ADD SI,2
ADD DI,2
LOOP INIT_DRAW
LEA SI,BT_X ;画15个黑色键
LEA DI,BD_X
MOV CX,15
INIT_BLOCK:
DRAW [SI],BT_Y,[DI],BD_Y,00H
ADD SI,2
ADD DI,2
LOOP INIT_BLOCK
RET
INIT ENDP
SONG_LIGHT_OFF PROC NEAR
;关闭灯1~5
DRAW 271,42,275,46,09H
DRAW 265,42,269,46,09H
DRAW 259,42,263,46,09H
DRAW 253,42,257,46,09H
DRAW 247,42,251,46,09H
RET
SONG_LIGHT_OFF ENDP
FREQ_CHANGE PROC NEAR
;IN:DL 扫描码
CMP DELAY_TIME,600
JB CHANGE_ADD
CMP DELAY_TIME,60000
JA CHANGE_SUB
CMP DL,0CH ;-
JNZ FREQ_SUB
ADD DELAY_TIME,500
DRAW 271,38,274,41,0EH
JMP CHANGE_END
CHANGE_ADD:
ADD DELAY_TIME,500
JMP CHANGE_END
CHANGE_SUB:
SUB DELAY_TIME,500
JMP CHANGE_END
FREQ_SUB:
CMP DL,0DH ;+
DRAW 271,38,274,41,0AH
JNZ CHANGE_END
SUB DELAY_TIME,500
CHANGE_END:
RET
FREQ_CHANGE ENDP
EXIT PROC NEAR
;程序结束
MOV AH,4CH
INT 21H
RET
EXIT ENDP
CODE ENDS
END START
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -