汇编课设(电子钢琴:源代码)
实现结果
程序的启动有点像小霸王游戏机的游戏,喜欢汇编的朋友可以发信与我一起讨论,发声程序参考的是一本汇编教材,程序写作和上传相隔有点久远,记不太清,千行代码,算是学生时代一个比较得意的课设
编译器下载
编译器可在我的上传资源中查找,已注明:汇编编译器
https://download.csdn.net/download/m0_37772174/10837741
注意事项
输入严格区分大小写,启动时应输入大写来C启动复杂版钢琴
汇编代码
;作者:cclplus
;仅供学习交流使用
DATA SEGMENT
MEM1 DW 200 DUP(0)
MEM2 DW 200 DUP(0);用于记录输入
Gao1 DB 0AH, 0DH, 'Hello User.THIS IS GMusic!'
DB 0AH, 0DH, 'Enjoy music!$'
Gao2 DB 0AH, 0DH, 'INPUT ERROR!$'
Gao3 DB 0AH, 0DH, 'PLEASE INPUT AGAIN!$'
Cue_list DB 0AH, 0DH, '*****************************'
DB 0AH, 0DH, 'PressB Begin your music lite'
DB 0AH,0DH,'PressC Begin your music Gao'
DB 0AH, 0DH, 'PressP Play back'
DB 0AH, 0DH, '*****************************'
DB 0AH, 0DH, '$'
soundcolor dw 0 ;音色缓存,用于改变播放或弹奏时琴上音响和琴面上点阵的颜色
key_tune dw 0 ;按键状态缓存,用于判断是否有手动按键,1为有,0为无
keynum dw 1 ;按键编号缓存,用于提取对应的按键位置
delay_time dw 7000 ;延时缓存,用于播放时存入bx中来计数
count dw 0;
;------------------------------进度条字符-----------------------
st_load db 10 ;起始行
db 4 ;起始列
db 0bh ;字体颜色
db 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII'
db 00
;------------------------------字符定义-----------------------
start_col db ? ;存储起始行
text db 14 ;起始行
db 2 ;起始列
db 0fh ;字体颜色
db 'MUSIC ^_^',0ffh,0ffh ;显示字
db ' HAVE A GOOD TIME!',0ffh ;以0ffh来判断是否换行
db ' [-1-2-3-4-5-6-7-8-]',0ffh
db 'Press p: replay',0ffh
db 'Press Esc: exit',0ffh
db 00
d_text db 14 ;起始行
db 2 ;起始列
db 0fh ;字体颜色
db 'MUSIC ^_^',0ffh,0ffh ;显示字
db ' HAVE A GOOD TIME!',0ffh ;以0ffh来判断是否换行
db ' [-1-2-3-4-5-6-7-]',0ffh
db 'g [ q w e r t y u ] p:replay ',0ffh
db 'z [ a s d f g h j ] enter: stop',0ffh
db 'd [ z x c v b n m ] Esc: exit',0ffh
db 00
;------------------------------高级版白色琴键坐标-------------------
d_st_lx dw 50,61,72,83,94,105,116 ;起点横坐标
dw 127,138,149,160,171,182,193
dw 204,215,226,237,248,259,270
d_st_y dw 50 ;起点纵坐标
d_ed_lx dw 60,71,82,93,104,115,126 ;终点横坐标
dw 137,148,159,170,181,192,203
dw 214,225,236,247,258,269,280
d_ed_y dw 90 ;终点纵坐标
;------------------------------高级版黑色琴键坐标--------------------------
d_bt_x dw 57,68,90,101,112 ;起点横坐标
dw 134,145,167,178,189
dw 211,222,244,254,265
d_bt_y dw 50 ;起点纵坐标
d_bd_x dw 64,75,97,108,119 ;终点横坐标
dw 141,152,174,185,196
dw 218,229,251,262,273
d_bd_y dw 70
;----------------------------简版乐器白色琴键坐标-------------------
st_lx dw 50,80,110,140,170,200,230,260 ;起点横坐标
st_y dw 50 ;起点纵坐标
ed_lx dw 70,100,130,160,190,220,250,280 ;终点横坐标
ed_y dw 90 ;终点纵坐标
;----------------------------简版乐器黑色琴键坐标--------------------------
bt_x dw 71,101,131,161,191,221,251 ;起点横坐标
bt_y dw 50 ;起点纵坐标
bd_x dw 79,109,139,169,199,229 ,259 ;终点横坐标
bd_y dw 70 ;终点纵坐标
;频率列表
;---------------------------高级版音乐频率值----------------------------
d_tune dw 220,247,278,294,330,371,416 ;低音
dw 441,495,556,589,661,742,833 ;中音
dw 882,990,1112,1178,1322,1484,1655 ;高音
;---------简版
TUNE DW 262, 294, 330, 347, 392, 440, 494, 523
DATA ENDS
STACK SEGMENT PARA STACK 'STACK'
STA DB 300 DUP('STACK')
STACK ENDS
CODE SEGMENT
ASSUME DS: DATA, SS: STACK, CS: CODE, ES: DATA
START: MOV DI ,0H
MOV AX, DATA
MOV DS, AX
MOV ES, AX
MOV AX, STACK
MOV SS, AX
SHOW MACRO B
MOV DX, OFFSET B
MOV AH, 09H
INT 21H;显示字符串
ENDM
SHOW Gao1 ;显示Gao1中的内容
LOP: SHOW Cue_list;显示操作提示清单
MOV AH, 01H
INT 21H;从键盘上输入一个字符,将其对应字符的ASCII码送入AL中
;并在屏幕上显示该字符
CMP AL, 42H ;判断键盘上的值是否为B(区分大小写)
JNZ sc;如果键盘上的内容不是B,检查是否是C
JMP LITE_v;如果输入了B,那么我们进入简版的音乐演奏器
SC: cmp al,43h;判断键盘上的值是否是C,如果是C,进入高级音乐演奏器
JNE LEXIT;
;高级音乐演奏器启动
GAO_V:
;---依次调用:开场效果--初始化--键盘扫描--按键处理程序-------------
call show_load ;调用进度条显示程序
;---延时20*waitf----
push bx
mov bx,20
d_del:
call waitf
dec bx
jnz d_del
pop bx
;-----------不一样的重新开始-------
d_restart: ;自动播放音乐时,按‘enter’键或音乐完全结束后会返回这里
PUSH AX
PUSH BX
PUSH CX
PUSH DX
PUSH BP
call d_init ;调用不一样的初始化程序
POP BP
POP DX
POP CX
POP BX
POP AX
d_new_scan: ;键盘扫描程序没有检测到功能键被按下时,会返回这里
call d_scan_key ;调用键盘扫描程序,扫描所按下的键
CALL REMEMBER
;-----------按键处理-------
call d_do_key
;----重新扫描---
jmp d_new_scan ;重新扫描有无键按下,直到按下esc键
;高级音乐演奏器程序截止
;-*-*-*-*-*--*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*--*-*-*-*-*-*-*
;简版音乐启动
LITE_v: CALL SHOW_LOAD
push bx
mov bx,20
del:
call waitf
dec bx
jnz del
pop bx
restart: ;自动播放音乐时,按‘enter’键或音乐完全结束后会返回这里
call init
new_scan: ;键盘扫描程序没有检测到功能键被按下时,会返回这里
call scan_key ;调用键盘扫描程序,扫描所按下的键
CALL REMEMBER
call do_key;进行按键处理
jmp new_scan ;----重新扫描---
replay proc near
push ax
push cx
PUSH SI
mov cx,count
mov di,0
replay1:
push ax
mov ax,700000
mov delay_time,ax
pop ax
replay2:
push di
MOV si,MEM1[DI]
mov ax,mem2[di]
mov keynum,ax
call do_key
call waitf
pop di
inc di
inc di
cmp CX,DI
JA replay2
POP SI
pop cx
pop ax
ret
replay endp
d_replay proc near
push ax
push cx
PUSH SI
mov cx,count
mov di,0
dreplay1:
push ax
mov ax,700000
mov delay_time,ax
pop ax
dreplay2:
push di
MOV si,MEM1[DI]
mov ax,mem2[di]
mov keynum,ax
call d_do_key
call waitf
pop di
inc di
inc di
cmp CX,DI
JA dreplay2
POP SI
pop cx
pop ax
JMP d_new_scan
d_replay endp
remember proc near
push cx
PUSH SI
push ax
mov cx,count
mov DI,CX
MOV MEM1[DI],SI
MOV AX,keynum
MOV MEM2[DI],AX
INC CX
inc cx
mov count,cx
pop ax
POP SI
pop cx
ret
remember endp
;**********************************矩形绘制宏*******************************
draw macro start_x,start_y,end_x,end_y,color
local draw_next
;local :避免宏重复调用时,标号的重复
;功能:画填充的矩形
;使用条件:start_x < end_x ,start_y < end_y
push ax ;堆栈
push bx
push cx
push dx
mov ah,0ch ;12号功能,写像素
mov al,color ;取颜色值
mov bh,0 ;页号0
mov cx,start_x ;列起始点
mov dx,start_y ;行起始点
draw_next:
int 10h ;画点
inc cx ;画横线
cmp cx,end_x ;比较行是否画完
jne draw_next ;画另一行
mov cx, start_x ;另一行的起始点
inc dx ;下一行
cmp dx,end_y ;比较列是否画完
jne draw_next ;未完继续画
pop dx ;出栈
pop cx
pop bx
pop ax
endm
;********************************矩形点阵绘制宏****************************
draw_point macro start_x,start_y,end_x,end_y,color
local draw_next
;local :避免宏重复调用时,标号的重复
;功能:画矩形点阵
;使用条件:start_x < end_x ,start_y < end_y
push ax
push bx
push cx
push dx
mov ah,0ch ;12号功能,写像素
mov al,color ;设置颜色
mov bh,0 ;页号0
mov cx,start_x ;列起始点
mov dx,start_y ;行起始点
draw_next:
int 10h ;画点
inc cx
inc cx ;隔一点
cmp cx,end_x ;比较行是否画完
jne draw_next ;画另一行
mov cx, start_x ;另一行的起始点
inc dx
inc dx ;隔一行
cmp dx,end_y ;比较列是否画完
jne draw_next ;未完继续画
pop dx
pop cx
pop bx
pop ax
endm
;****************************矩形框绘制宏****************************
drawsqre macro start_x,start_y,end_x,end_y,color
local row_up,row_down,rank_left,rank_right
;--功能:画矩形框。
push ax
push bx
push cx
push dx
push si
mov ah,0ch ;12号功能,写像素
mov al,color
mov bh,0
mov cx,start_x
mov dx,start_y
row_up: ;画上边
int 10h
inc cx
cmp cx,end_x
jne row_up
rank_right: ;画右边
int 10h
inc dx
cmp dx,end_y
jne rank_right
mov cx, start_x ;下边起始点
mov si,end_x
inc si
row_down: ;画下边
int 10h
inc cx
cmp cx,si
jne row_down
mov dx,start_y ;左边起始点
mov cx,start_x
rank_left: ;画左边
int 10h
inc dx
cmp dx, end_y
jne rank_left
pop si
pop dx
pop cx
pop bx
pop ax
endm
;*************************在屏幕上显示字符************************
;--功能:显示字符和说明。
show_text proc near
;--------------------初始化光标的位置----------
lea di,text ;载入字符串首地址
mov dh,[di] ;2号功能,赋行值
inc di ;取得列
mov dl,[di] ;2号功能,赋列值
mov start_col,dl ;保存开始列
mov ah,2 ;2号功能,设置光标位置,dh=行号;dl=列号;bh=页号
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 ;2号功能,下一行
mov dl,start_col ;2号功能,赋开始列值
mov ah,2 ;2号功能,设光标位置
mov bh,0 ;2号功能,页号
int 10h
jmp char_write
show_text endp
;*************************在高级演奏器屏幕上显示字符************************
;--功能:显示字符和说明。
show_d_text proc near
;--------------------初始化光标的位置----------
lea di,d_text ;载入字符串首地址
mov dh,[di] ;2号功能,赋行值
inc di ;取得列
mov dl,[di] ;2号功能,赋列值
mov start_col,dl ;保存开始列
mov ah,2 ;2号功能,设置光标位置,dh=行号;dl=列号;bh=页号
mov bh,0 ;0页
int 10h
;---------------取颜色值-------------
inc di ;取得颜色值
mov bl,[di] ;赋颜色值
;---------------显示字符--------------
d_char_write:
inc di ;取得要显示的字符
mov al,[di]
cmp al,0ffh ;行结束否
je d_bump_row ;下一行
cmp al,0 ;结束否
jz end_text
call show_char ;显示字符
jmp d_char_write ;下一个字符
end_text:
ret
;---光标下移一行---
d_bump_row:
inc dh ;2号功能,下一行
mov dl,start_col ;2号功能,赋开始列值
mov ah,2 ;2号功能,设光标位置
mov bh,0 ;2号功能,页号
int 10h
jmp d_char_write
show_d_text endp
;***********************显示字符************************
;--功能:横向显示字符。
show_char proc near
push ax
push bx
push cx
mov ah,9 ;9号功能,显示字符bl=字符属性,bh=页号;al=字符ASCII码;cx=写入字符数
mov bh,0 ;0页
mov cx,1 ;写入一个字符
int 10h
inc dl ;2号功能,赋列值,这里为光标右移一个字符位
mov ah,2 ;设置光标位置
mov bh,0 ;0页
int 10h
pop cx
pop bx
pop ax
ret
show_char endp
;***********************初始化*****************************
;--功能:初始化屏幕和显示,显示字符说明,绘制出电子琴。
init proc near
mov ax,data
mov ds,ax
;------------屏幕以及显示初始化-------------
mov ah,0 ;0号功能,设置屏幕
mov al,0dh ;文本分辨率40*25;像素框8*8;像素分辨率320*200;颜色16
int 10h
mov ah,0bh ;11号功能,设置背景颜色,bh=0时,设置背景颜色
mov bh,0
mov bl,00h ;背景色
int 10h
;------------------显示字符说明------------------
call show_text ;显示字符串
;------------------绘制电子琴------------------
call draw_dzq ;绘制琴身和底座
ret
init endp
;************绘制电子琴***************
;--功能:绘制琴身和底座,黑白键,效果灯
draw_dzq proc near
draw_point 40,52,44,92,07h ;调用矩形点阵宏,绘制音响孔左
draw_point 288,52,292,92,07h ;调用矩形点阵宏,绘制音响孔右
drawsqre 38,50,292,92,07h ;调用矩形框绘制宏,绘制音响框
drawsqre 44,30,286,93,07h ;调用矩形框绘制宏,绘制底框1
draw 45,30,285,94,08h ;调用矩形绘制宏,绘制琴身颜色
drawsqre 45,30,285,94,07h ;调用矩形框绘制宏,绘制底框2
draw_point 150,34,282,38,07h ;调用矩形点阵宏,绘制正面音孔
drawsqre 46,31,284,32,00h ;调用矩形框绘制宏,绘制琴上边
drawsqre 49,48,280,49,00h ;调用矩形框绘制宏,绘制琴挡
draw 55,38,60,41,0ah ;调用矩形绘制宏,绘制灯1
draw 65,38,70,41,07h ;调用矩形绘制宏,绘制灯2
draw 271,42,275,46,07h ;调用矩形绘制宏,绘制5个指示灯
draw 265,42,269,46,07h
draw 259,42,263,46,07h
draw 253,42,257,46,07h
draw 247,42,251,46,07h
;----绘制白键----
lea si,st_lx ;画8个白色键
lea di,ed_lx
mov cx,8
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 ;画7个黑色键
lea di,bd_x
mov cx,7
init_block:
draw [si],bt_y,[di],bd_y,00h ;调用矩形绘制宏,绘制黑色矩形作为黑键
add si,2
add di,2
loop init_block
RET
draw_dzq ENDP
;*************************进度条显示程序************************
;---功能:程序启动时,显示动态进度条,快慢与waitf子程序有关
show_load proc near
mov ax,data
mov ds,ax
mov ah,0 ;0号功能,设置屏幕
mov al,0dh ;文本分辨率40*25;像素框8*8;像素分辨率320*200;颜色16
int 10h
mov ah,0bh ;11号功能,设置背景颜色,bh=0时,设置背景颜色
mov bh,0
mov bl,00h ;背景色
int 10h
;--------------------初始化光标的位置----------
lea di,st_load ;载入字符串首地址
mov dh,[di] ;2号功能,赋行值
inc di ;取得列
mov dl,[di] ;2号功能,赋列值
mov start_col,dl ;保存开始列
mov ah,2 ;2号功能,设置光标位置,dh=行号;dl=列号;bh=页号
mov bh,0 ;0页
int 10h
;---------------取颜色值-------------
inc di ;取得颜色值
mov bl,[di] ;赋颜色值
;-----------绘制矩形载入外框------------
drawsqre 31,78,296,88,08h ;调用矩形框绘制宏,绘制载入框 内,灰色
drawsqre 29,76,298,90,0fh ;调用矩形框绘制宏,绘制载入框 外,纯白
;---------------显示字符--------------
load_write:
inc di ;取得要显示的字符
mov al,[di]
cmp al,0 ;结束否
jz end_load
call show_char ;调用显示字符程序,行显示
call waitf
jmp load_write ;下一个字符
end_load:
ret
show_load endp
;********************简版琴键处理程序********************
do_key proc near
;---显示按下---
push bx ;bx入栈
mov bx,keynum ;取按键编号缓存值,存入bx
call key_down ;在屏幕上显示按下状态
;----按下时琴身点阵颜色改变--纯白--
draw_point 40,52,44,92,0fh ;调用矩形点阵宏,绘制音响孔左点阵
draw_point 288,52,292,92,0fh ;调用矩形点阵宏,绘制音响孔右点阵
draw_point 150,34,282,38,0fh ;调用矩形点阵宏,绘制正面音孔点阵
pop bx ;bx出栈
;---发出声音---
lea bx,tune ;装入对应频率段地址到bx中
push si ;si入栈
mov si,keynum ;取按键编号缓存值,存入si
mov di,[bx+si] ;取对应编号的音符频率值,存入di
call play_hand ;调用手动发声程序
pop si ;出栈
;---显示弹起---
push bx
mov bx,keynum ;在屏幕上显示弹起状态
call key_up
;----按下时琴身点阵颜色恢复--灰色--
draw_point 40,52,44,92,07h ;调用矩形点阵宏,绘制音响孔左
draw_point 288,52,292,92,07h ;调用矩形点阵宏,绘制音响孔右
draw_point 150,34,282,38,07h ;调用矩形点阵宏,绘制正面音孔
pop bx
mov key_tune,0 ;恢复按键状态缓存,
;-------
ret
do_key endp
;*****高级版本琴键处理
d_do_key proc near
;---显示按下---
push bx ;bx入栈
mov bx,keynum ;取按键编号缓存值,存入bx
call d_key_down ;在屏幕上显示按下状态
;----按下时琴身点阵颜色改变--纯白--
draw_point 40,52,44,92,0fh ;调用矩形点阵宏,绘制音响孔左点阵
draw_point 288,52,292,92,0fh ;调用矩形点阵宏,绘制音响孔右点阵
draw_point 150,34,282,38,0fh ;调用矩形点阵宏,绘制正面音孔点阵
pop bx ;bx出栈
;---发出声音---
lea bx,d_tune ;装入对应频率段地址到bx中
push si ;si入栈
mov si,keynum ;取按键编号缓存值,存入si
mov di,[bx+si] ;取对应编号的音符频率值,存入di
call play_hand ;调用手动发声程序
pop si ;出栈
;---显示弹起---
push bx
mov bx,keynum ;在屏幕上显示弹起状态
call d_key_up
;----按下时琴身点阵颜色恢复--灰色--
draw_point 40,52,44,92,07h ;调用矩形点阵宏,绘制音响孔左
draw_point 288,52,292,92,07h ;调用矩形点阵宏,绘制音响孔右
draw_point 150,34,282,38,07h ;调用矩形点阵宏,绘制正面音孔
pop bx
mov key_tune,0 ;恢复按键状态缓存,
;-------
ret
d_do_key endp
;************************任意时间延时程序************************
;************************任意时间延时程序************************
waitf proc near
push ax ;ax入栈
push cx
mov cx,delay_time ;t=delay_time*15.08us
;-----------15.08us硬件延时------------
waitf1:
in al,61h
and al,10h ;检查pb4口
cmp al,ah ;判断al变化否
je waitf1 ;等待al变化
mov ah,al ;保存pb4的新状态(al中)
loop waitf1 ;cx-1不为0则回到waitf
pop cx
pop ax ;ax出栈
;----------------
ret
waitf endp
;*************返回dos程序***************
exit proc near
mov ah,4ch
int 21h
ret
exit endp
scan_key proc near
mov ah,0 ;读键盘,键盘扫描码存入ah,ASCII码存入al
int 16h
mov dl,al ;al中的ASCII码存入dl,为了便于修改,通过ASCII码来检测
;--------------检测是否为结束键--------------
cmp ah,01h ;是否是结束键,Esc键作为结束键,其扫描码为01h
jne flag_scan ;若不是继续检测
call exit ;若是则退出
;----------扫描琴键--------
flag_scan:
dkey_l1:
cmp dl,'1' ;是否是0
jne dkey_l2 ;不是则继续扫描
mov keynum,0 ;是则改变按键编号缓存
mov key_tune,1 ;改变按键状态缓存
jmp scan_end ;键扫描结束
dkey_l2:
cmp dl,'2' ;是否是2
jne dkey_l3
mov keynum,2
mov key_tune,1
jmp scan_end
dkey_l3:
cmp dl,'3' ;是否是3
jne dkey_l4
mov keynum,4
mov key_tune,1
jmp scan_end
dkey_l4:
cmp dl,'4' ;是否是4
jne dkey_l5
mov keynum,6
mov key_tune,1
jmp scan_end
dkey_l5:
cmp dl,'5' ;是否是5
jne dkey_l6
mov keynum,8
mov key_tune,1
jmp scan_end
dkey_l6:
cmp dl,'6' ;是否是6
jne dkey_l7
mov keynum,10
mov key_tune,1
jmp scan_end
dkey_l7:
cmp dl,'7' ;是否是7
jne dkey_1
mov keynum,12
mov key_tune,1
jmp scan_end
dkey_1:
cmp dl,'8' ;是否是8
jne scan_end
mov keynum,14
mov key_tune,1
jmp scan_esc
scan_esc:
cmp dl,27
jne scan_end
jmp Lexit
scan_end:
cmp dl,'p' ;判断是否按下了自动播放键
JE REPLAY
jnz hand_play ;若不是,继续扫描
jmp restart ;演奏结束,返回restart
hand_play:
cmp key_tune,1 ;取按键状态缓存值,判断是否手动演奏,1为有,0为无
jnz again ;若不是,重新扫描有无键按下
ret ;若是音键,则返回并继续进行音键处理
again:
jmp new_scan
scan_key endp
;***************************按下显示程序************************
;--功能:显示按下键盘时相应键盘状态。
key_down proc near
push si
push di
lea si,st_lx ;载入音键起始坐标首地址
lea di,ed_lx ;载入音键结束坐标首地址
draw [si+bx],90,[di+bx],92,0fh ;调用矩形绘制宏,bx为按键标号缓存值,画一小块琴键色方块
draw [si+bx],92,[di+bx],94,07h ;调用矩形绘制宏,bx为按键标号缓存值,画一小块琴键阴影色方块
pop di
pop si
ret
key_down endp
;***************************按下显示程序(为高级乐器准备)************************
;--功能:显示按下键盘时相应键盘状态。
d_key_down proc near
push si
push di
lea si,d_st_lx ;载入音键起始坐标首地址
lea di,d_ed_lx ;载入音键结束坐标首地址
draw [si+bx],90,[di+bx],92,0fh ;调用矩形绘制宏,bx为按键标号缓存值,画一小块琴键色方块
draw [si+bx],92,[di+bx],94,07h ;调用矩形绘制宏,bx为按键标号缓存值,画一小块琴键阴影色方块
pop di
pop si
ret
d_key_down endp
;******************************手动演奏发声程序**************************
;在8253中的43H端口送入一个控制字0B6H,该控制字对定时器2进行初始化,使定时器2准备接收计数初值
;在8253中的42H端口(Timer2)装入一个16位的计数值533H*896/频率,以建立将要产生的声音的频率
;把输出端口61H的0、1两位置1发出声音
;--功能:当手动按键时,播放相应键的声音,只要不放开,就会一直播放。
;--在di中存放发声频率。
play_hand proc near
;-----------
push ax
push bx
push cx
push dx
push di
;-----------
mov al,0b6h ;在8253的43端送出一个控制字0b6h(10110110b)
out 43h,al ;从而对定时器2初始化,准备接收计数初值
mov dx,12h ;1.1931Mhz/给定频率=12348h/给定频率=计数初值
mov ax,348ch ;12348h存入DX:AX中,作32位运算,商存入AX,余数存入DX
div di ;di中存放给定频率
out 42h,al
in al,61h ;开扬声器
mov al,ah ;给定时器2写入AX中存放的计数初值
out 42h,al
in al,61h
mov ah,al ;把8255输出端的61h的0、1两位置1,并把端口状态存入ah
or al,3 ;打开扬声器
out 61h,al
;----------------按键等待------------
wait2:
call waitf ;调用延时
in al,60h ;读取键盘扫描码,按下和放开都有相应的扫描码,放开码=按下码+80h>80h
test al,80h ;al和80h相与,影响标志位
jz wait2 ;未放开则继续延时
mov al,ah ;恢复8255端口61h的状态,关扬声器
out 61h,al
;----------------
pop di ;恢复寄存器状态
pop dx
pop cx
pop bx
pop ax
;----------
ret
play_hand endp
;***************************弹起显示程序************************
;--功能:显示按下键盘后相应键盘恢复以前状态。
key_up proc near
push si
push di
lea si,st_lx ;载入音键起始坐标首地址
lea di,ed_lx ;载入音键结束坐标首地址
draw [si+bx],90,[di+bx],93,07h ;调用矩形绘制宏,恢复阴影
draw [si+bx],93,[di+bx],94,08h ;调用矩形绘制宏,恢复背景色
pop di
pop si
ret
key_up endp
;----------------高级音乐编辑器子程序区顶部---
d_scan_key proc near
PUSH AX
mov ah,0 ;读键盘,键盘扫描码存入ah,ASCII码存入al
int 16h
mov dl,al ;al中的ASCII码存入dl,为了便于修改,通过ASCII码来检测
;--------------检测是否为结束键--------------
cmp ah,01h ;是否是结束键,Esc键作为结束键,其扫描码为01h
jne flag_scan ;若不是继续检测
call exit
;----------扫描琴键--------
; do re mi fa so la xi
;低音:z x c v b n m
;中音:a s d f g h j
;高音:q w e r t y u
flag_scan:
key_l1:
cmp dl,'z' ;是否是z
jne key_l2 ;不是则继续扫描
mov keynum,0 ;是则改变按键编号缓存
mov key_tune,1 ;改变按键状态缓存
jmp d_scan_end ;键扫描结束
key_l2:
cmp dl,'x' ;是否是x
jne key_l3
mov keynum,2
mov key_tune,1
jmp d_scan_end
key_l3:
cmp dl,'c' ;是否是y
jne key_l4
mov keynum,4
mov key_tune,1
jmp d_scan_end
key_l4:
cmp dl,'v' ;是否是v
jne key_l5
mov keynum,6
mov key_tune,1
jmp d_scan_end
key_l5:
cmp dl,'b' ;是否是b
jne key_l6
mov keynum,8
mov key_tune,1
jmp d_scan_end
key_l6:
cmp dl,'n' ;是否是n
jne key_l7
mov keynum,10
mov key_tune,1
jmp d_scan_end
key_l7:
cmp dl,'m' ;是否是m
jne key_1
mov keynum,12
mov key_tune,1
jmp d_scan_end
key_1:
cmp dl,'a' ;是否是a
jne key_2
mov keynum,14
mov key_tune,1
jmp d_scan_end
key_2:
cmp dl,'s' ;是否是s
jne key_3
mov keynum,16
mov key_tune,1
jmp d_scan_end
key_3:
cmp dl,'d' ;是否是d
jne key_4
mov keynum,18
mov key_tune,1
jmp d_scan_end
key_4:
cmp dl,'f' ;是否是f
jne key_5
mov keynum,20
mov key_tune,1
jmp d_scan_end
key_5:
cmp dl,'g' ;是否是g
jne key_6
mov keynum,22
mov key_tune,1
jmp d_scan_end
key_6:
cmp dl,'h' ;是否是h
jne key_7
mov keynum,24
mov key_tune,1
jmp d_scan_end
key_7:
cmp dl,'j' ;是否是j
jne key_h1
mov keynum,26
mov key_tune,1
jmp d_scan_end
key_h1:
cmp dl,'q' ;是否是q
jne key_h2
mov keynum,28
mov key_tune,1
jmp d_scan_end
key_h2:
cmp dl,'w' ;是否是w
jne key_h3
mov keynum,30
mov key_tune,1
jmp d_scan_end
key_h3:
cmp dl,'e' ;是否是e
jne key_h4
mov keynum,32
mov key_tune,1
jmp d_scan_end
key_h4:
cmp dl,'r' ;是否是r
jne key_h5
mov keynum,34
mov key_tune,1
jmp d_scan_end
key_h5:
cmp dl,'t' ;是否是t
jne key_h6
mov keynum,36
mov key_tune,1
jmp d_scan_end
key_h6:
cmp dl,'y' ;是否是y
jne key_h7
mov keynum,38
mov key_tune,1
jmp d_scan_end
key_h7:
cmp dl,'u' ;是否是u
jne d_scan_end
mov keynum,40
mov key_tune,1
d_scan_end:
cmp dl,'p' ;判断是否按下了自动播放键
JE d_REPLAY ;若不是,继续扫描
jmp hand_play
hand_play:
cmp key_tune,1 ;取按键状态缓存值,判断是否手动演奏,1为有,0为无
jnz again ;若不是,重新扫描有无键按下
POP AX
ret ;若是音键,则返回并继续进行音键处理
again:
jmp d_new_scan
d_scan_key endp
;***********************高级音乐播放器的初始化*****************************
;--功能:初始化屏幕和显示,显示字符说明,绘制出电子琴。
d_init proc near
mov ax,data
mov ds,ax
;------------屏幕以及显示初始化-------------
mov ah,0 ;0号功能,设置屏幕
mov al,0dh ;文本分辨率40*25;像素框8*8;像素分辨率320*200;颜色16
int 10h
mov ah,0bh ;11号功能,设置背景颜色,bh=0时,设置背景颜色
mov bh,0
mov bl,00h ;背景色
int 10h
;------------------显示字符说明------------------
call show_d_text ;显示字符串
;------------------绘制电子琴------------------
call d_draw_dzq ;绘制琴身和底座
ret
d_init endp
;************绘制高级电子琴***************
;--功能:绘制琴身和底座,黑白键,效果灯
d_draw_dzq proc near
draw_point 40,52,44,92,07h ;调用矩形点阵宏,绘制音响孔左
draw_point 288,52,292,92,07h ;调用矩形点阵宏,绘制音响孔右
drawsqre 38,50,292,92,07h ;调用矩形框绘制宏,绘制音响框
drawsqre 44,30,286,93,07h ;调用矩形框绘制宏,绘制底框1
draw 45,30,285,94,08h ;调用矩形绘制宏,绘制琴身颜色
drawsqre 45,30,285,94,07h ;调用矩形框绘制宏,绘制底框2
draw_point 150,34,282,38,07h ;调用矩形点阵宏,绘制正面音孔
drawsqre 46,31,284,32,00h ;调用矩形框绘制宏,绘制琴上边
drawsqre 49,48,280,49,00h ;调用矩形框绘制宏,绘制琴挡
draw 55,38,60,41,0ah ;调用矩形绘制宏,绘制灯1
draw 65,38,70,41,07h ;调用矩形绘制宏,绘制灯2
draw 271,42,275,46,07h ;调用矩形绘制宏,绘制5个指示灯
draw 265,42,269,46,07h
draw 259,42,263,46,07h
draw 253,42,257,46,07h
draw 247,42,251,46,07h
;----绘制白键----
lea si,d_st_lx ;画21个白色键
lea di,d_ed_lx
mov cx,21
d_init_draw:
draw [si],d_st_y,[di],d_ed_y,0fh ;调用矩形绘制宏,绘制白色矩形作为白键
draw [si],90,[di],93,07h ;调用矩形绘制宏,绘制灰色矩形作为阴影
add si,2
add di,2
loop d_init_draw
;----绘制黑键----
lea si,d_bt_x ;画15个黑色键
lea di,d_bd_x
mov cx,15
d_init_block:
draw [si],d_bt_y,[di],d_bd_y,00h ;调用矩形绘制宏,绘制黑色矩形作为黑键
add si,2
add di,2
loop d_init_block
ret
d_draw_dzq endp
;***************************弹起显示程序************************
;--功能:显示按下键盘后相应键盘恢复以前状态。
d_key_up proc near
push si
push di
lea si,d_st_lx ;载入音键起始坐标首地址
lea di,d_ed_lx ;载入音键结束坐标首地址
draw [si+bx],90,[di+bx],93,07h ;调用矩形绘制宏,恢复阴影
draw [si+bx],93,[di+bx],94,08h ;调用矩形绘制宏,恢复背景色
pop di
pop si
ret
d_key_up endp
;------------高级音乐编辑器子程序区底部---*-*-*
LEXIT: SHOW Gao2
SHOW Gao3
JMP LOP
CODE ENDS
END START