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

📄 zuoqu.asm

📁 作曲程序,输入节拍
💻 ASM
字号:
CURSE	MACRO	OP1,OP2		;设置光标位置
	PUSH	AX
	PUSH	DX
	MOV	AH,02H
	MOV	DH,OP1
	MOV	DL,OP2
	INT	10H
	POP	DX
	POP	AX
	ENDM

LINE1	MACRO	X1,Y1,LONG1	;画横线
	LOCAL	AA
	MOV	CX,X1
	MOV	DX,Y1
	MOV	BX,LONG1
	ADD	BX,CX
	MOV	AH,0CH	
AA:	INT	10H
	INC	CX
	CMP	CX,BX
	JNE	AA
	ENDM

LINE2	MACRO	X2,Y2,LONG2	;画竖线
	LOCAL	AAA
	MOV	CX,X2
	MOV	DX,Y2
	MOV	BX,LONG2
	ADD	BX,DX
	MOV	AH,0CH	
AAA:	INT	10H
	INC	DX
	CMP	DX,BX
	JNE	AAA
	ENDM
	
XIE1	MACRO	COL1,ROW1,COLE1	;画正斜线
	LOCAL	EE,FF
	PUSH	AX
	MOV	CX,COL1
	MOV	DX,ROW1
	MOV	AH,0CH
EE:	CMP	CX,COLE1
	JAE	FF
	INT	10H
	INC	CX
	INC	DX
	JMP	EE
FF:	POP	AX
	ENDM

XIE2	MACRO	COL2,ROW2,COLE2	;画反斜线
	LOCAL	EEE,FFF
	PUSH	AX
	MOV	CX,COL2
	MOV	DX,ROW2
	MOV	AH,0CH
EEE:	CMP	CX,COLE2
	JAE	FFF
	INT	10H
	INC	CX
	SUB	DX,1
	JMP	EEE
FFF:	POP	AX
	ENDM

DATA	SEGMENT
freq      dw 2 dup(262,294,330,262) 
      dw 2 dup(330,349,392) 
      dw 2 dup(392,440,392,349,330,262) 
      dw 2 dup(294,196,262),0 

MTIM       dw 10 dup(5000),10000,5000,5000,10000 
             dw 2 dup(2500,2500,2500,2500,5000,5000) 
             dw 2 dup(5000,5000,10000)   

BUFF1	DB	'  Welcome you to run this programme!      Please input time:$'
BUFF2	DB	'E: finish composing    P: play$'
BUFF3	DB	'P: play           S: save               R: compose again  Q: exit$'	
BUFF4	DB	'Please input file name:$'
BUFF5	DB	'Error  Press S to try again:$'
BUFF6	DB	'Music had been saved$'
NAM	DB	30 DUP(''),'$'
FILEHAN	DW	?	
JPAI	DB	4		;记录输入的节拍(一小节总节拍数)
RM	DB	4		;剩余节拍数
NOT2	EQU	2		;二分音符所占的拍子数
NOT1	EQU	4		;全音符所占的拍子数
COL	DW	?		;音符在屏幕上的位置
ROW	DW	?
HEIGHT	DW	?		;当前音符音高		
TIME	DB	?		;当前音符时值
NUM	DW	?		;用来计数
FREQ_T	DW	196,220,247,262,294,330,349,392,440,494,523,587,659,698,784
FREQ_R	DB	'196 ','220 ','247 ','262 ','294 '	;低音sol到中音re的频率
	db	'330 ','349 ','392 ','440 ','494 '	;中音mi到中音xi的频率
	db	'523 ','587 ','659 ','698 ','784 '	;高音do到高音sol的频率
TIM_R	DB	'0.5s','1s ','2s '	
ZZHEN	DW	?
STO	DB	320 DUP('')


DATA	ENDS
stak      segment para stack 'stack' 
      dw 100 dup(?) 
stak      ends 
CODE	SEGMENT
MAIN	PROC	FAR
	ASSUME	CS:CODE,DS:DATA
	PUSH	AX
	MOV	AX,DATA
	MOV	DS,AX
	MOV	ES,AX
	MOV	AX,0004H	;设置显示模式为320*200彩色图形方式
	INT	10H
	MOV	AH,0BH		;设置背景为蓝色
	MOV	BH,00
	MOV	BL,1
	INT	10H
OK:	CURSE	0,0	
	MOV	DX,OFFSET BUFF1	;显示提示信息
	MOV	AH,09
	INT	21H
	CALL	INPUT
	MOV	COL,34		;参数恢复
	MOV	ROW,78
	MOV	NUM,0
	MOV	HEIGHT,4
	MOV	TIME,1
	CURSE	2,2
	MOV	DX,OFFSET BUFF2
	MOV	AH,09H
	INT	21H
	CALL	YUEPU
	CALL	COM
	CURSE	2,2
	MOV	DX,OFFSET BUFF3
	MOV	AH,09H
	INT	21H
SSS:	MOV	AH,08
	INT	21H
	CMP	AL,'P'
	JE	PPP
	CMP	AL,'S'
	JE	STOR
	CMP	AL,'R'
	JE	AGAIN
	CMP	AL,'Q'
	JE	QUIT
	JMP	SSS
PPP:	
	CALL	PLAY
	JMP	SSS
STOR:	CALL	STORE
	JMP	SSS
AGAIN:	CALL	CLEALL		;重头开始
	JMP	OK		
QUIT:	POP	AX
	MOV	AX,4C00H
	INT	21H
MAIN	ENDP

INPUT	PROC	NEAR		;输入节拍
	PUSH	AX
	PUSH	BX
	MOV	BX,0
CC:	MOV	AH,01H
	INT	21H
	CMP	AL,0DH		;回车?
	JE	BB
	CMP	BX,0		;只存第一个输入的数
	JNE	JJ
	MOV	STO[0],AL
	MOV	STO[1],'/'
	MOV	STO[2],'4'
	MOV	STO[3],' '
	MOV	ZZHEN,4
	AND	AL,0FH		;ASCLL转化为数字
	MOV	JPAI,AL
	MOV	RM,AL
JJ:	INC	BX
	CMP	BX,3
	JNA	CC
BB:	POP	BX
	POP	AX
INPUT	ENDP

YUEPU	PROC	NEAR		;显示乐谱
	MOV	AL,2
	LINE1	0,50,320
	LINE1	0,56,320
	LINE1	0,62,320
	LINE1	0,68,320
	LINE1	0,74,320
	LINE1	0,110,320
	LINE1	0,116,320
	LINE1	0,122,320
	LINE1	0,128,320
	LINE1	0,134,320
	MOV	AL,5		;高音谱号
	LINE1	13,62,6   
	LINE1	10,74,9
	LINE1	8,84,5
	LINE1	13,57,3
	LINE2	15,43,39
	LINE2	22,66,5
	LINE2	10,65,5
	LINE2	5,65,5
	LINE2	20,47,6
	XIE1	6,82,8
	XIE1	5,69,10
	XIE1	16,43,20
	XIE1	18,62,22
	XIE2	18,74,22
	XIE2	13,83,15
	XIE2	10,65,14
	XIE2	16,56,21
	XIE2	5,64,13
	RET
YUEPU	ENDP

NOTE	PROC	NEAR		;显示音符
	PUSH	AX
	PUSH	SI
	PUSH	DI
	CMP	RM,0		;剩余节拍数是否为零,是否画小节线
	JNE	KK
	MOV	AH,JPAI		;还原小节剩余节拍数
	MOV	RM,AH
	MOV	AL,5
	MOV	SI,COL
	SUB	SI,6
	MOV	DI,ROW
	SUB	DI,28	
	LINE2	SI,DI,25
KK:	CMP	HEIGHT,5	;是否下加一线
	JAE	NN
	MOV	AL,2
	MOV	SI,COL
	SUB	SI,5
	CMP	NUM,19
	JB	FAI
	MOV	DI,140
	JMP	YOUA
FAI:	MOV	DI,80
YOUA:	LINE1	SI,DI,13
	CMP	HEIGHT,3	;是否下加二线
	JAE	NN
	ADD	DI,6
	LINE1	SI,DI,13
NN:	MOV	AL,7		;拼出音符头
	MOV	SI,COL
	MOV	DI,ROW
	CMP	TIME,2
	JAE	PP
	LINE1	SI,DI,2		;实心头
	ADD	DI,4
	LINE1	SI,DI,2
	SUB	SI,1
	SUB	DI,1
	LINE1	SI,DI,4
	SUB	DI,2
	LINE1	SI,DI,4
	SUB	SI,1
	ADD	DI,1
	LINE1	SI,DI,6
	JMP	QQ
PP:	MOV	AH,0CH		;空心头
	MOV	CX,SI
	MOV	DX,DI
	SUB	SI,2
	ADD	DI,2
	INT	10H
	ADD	CX,1
	INT	10H
	ADD	DX,4
	INT	10H
	SUB	CX,1
	INT	10H
	SUB	CX,1
	SUB	DX,1
	INT	10H
	ADD	CX,3
	INT	10H
	SUB	DX,2
	INT	10H
	SUB	CX,3
	INT	10H
	SUB	CX,1
	ADD	DX,1
	INT	10H
	ADD	CX,5
	INT	10H
QQ:	CMP	TIME,4		;画音符尾巴
	JE	OO
	CMP	HEIGHT,9	
	JA	MM
	ADD	SI,5
	SUB	DI,20
MM:	LINE2	SI,DI,21
OO:	POP	DI
	POP	SI
	POP	AX
	RET
NOTE	ENDP

CLEAR	PROC	NEAR		;清除音符
	PUSH	SI
	PUSH	DI
	PUSH	BP
	MOV	SI,COL
	SUB	SI,5
	CMP	NUM,19
	JB	TAI
	MOV	DI,105
	MOV	BP,153
	JMP	LL
TAI:	MOV	DI,45
	MOV	BP,93
LL:	CMP	DI,50
	JE	COLOR
	CMP	DI,56
	JE	COLOR
	CMP	DI,62
	JE	COLOR
	CMP	DI,68
	JE	COLOR
	CMP	DI,74
	JE	COLOR
	CMP	DI,110
	JE	COLOR
	CMP	DI,116
	JE	COLOR
	CMP	DI,122
	JE	COLOR
	CMP	DI,128
	JE	COLOR
	CMP	DI,134
	JE	COLOR
	MOV	AL,0
	JMP	HEHE
COLOR:	MOV	AL,2
HEHE:	LINE1	SI,DI,14
	INC	DI
	CMP	DI,BP
	JNE	LL
	POP	BP
	POP	DI
	POP	SI
	RET
CLEAR	ENDP

CLEALL	PROC	NEAR		;清屏
	PUSH	AX
	PUSH	CX
	PUSH	DX
	MOV	AX,0C00H
	MOV	CX,0
	MOV	DX,0
HANG:	INT	10H
	INC	CX
	CMP	CX,320
	JNE	HANG
	MOV	CX,0
	INC	DX
	CMP	DX,200
	JNE	HANG
	POP	DX
	POP	CX
	POP	AX
	RET
CLEALL	ENDP

COM	PROC	NEAR		;作曲
	PUSH	AX	
HH:	CALL	CLEAR
	CALL	NOTE
	MOV	AH,10H		;从键盘接收字符
	INT	16H
	CMP	AH,48H		;上?
	JE	UP
	CMP	AH,50H		;下?
	JE	DOWN
	CMP	AH,4BH		;左?
	JE	LEFT
	CMP	AH,4DH		;右?
	JE	RIGHT
	CMP	AL,0DH		;回车?
	JE	XING
	CMP	AX,1245H	;按下"E"结束作曲
	JE	II
	CMP	AX,1950H	;按下"P"演奏
	JE	III
	JMP	HH
UP:	MOV	DI,0
	CALL	YINGAO
	JMP	HH
DOWN:	MOV	DI,1
	CALL	YINGAO
	JMP	HH
LEFT:	MOV	DI,2
	CALL	TIM
	JMP	HH
RIGHT:	MOV	DI,3
	CALL	TIM
	JMP	HH
XING:	CALL	ONE	
	JMP	HH
III:	CALL	PLAY
	JMP	HH
II:	MOV	AH,JPAI		;不能从小节中间结束
	CMP	RM,AH
	JNE	HH
	CALL	CLEAR		;结束,画结束线
	MOV	AL,5
	MOV	SI,COL
	SUB	SI,4
	CMP	NUM,19
	JB	FASE
	MOV	DI,110
	JMP	YOEH
FASE:	MOV	DI,50
YOEH:	LINE2	SI,DI,25
	POP	AX
	RET
COM	ENDP	

ONE	PROC	NEAR
	PUSH	DI
	PUSH	BX
	PUSH	AX
	PUSH	CX
	MOV	BX,NUM		;保存设置音符
	MOV	DI,HEIGHT
	SUB	DI,1
	MOV	DX,FREQ_T[DI]
	MOV	FREQ[BX],DX
	MOV	AL,4
	MUL	DI
	MOV	DI,AX
	MOV	BX,ZZHEN
	MOV	CX,4
QWER:	MOV	DL,FREQ_R[DI]
	MOV	STO[BX],DL
	INC	DI
	INC	BX
	LOOP	QWER
	MOV	ZZHEN,BX
	;MOV	CX,TIME
	;MOV	MUTIM[BX],CX
	;SHL	BX,02
	

	MOV	AH,RM		;参数更新
	SUB	AH,TIME		;计算一小节内的剩余节拍
	MOV	RM,AH
	ADD	NUM,1	
	CMP	NUM,19		;是否超出第一行
	JB	BUCUO
	JA	HAOLE
	MOV	COL,4
HAOLE:	MOV	ROW,138
	JMP	HENHAO
BUCUO:	MOV	ROW,78
HENHAO:	ADD	COL,15
	MOV	HEIGHT,4
	MOV	TIME,1
	POP	CX
	POP	AX	
	POP	BX
	POP	DI
	RET
ONE	ENDP

YINGAO	PROC	NEAR		;改变音高
	PUSH	AX
	CMP	DI,1
	JZ	DOWN1
	CMP	HEIGHT,15
	JAE	EXITY
	SUB	ROW,3
	ADD	HEIGHT,1
	JMP	EXITY
DOWN1:	CMP	HEIGHT,1
	JBE	EXITY
	ADD	ROW,3
	SUB	HEIGHT,1
EXITY:	POP	AX
	RET
YINGAO	ENDP

TIM	PROC	NEAR		;改变音符时值
	PUSH	AX
	CMP	DI,2		;表明是按左键还是右键的标志
	JZ	LEFT1	
	MOV	AL,RM		;根据剩余节拍数限制可用音符
	MOV	AH,1		;先假定只能放入4分音符,时值为1
	CMP	AL,NOT2		;本小节节拍剩余数和2分音符时长作比较
	JB	XX
	INC	AH		;剩余数大于等于2,AH加为2
	CMP	AL,NOT1		;本小节节拍剩余数和全音符时长作比较
	JB	XX
	ADD	AH,2		;剩余数大于等于4,AH加为4
XX:	CMP	TIME,AH		;AH来限制TIME的上限
	JAE	EXITT
	CMP	TIME,2		;如果是2分音符变全音符,TIME必须加2
	JNE	WW
	ADD	TIME,1
WW:	ADD	TIME,1		;其他请况TIME加1
	JMP	EXITT
LEFT1:	CMP	TIME,1		;按左键时,TIME值减小,下限是1
	JBE	EXITT
	CMP	TIME,4		;如果是全音符变2分音符,TIME必须减2
	JNE	VV
	SUB	TIME,1
VV:	SUB	TIME,1		;其他请况TIME减1	
EXITT:	POP	AX		;退出
	RET
TIM	ENDP

STORE	PROC	NEAR		;保存文件
	PUSH	AX
	PUSH	CX
	PUSH	DX
	CALL	CLE
	CURSE	20,2
	MOV	DX,OFFSET BUFF4
	MOV	AH,09
	INT	21H
	MOV	BX,0
SET:	MOV	NAM[BX],00H	;存储清零
	INC	BX
	CMP	BX,30
	JB	SET
	MOV	FILEHAN,0
	MOV	AH,1		;输入文件名
	MOV	BX,0
DLL:	INT	21H
	CMP	AL,0DH
	JE	DLLL
	MOV	NAM[BX],AL
	INC	BX
	JMP	DLL
DLLL:	LEA	DX,NAM		;新建
	MOV	AH,3CH
	MOV	CX,00
	INT	21H
	JC	ERROR
	MOV	FILEHAN,AX
	JMP	B90
ERROR:	CALL	CLE
	CURSE	20,2		;出错处理,重试
	MOV	DX,OFFSET BUFF5
	MOV	AH,09
	INT	21H
	JMP	B100
B90:	MOV	AH,40H		;写入数据
	MOV	BX,FILEHAN
	MOV	CX,320
	LEA	DX,STO
	INT	21H
	JC	ERROR
	MOV	AH,3EH		;关闭文件
	INT	21H
	JC	ERROR
	CALL	CLE
	CURSE	20,2		;成功提示
	MOV	DX,OFFSET BUFF6
	MOV	AH,09
	INT	21H
B100:	POP	DX
	POP	CX
	POP	AX
	RET
STORE	ENDP

CLE	PROC	NEAR	
	MOV	AX,0C00H
	MOV	CX,0
	MOV	DX,155
HANG1:	INT	10H
	INC	CX
	CMP	CX,320
	JNE	HANG1
	MOV	CX,0
	INC	DX
	CMP	DX,200
	JNE	HANG1
	RET
CLE	ENDP

PLAY	proc 	near		;演奏 
      	push 	di 
      	push 	si 
      	push 	bp 
      	push 	bx
    	mov si,offset FREQ
      	mov bp,offset MTIM
repts:  mov	di,[si] 
      	cmp	di,0 
	je	endsing 
	mov	bx,ds:[bp]
 	
	call	sound 
	add	si,2 
	add	bp,2 
	JMP	repts 
endsing:    
	pop bx 
	pop bp 
	pop si 
	pop di 
	ret 
PLAY	endp 

sound	proc 	near		;发音
	push	ax 
	push	bx 
	push	cx 
	push	dx 
	push	di

	mov	al,0b6h 
	out	43h,al 
	mov	dx,12h 
	mov	ax,0ffffh 
	div	di 
	out	42h,al 
	mov	al,ah 
	out	42h,al 
	in	al,61h 
	mov	ah,al 
	or	al,3 
	out	61h,al 
delay: 	mov 	cx,0ffffh	;延迟
dl10ms:	loop 	dl10ms 
	dec	bx 
	jnz	delay 
	mov	al,ah 
	out	61h,al 
	pop	di 
	pop	dx 
	pop	cx 
	pop	bx 
	pop	ax 
	ret 
sound	endp

CODE	ENDS
	END	MAIN

⌨️ 快捷键说明

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