⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 eleorgan.asm

📁 还是电子钟
💻 ASM
字号:
;----------------------------------------------------------------------
;                             完整程序代码
;----------------------------------------------------------------------
DRAW MACRO START_X,START_Y,END_X,END_Y,COLOR			;画实心矩形宏
	LOCAL DRAW_NEXT
	PUSH AX
	PUSH BX
	PUSH CX
	PUSH DX
	MOV AH,0CH						;写像素点
	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

DRAWSQRE MACRO START_X,START_Y,END_X,END_Y,COLOR		;画空心矩形宏
	LOCAL ROW_UP,RANK_RIGHT,ROW_DOWN,RANK_LEFT
	PUSH AX
	PUSH BX
	PUSH CX
	PUSH DX
	PUSH SI
	MOV AH,0CH
	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

DATA SEGMENT
	SPACE	 DW 500 DUP(?)						;存放弹奏录音的音符
	TIME	 DW 500 DUP(300)					;存放弹奏录音的音长
	MUS_FREQ DW 392,392,440,294,262,262,220,294			;预存歌曲《东方红》频率
		 DW 392,392,440,523,440,392,262,262,220,294
		 DW 392,294,262,247,220,196,392,294,330,294
		 DW 262,262,220,294,330,294,262,294,262,247,220,196
		 DW 392,294,262,247,220,196,392,294,330,294
		 DW 262,262,220,294,330,294,262,554,523,494,440,392,-1
	MUS_TIME DW 3000,1500,1500,6000,3000,1500,1500,6000		;预存歌曲《东方红》音长
		 DW 3000,3000,1500,1500,1500,1500,3000,1500,1500,6000
		 DW 3000,3000,3000,1500,1500,3000,3000,3000,1500,1500
		 DW 3000,10 DUP(1500),6000
		 DW 3000,3000,3000,1500,1500,3 DUP(3000),1500,1500
		 DW 3000,1500 DUP(10),6000	
	TEXT1 DB ' FUNNY PIANO ',0DH,0AH,0DH,0AH,'$'           		;显示文本
	TEXT2 DB 'Designed By WANG QI ',0DH,0AH,'$'
	TEXT3 DB 'Copyright  2006','$'
	TEXT4 DB 'BACH MOZART BEETHOVEN BRAHMS CHOPIN','$'
	SPEED DW 1							;播放乐曲的速度标记
	STAND_ST DW 100,122,144,166,188,210,232,254,276,298,320 	;画白键的边框
		    342,364,386,408,430,452,474,496,518,540
	STAND_ED DW 120,142,164,186,208,230,252,274,296,318,340,
		    362,384,406,428,450,472,494,516,538,560
	ST_LX DW  100,122,144,166,188,210,232				;白色琴键坐标
	ST_MX DW  254,276,298,320,342,364,386
	ST_HX DW  408,430,452,474,496,518,540
	ST_Y  DW  160
	ED_LX DW  120,142,164,186,208,230,252
	ED_MX DW  274,296,318,340,362,384,406
	ED_HX DW  428,450,472,494,516,538,560
	ED_Y  DW  230
	BT_X  DW  112,134,178,200,222					;黑色琴键坐标
	BT_Z  DW  266,288,332,354,376
	      DW  420,442,486,508,530
	BT_Y  DW  160
	BD_X  DW  128,150,194,216,238
	BD_Z  DW  282,304,348,370,392
	      DW  436,458,502,524,546
	BD_Y  DW  205
	MES   DB '                            WELCOME TO ELE_PIANO!                     ',0DH,0AH                             
	      DB '                          PRESS 1-8 TO PLAY THE PIANO                 ',0DH,0AH
	      DB '                          PRESS Z AND NUMBER TO AUTO_PLAY             ',0DH,0AH
	      DB '                          PRESS ESC TO RETURN TO DOS                    ','$'     
DATA ENDS

CODE SEGMENT
	ASSUME DS:DATA,CS:CODE
START:	
	MOV AX,DATA
	MOV DS,AX
	MOV AL,10000000B		;初始化 8255
	MOV DX,28BH			;PORT A,模式0
	OUT DX,AL			
	CALL INIT			;初始化屏幕
	MOV DH,26
	MOV DL,0
	MOV AH,2			;置光标位置
	INT 10H
	MOV DX,OFFSET MES 
	MOV AH,9			;显示提示信息
	INT 21H
GET:	MOV AH,7			;读入键盘输入
	INT 21H	
JUDGE_P:				;判断是否播放录音
	CMP AL,'P'
	JNZ JUDGE	
	MOV AX,-1
	MOV [BX],AX
	CALL MUSIC1
	MOV BX,OFFSET SPACE
	JMP GET
JUDGE:	CMP AL,'Z'			;若输入是'Z',播放乐曲
	JNZ COMPARE			;否则判断是哪个音符
	MOV AH,7			;输入播放乐曲速度
	INT 21H
	SUB AL,'0'			;获得速度
	MOV AH,0
	MOV SPEED,AX
	CALL MUSIC
	JMP GET
COMPARE:				;判断是否为do
	CMP AL,'1'
	JNZ SHARP_DO 			
	MOV AX,261			;将弹奏音符存入space中
	MOV [BX],AX
	ADD BX,2
	LEA SI,ST_MX                     
	LEA DI,ED_MX
	DRAW [SI],230,[DI],238,0FH      ;灰色变白色:琴键按下 
	MOV CX,261			;计数初值OF 1
	CALL BEEP
	DRAW [SI],230,[DI],238,07H 	;白色变灰色:琴键弹起
	JMP GET
SHARP_DO:				;判断是否为升do
	CMP AL,'Q'
	JNZ RE 
	MOV AX,261			;将弹奏音符存入space中
	MOV [BX],AX
	ADD BX,2
	LEA SI,BT_Z                     
	LEA DI,BD_Z
	DRAW [SI],199,[DI],205,00H	;灰色变白色:琴键按下 
	MOV CX,277			;计数初值 OF #1    
	CALL BEEP
	DRAW [SI],199,[DI],205,07H    	;白色变灰色:琴键弹起
	JMP GET
RE:	CMP AL,'2'			;判断是否为re
	JNZ SHARP_RE 
	MOV AX,261			;将弹奏音符存入space中
	MOV [BX],AX
	ADD BX,2
	LEA SI,ST_MX                     
	LEA DI,ED_MX
	ADD SI,2
	ADD DI,2
	DRAW [SI],230,[DI],238,0FH      ;灰色变白色:琴键按下 
	MOV CX,294			;计数初值 OF 2
	CALL BEEP
	DRAW [SI],230,[DI],238,07H 	;白色变灰色:琴键弹起
	JMP GET
SHARP_RE:				;判断是否为升re
	CMP AL,'W'
	JNZ MI 
	MOV AX,261			;将弹奏音符存入space中
	MOV [BX],AX
	ADD BX,2
	LEA SI,BT_Z                     
	LEA DI,BD_Z
	ADD SI,2
	ADD DI,2
	DRAW [SI],199,[DI],205,00H	;灰色变白色:琴键按下 
	MOV CX,311	       		;计数初值 OF #2
	CALL BEEP
	DRAW [SI],199,[DI],205,07H  	;白色变灰色:琴键弹起
	JMP GET
MI:	CMP AL,'3'			;判断是否为mi
	JNZ FA
	MOV AX,261			;将弹奏音符存入space中
	MOV [BX],AX
	ADD BX,2
	LEA SI,ST_MX                     
	LEA DI,ED_MX 
	ADD SI,4
	ADD DI,4
	DRAW [SI],230,[DI],238,0FH      ;灰色变白色:琴键按下 
	MOV CX,330			;计数初值 OF 3
	CALL BEEP
	DRAW [SI],230,[DI],238,07H 	;白色变灰色:琴键弹起
	JMP GET
FA:	CMP AL,'4'			;判断是否为fa
	JNZ SHARP_FA
	MOV AX,261			;将弹奏音符存入space中
	MOV [BX],AX
	ADD BX,2
	LEA SI,ST_MX                     
	LEA DI,ED_MX 
	ADD SI,6
	ADD DI,6
	DRAW [SI],230,[DI],238,0FH      ;灰色变白色:琴键按下 
	MOV CX,349			;计数初值 OF 4
	CALL BEEP
	DRAW [SI],230,[DI],238,07H 	;白色变灰色:琴键弹起
	JMP GET
SHARP_FA:				;判断是否为升fa
	CMP AL,'R'
	JNZ SO
	MOV AX,261			;将弹奏音符存入space中
	MOV [BX],AX
	ADD BX,2
	LEA SI,BT_Z                     
	LEA DI,BD_Z
	ADD SI,4
	ADD DI,4
	DRAW [SI],199,[DI],205,00H 	;灰色变白色:琴键按下 
	MOV CX,370			;计数初值 OF #4
	CALL BEEP
	DRAW [SI],199,[DI],205,07H  	;白色变灰色:琴键弹起
	JMP GET
SO:	CMP AL,'5'			;判断是否为so
	JNZ SHARP_SO
	MOV AX,261			;将弹奏音符存入space中
	MOV [BX],AX
	ADD BX,2
	LEA SI,ST_MX                     
	LEA DI,ED_MX
	ADD SI,8
	ADD DI,8
	DRAW [SI],230,[DI],238,0FH      ;灰色变白色:琴键按下 
	MOV CX,392			;计数初值 OF 5
	CALL BEEP
	DRAW [SI],230,[DI],238,07H 	;白色变灰色:琴键弹起
	JMP GET
SHARP_SO:				;判断是否为升so
	CMP AL,'T'
	JNZ LA
	MOV AX,261			;将弹奏音符存入space中
	MOV [BX],AX
	ADD BX,2
	LEA SI,BT_Z                     
	LEA DI,BD_Z
	ADD SI,6
	ADD DI,6
	DRAW [SI],199,[DI],205,00H 	;灰色变白色:琴键按下 
	MOV CX,415			;计数初值 OF #5
	CALL BEEP
	DRAW [SI],199,[DI],205,07H  	;白色变灰色:琴键弹起
	JMP GET
LA:	CMP AL,'6'			;判断是否为la
	JNZ SHARP_LA
	MOV AX,261			;将弹奏音符存入space中
	MOV [BX],AX
	ADD BX,2
	LEA SI,ST_MX                     
	LEA DI,ED_MX
	ADD SI,10
	ADD DI,10
	DRAW [SI],230,[DI],238,0FH      ;灰色变白色:琴键按下  
	MOV CX,440			;计数初值 OF 6
	CALL BEEP
	DRAW [SI],230,[DI],238,07H 	;白色变灰色:琴键弹起
	JMP GET
SHARP_LA:				;判断是否为升la
	CMP AL,'Y'
	JNZ XI
	MOV AX,261			;将弹奏音符存入space中
	MOV [BX],AX
	ADD BX,2
	LEA SI,BT_Z                     
	LEA DI,BD_Z
	ADD SI,8
	ADD DI,8
	DRAW [SI],199,[DI],205,00H	;灰色变白色:琴键按下 
	MOV CX,466			;计数初值 OF #6
	CALL BEEP
	DRAW [SI],199,[DI],205,07H  	;白色变灰色:琴键弹起
	JMP GET
XI:	CMP AL,'7'			;判断是否为xi
	JNZ HIGH_DO
	MOV AX,261			;将弹奏音符存入space中
	MOV [BX],AX
	ADD BX,2
	LEA SI,ST_MX                     
	LEA DI,ED_MX
	ADD SI,12
	ADD DI,12
	DRAW [SI],230,[DI],238,0FH      ;灰色变白色:琴键按下 
	MOV CX,494			;计数初值 OF 7
	CALL BEEP
	DRAW [SI],230,[DI],238,07H 	;白色变灰色:琴键弹起
	JMP GET
HIGH_DO:				;判断是否为高音do
	CMP AL,'8'
	JNZ IF_ESC
	MOV AX,261			;将弹奏音符存入space中
	MOV [BX],AX
	ADD BX,2
	LEA SI,ST_MX                     
	LEA DI,ED_MX
	ADD SI,14
	ADD DI,14
	DRAW [SI],230,[DI],238,0FH      ;灰色变白色:琴键按下 
	MOV CX,523			;计数初值 OF 8
	CALL BEEP
	DRAW [SI],230,[DI],238,07H 	;白色变灰色:琴键弹起
	JMP GET	
IF_ESC:			        	
	CMP AL,27			;是否是'ESC'
	JZ GO_BACK
	JMP GET 			;不是,继续读数
GO_BACK:
	MOV AX,0003			;调回显示模式
	INT 10H
	MOV AH,4CH			;返回dos
	INT 21H
;---------------------------------------------------------------
INIT PROC NEAR				;初始化屏幕:画琴键
	MOV AX,DATA
	MOV DS,AX
	MOV AH,0                        ;设置屏幕显示方式
	MOV AL,12H			;VGA 640×480 16色
	INT 10H
	MOV AH,0BH			;置彩色调板
	MOV BH,0
	MOV BL,00H                  	;背景色
	INT 10H
	DRAWSQRE 70,60,590,412,0CH	;框框
	DRAWSQRE 74,62,586,410,0EH	;框框
	DRAW 260,330,387,358,09H	;TEXT1的框框
	MOV DH,21			;行
	MOV DL,34			;列
	MOV AH,2			;置光标位置
	INT 10H
	MOV DX,OFFSET TEXT1
	MOV AH,9			;显示字符串
	INT 21H
	DRAW 220,359,427,385,09H	;TEXT2的框框	
	MOV DH,23
	MOV DL,30
	MOV AH,2			;置光标位置
	INT 10H
	MOV DX,OFFSET TEXT2
	MOV AH,9			;显示字符串
	INT 21H
	DRAW 255,386,392,405,09H	;TEXT3的框框
	MOV DH,24
	MOV DL,33
	MOV AH,2			;置光标位置	
	INT 10H
	MOV DX,OFFSET TEXT3
	MOV AH,9			;显示字符串
	INT 21H
	DRAW 85,120,575,260,09H		;蓝色
	DRAWSQRE 85,120,575,260,0AH	;绿色
	DRAW 90,125,570,145,10		;浅绿色
	;DRAWSQRE 90,150,570,250,0EH
	MOV DH,8			;行
	MOV DL,22			;列
	MOV AH,2			;置光标位置
	INT 10H
	MOV DX,OFFSET TEXT4
	MOV AH,9			;显示字符串
	INT 21H
	LEA SI,ST_LX                     ;画21个白色键
	LEA DI,ED_LX
	MOV CX,21
INIT_DRAW:
	DRAW [SI],ST_Y,[DI],ED_Y,0FH	 ;0FH白色
	DRAW [SI],230,[DI],238,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	 ;00H黑色
	DRAW [SI],199,[DI],205,07H       ;阴影
	ADD SI,2
	ADD DI,2
	LOOP INIT_BLOCK
	RET
;--------------------------------------------------------------
BEEP 	PROC NEAR               ;扬声器发声子程序
	MOV AL,00110110B        ;8253计数器0方式3,16位2进制
	MOV DX,283H		
	OUT DX,AL
	MOV DX,12H		;1.19MHZ对应初值
	MOV AX,348CH		;1.19MHZ
	DIV CX			;计数初值放于AX
	  			;8253计数初值
	MOV DX,280H		;计数器 0
	OUT DX,AL		
	MOV AL,AH		;先写低位,后写高位
	OUT DX,AL
	MOV DX,288H		;读8255 PA口
	IN AL,DX		
	MOV AH,AL		;将数据暂存
	OR AL,03H
	OUT DX,AL		;打开gate2,使out2输出到扬声器
GET1:	IN AL,60H		;判断按键是否持续
	TEST AL,80H
	JNZ STOP
	JMP GET1	
STOP:	MOV AL,AH		;回复8255A的pA口原值,停止发声
	MOV DX,288H		
	OUT DX,AL
	RET
BEEP	ENDP
;--------------------------------------------------------
MUSIC	PROC NEAR		;乐曲播放子程序
	LEA BP,DS:MUS_TIME	
	LEA SI,MUS_FREQ
FREQ:	MOV DI,[SI]
	CMP DI,-1		;如果是末尾
	JZ END_MUS
	MOV BX,DS:[BP]		;BX 储存发声时间	
	MOV DX,0
	MOV AX,BX
	DIV SPEED
	MOV BX,AX
	CALL SOUNDF
	ADD SI,2
	ADD BP,2
	MOV AH,01H		;播放时有按键退出
	INT 16H
	JNZ END_MUS
	JMP FREQ
END_MUS:	
	RET
MUSIC ENDP
;---------------------------------------------------------
SOUNDF	PROC NEAR		;乐曲播放音符长短程序
	MOV AL,00110110B
	OUT 283H,AL		
	MOV DX,12H		;1.19MHZ对应的初值
	MOV AX,348CH		;1.19MHZ
	DIV DI
	MOV DX,280H
	OUT DX,AL		;通道 0
	MOV AL,AH
	OUT DX,AL		
	MOV DX,288H
	IN AL,DX		;PORT A
	MOV AH,AL
	OR AL,3
	OUT DX,AL		
AA:	MOV CX,0
DELAY:	LOOP DELAY
	DEC BX
	JNZ AA
	MOV AL,AH
	OUT DX,AL		
	RET
SOUNDF 	ENDP
;----------------------------------------------------------
INIT ENDP
CODE ENDS
END START

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -