彙編課設(電子鋼琴:原始碼)
阿新 • • 發佈:2018-12-09
實現結果
程式的啟動有點像小霸王遊戲機的遊戲,喜歡彙編的朋友可以發信與我一起討論,發聲程式參考的是一本彙編教材,程式寫作和上傳相隔有點久遠,記不太清,千行程式碼,算是學生時代一個比較得意的課設
編譯器下載
編譯器可在我的上傳資源中查詢,已註明:彙編編譯器
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