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

📄 leq.asm

📁 在定时器中断中做LED的PWM输出 AT89C2051实现A/D转换的C51程序 单片机开发系统 指令系统 程序设计 定时与中断 系统扩展 接口技术 串行口
💻 ASM
📖 第 1 页 / 共 2 页
字号:
;解线性方程组的主元消去法(有回代过程)。
;入口条件:
; 方程组系数增广矩阵存放在片外RAM中指定的页面内,
; 数据格式为三字节二进制浮点数,方程组最大阶数为八阶。
;出口信息:
; 方程组的解X1,X2,...Xn依次在首址为WORK的内存中(二进制浮点数形式)。
ANNB	EQU	20H	;方程组系数增广矩阵存放的片外RAM页面。
WORK	EQU	30H	;工作区及方程根存放区首址。
WORK1	EQU	4BH	;辅助工作区。
N	EQU	5	;未知数个数(最多为八个)。
I	DATA	29H	;行指针变量。
J	DATA	2AH	;列指针变量。
K	DATA	2BH	;辅助指针变量。
CON	DATA	2CH	;计数器
TEMP	EQU	2DH	;临时浮点变量存放首址。

FLAG	DATA	23H	;浮点运算标志
PFA	BIT	FLAG.7
PFB	BIT	FLAG.6
PFC	BIT	FLAG.5
PFD	BIT	FLAG.4

	ORG	0000H
	LJMP	TEST
	
	ORG	100H
TEST:	MOV	DPTR,#DATS;把测试数据复制到片外RAM指定的页面。
	MOV	P2,#ANNB;系数增广矩阵存放首址。
	MOV	R1,#0
	MOV	A,#N	;计算系数个数。
	MOV	B,A
	INC	A
	MUL	AB
	MOV	CON,A
TRA0:	MOV	R5,#3	;每个系数有三个字节。
	MOV	R0,#TEMP;先读到片内RAM。
TRA2:	CLR	A
	MOVC	A,@A+DPTR
	MOV	@R0,A
	INC	DPTR
	INC	R0
	DJNZ	R5,TRA2
	MOV	A,R1
	PUSH	ACC
	MOV	R0,#TEMP
	PUSH	DPH
	PUSH	DPL
	LCALL	BTOF	;把方程各系数由十进制浮点数转换成二进制浮点数。
	POP	DPL
	POP	DPH
	POP	ACC
	MOV	R1,A
	MOV	R5,#3	;再存放到片外RAM指定页面。
TRA3:	MOV	A,@R0
	MOVX	@R1,A
	INC	R0
	INC	R1
	DJNZ	R5,TRA3
	DJNZ	CON,TRA0;将所有系数均存放好。
	LCALL	LEQ	;调用有回代主元消去法求解方程组的根。
	MOV	CON,#N	;将全部根
	MOV	R0,#WORK
TRA4:	LCALL	FTOB	;转换成十进制浮点数。
	INC	R0
	INC	R0
	INC	R0
	DJNZ	CON,TRA4
STOP:	LJMP	STOP	

;测试结果X1=1.000 ( 01H 10H 00H )
;测试结果X2=-0.9999 ( 80H 99H 99H )(准确值为-1.000)
;测试结果X3=2.000 ( 01H 20H 00H )
;测试结果X4=-2.000 ( 81H 20H 00H )
;测试结果X5=1.000 ( 01H 10H 00H )

DATS:	DB	01H,30H,0H	;系数增广矩阵A11=3.0
	DB	01H,20H,0H	;A12=2.0
	DB	41H,00H,0H	;A13=0.0
	DB	01H,10H,0H	;A14=1.0
	DB	81H,20H,0H	;A15=-2.0
	DB	81H,30H,0H	;B1 =-3.0
	DB	01H,10H,0H	;A21=1.0
	DB	81H,10H,0H	;A22=-1.0
	DB	01H,20H,0H	;A23=2.0
	DB	01H,30H,0H	;A24=3.0
	DB	01H,50H,0H	;A25=5.0
	DB	01H,50H,0H	;B2 =5.0
	DB	41H,00H,0H	;A31=0.0
	DB	01H,30H,0H	;A32=3.0
	DB	41H,00H,0H	;A33=0.0
	DB	01H,20H,0H	;A34=2.0
	DB	01H,10H,0H	;A35=1.0
	DB	81H,60H,0H	;B3 =-6.0
	DB	81H,10H,0H	;A41=-1.0
	DB	41H,00H,0H	;A42=0.0
	DB	01H,10H,0H	;A43=1.0
	DB	01H,10H,0H	;A44=1.0
	DB	41H,00H,0H	;A45=0.0
	DB	81H,10H,0H	;B4 =-1.0
	DB	01H,40H,0H	;A51=4.0
	DB	01H,10H,0H	;A52=1.0
	DB	01H,20H,0H	;A53=2.0
	DB	81H,10H,0H	;A54=-1.0
	DB	81H,10H,0H	;A55=-1.0
	DB	01H,80H,0H	;B5 =8.0

LEQ:	MOV	DPH,#ANNB;无回代主元消去法。
	MOV	P2,#ANNB;指向系数存放页面。
	MOV	I,#0	;从第一行(行号为0)开始处理。
LEQ0:	MOV	A,I	;取将要处理的行号。
	INC	A
	XRL	A,#N
	JZ	LEQ1	;如果是最后一行,不必寻找主元。
	LCALL	FINDMIN	;寻找主元,并将其所在行交换到当前处理行位置上。
LEQ1:	LCALL	DIVMIN	;将当前处理行的各个系数除以主元,使主元为1。
	MOV	A,I
	INC	A
	MOV	K,A	;从主元下一行开始,进行消元处理。
	XRL	A,#N
	JZ	LEQ4	;没有下一行,结束消元工作。
LEQ2:	LCALL	DEL	;进行消元处理。
	INC	K	;调整到下一行。
	MOV	A,K
	XRL	A,#N
	JNZ	LEQ2	;直到各行均进行过消元处理。
	INC	I	;调整寻找主元的行号。
	MOV	A,I
	XRL	A,#N
	JNZ	LEQ0	;直到整个系数矩阵主对角线全部为1。
LEQ4:	MOV	I,#0	;增广矩阵的最后一列,就是方程组的常数项。
	MOV	J,#N	
	LCALL	LOADH	;将其调入片内RAM中。
	MOV	I,#N-2	;从倒数第二行开始进行回代。
LEQ5:	MOV	J,I
	INC	J
	MOV	A,#WORK1
	LCALL	LOADL	;将回代行主对角线右侧系数调入片内。
	MOV	A,#N	;计算乘积项数。
	SETB	C
	SUBB	A,I
	PUSH	ACC
	MOV	CON,A
	MOV	A,#N-1	;计算Bn-1的地址。
	MOV	B,#3
	MUL	AB
	ADD	A,#WORK
	MOV	R1,A	;R1先指向Bn-1,即Xn-1的值。
	MOV	A,CON	;计算Ai,n-1的地址。
	DEC	A
	MOV	B,#3
	MUL	AB
	ADD	A,#WORK1
	MOV	R0,A	;R0先指向Ai,n-1。
LEQ6:	LCALL	FMUL	;计算乘积Ai,k×Bk→ Ai,k。
	DEC	R0	;调整系数项指针。
	DEC	R0
	DEC	R0
	DEC	R1	;调整根指针。	
	DEC	R1
	DEC	R1
	DJNZ	CON,LEQ6;计算完各个乘积项。
	POP	CON
	MOV	A,R1
	MOV	R0,A	;指向Bi。
	MOV	R1,#WORK1;指向乘积项。
LEQ7:	LCALL	FSUB	;减去乘积项。
	INC	R1
	INC	R1
	INC	R1
	DJNZ	CON,LEQ7;减完各个乘积项后,便得到根Xi。
	DEC	I	;上移一行。
	MOV	A,I
	JNB	ACC.7,LEQ5;还有,继续回代。
	RET		;求解方程组的任务完成。

FINDMIN:MOV	J,I	;寻找主元,定位主对角线系数。
	LCALL	LOADH	;将主对角线系数及其以下同一列的系数读入片内。
	MOV	R0,#WORK;先设第一个系数为最大值。
	MOV	R1,#WORK+3;从第二个系数开始进行比较。
	MOV	A,#N	;计算比较的次数。
	SETB	C
	SUBB	A,I
	MOV	CON,A
	MOV	A,@R0	;取绝对值。
	CLR	ACC.7
	MOV	@R0,A
MAX:	MOV	A,@R1	;取绝对值。
	CLR	ACC.7
	MOV	@R1,A
	LCALL	FCMP	;比较。
	JNC	MAX1
	MOV	A,R1	;以比较对象为新的最大值。
	MOV	R0,A
MAX1:	INC	R1	;准备比较下一个系数。
	INC	R1
	INC	R1
	DJNZ	CON,MAX	;完成所有比较。
	MOV	A,R0	;取最大值的地址。
	CLR	C
	SUBB	A,#WORK	;和主对角线系数的距离(字节数)。
	JZ	FINDE	;为零,主对角线系数就是最大值系数,不必交换。
	MOV	B,#3	;将距离转换为系数个数。
	DIV	AB
	ADD	A,I	;加上当前行号,
	MOV	K,A	;得到最大值所在行号。
	MOV	J,I	;主对角线系数的列号和行号相同。
	LCALL	ADDR	;计算主对角线系数的地址。
	MOV	R0,DPL	;保存地址在R0中。
	PUSH	I	;保存主对角线系数的行号。
	MOV	I,K	;将行号改为最大值的行号(列号不变)。
	LCALL	ADDR	;计算地址。
	MOV	R1,DPL	;保存地址在R1中。
	POP	I	;恢复主对角线系数的行号。
	MOV	A,#N+1	;计算待交换系数的字节数。
	CLR	C
	SUBB	A,J
	MOV	B,#3
	MUL	AB
	MOV	R7,A
XCHG:	MOVX	A,@R0	;交换两行,使最大值系数处于主对角线上。
	MOV	R6,A
	MOVX	A,@R1
	XCH	A,R6
	MOVX	@R1,A
	MOV	A,R6
	MOVX	@R0,A
	INC	R1
	INC	R0
	DJNZ	R7,XCHG
FINDE:	RET		;完成主元寻找和交换任务。

DEL:	MOV	J,I	;待消元的系数的列号等于主元的行号。
	PUSH	I	;保存主元的行号。
	MOV	I,K	;指向待消元的行号。
	MOV	A,#WORK	;指向片内工作区。
	LCALL	LOADL	;将待消元的一行系数调入片内工作区。
	POP	I	;恢复主元行号。
	MOV	A,#N	;计算需要调整数值的系数个数。
	CLR	C
	SUBB	A,J
	MOV	CON,A
	MOV	R0,#WORK+3;指向第一个待调整数值的系数A k , j。
	MOV	R1,#WORK1+3;指向主元数值行的第一个参照系数A i , j。
DEL1:	MOV	TEMP,WORK;将待消元的系数值A k , i复制到临时变量中。
	MOV	TEMP+1,WORK+1
	MOV	TEMP+2,WORK+2
	MOV	A,R0
	PUSH	ACC
	MOV	R0,#TEMP
	LCALL	FMUL	;计算A k , i×A i , j→TEMP。
	POP	ACC
	MOV	R0,A
	MOV	A,R1
	PUSH	ACC
	MOV	R1,#TEMP
	LCALL	FSUB	;计算A k , j=A k , j-A k , i×A i , j
	POP	ACC
	MOV	R1,A
	INC	R0
	INC	R0
	INC	R0
	INC	R1
	INC	R1
	INC	R1
	DJNZ	CON,DEL1;将待消元行有关系数全部调整好。
	MOV	J,I	;主元所在的列号等于行号。
	INC	J	;加一,得到已调整系数的最小列号。
	PUSH	I
	MOV	I,K	;取已调整系数的行号。
	MOV	A,#WORK+3;取已调整系数在片内的首址。
	LCALL	SAVE	;将全部已调整系数存回到片外RAM原来位置上。
	POP	I	;恢复主元行号。
	RET		;一行消元处理结束。

DIVMIN:	MOV	J,I	;主元所在行系数处理。
	MOV	A,#WORK1;指向辅助工作区。
	LCALL	LOADL	;将主元所在行的系数调入片内RAM中。
	MOV	R1,#WORK1;以主元作除数。
	MOV	R0,#WORK1+3;其右的系数作为第一个被除数。
	MOV	A,#N	;计算需要处理的系数个数。
	CLR	C
	SUBB	A,I
	MOV	CON,A
DMIN:	LCALL	FDIV	;进行除法运算A i , j=A i , j/A i , i。
	INC	R0
	INC	R0
	INC	R0
	DJNZ	CON,DMIN
	MOV	A,#WORK1+3;指向片内第一个已经处理的系数。
	MOV	J,I
	INC	J	;列号j=i+1。
SAVE:	MOV	R0,A	;片内首址。
	LCALL	ADDR	;计算片外首址。
	MOV	A,#N+1	;计算回存字节数。
	CLR	C
	SUBB	A,J
	MOV	B,#3
	MUL	AB
	MOV	R7,A
SAVE1:	MOV	A,@R0	;回存到片外。
	MOVX	@DPTR,A
	INC	DPTR
	INC	R0
	DJNZ	R7,SAVE1
	RET

LOADL:	MOV	R0,A	;片内首址。
	LCALL	ADDR	;计算片外首址。
	MOV	A,#N+1	;计算回存字节数。
	CLR	C
	SUBB	A,J
	MOV	B,#3
	MUL	AB
	MOV	R7,A
LOAD1:	MOVX	A,@DPTR	;调入到片内。
	MOV	@R0,A
	INC	DPTR
	INC	R0
	DJNZ	R7,LOAD1
	RET

LOADH:	MOV	R0,#WORK;将一列系数调入WORK为首址片内RAM中。
	MOV	A,#N	;计算同一列相邻系数中间间隔的字节数。
	MOV	B,#3
	MUL	AB
	MOV	R6,A
	LCALL	ADDR	;计算片外首址。
	MOV	A,#N	;计算调入系数个数。
	CLR	C
	SUBB	A,I
	MOV	R7,A
LOAD2:	MOV	R2,#3	;每个系数为三个字节。
LOAD3:	MOVX	A,@DPTR	;调入一个系数。
	MOV	@R0,A
	INC	DPTR
	INC	R0
	DJNZ	R2,LOAD3
	MOV	A,DPL	;调整到同一列下一个相邻系数的首址。
	ADD	A,R6
	MOV	DPL,A
	DJNZ	R7,LOAD2;将所需系数全部调入片内RAM中。
	RET	

ADDR:	MOV	B,#N+1	;计算A i , j的片外地址(低八位)。
	MOV	A,I
	MUL	AB
	ADD	A,J
	MOV	B,#3
	MUL	AB
	MOV	DPL,A
	RET

;以下是浮点运算子程序库。
FADD:	CLR	F0
	SJMP	AS
FSUB:	SETB	F0
AS:	LCALL	MVR1
	MOV	C,F0
	RRC	A
	XRL	A,@R1
	MOV	C,ACC.7
ASN:	MOV	PFB,C
	XRL	A,@R0
	RLC	A
	MOV	F0,C
	LCALL	MVR0
	LCALL	AS1
MOV0:	INC	R0
	INC	R0
	MOV	A,R4
	MOV	@R0,A
	DEC	R0
	MOV	A,R3
	MOV	@R0,A
	DEC	R0
	MOV	A,R2
	MOV	C,PFA
	MOV	ACC.7,C
	MOV	@R0,A
	CLR	ACC.7
	CLR	OV
	CJNE	A,#3FH,MV01
	SETB	OV
MV01:	MOV	A,@R0
	RET

MVR0:	MOV	A,@R0
	MOV	C,ACC.7
	MOV	PFA,C
	MOV	C,ACC.6
	MOV	ACC.7,C
	MOV	R2,A
	INC	R0
	MOV	A,@R0
	MOV	R3,A
	INC	R0
	MOV	A,@R0
	MOV	R4,A
	DEC	R0
	DEC	R0
	RET

MVR1:	MOV	A,@R1
	MOV	C,ACC.7
	MOV	PFB,C
	MOV	C,ACC.6
	MOV	ACC.7,C
	MOV	R5,A
	INC	R1
	MOV	A,@R1
	MOV	R6,A
	INC	R1
	MOV	A,@R1
	MOV	R7,A
	DEC	R1
	DEC	R1
	RET

AS1:	MOV	A,R6
	ORL	A,R7
	JZ	AS2
	MOV	A,R3
	ORL	A,R4
	JNZ	EQ1
	MOV	A,R6
	MOV	R3,A
	MOV	A,R7
	MOV	R4,A
	MOV	A,R5
	MOV	R2,A
	MOV	C,PFB
	MOV	PFA,C
AS2:	RET
EQ1:	MOV	A,R2
	XRL	A,R5
	JZ	AS4
	JB	ACC.7,EQ3
	MOV	A,R2
	CLR	C
	SUBB	A,R5
	JC	EQ4
EQ2:	CLR	C
	MOV	A,R6
	RRC	A
	MOV	R6,A
	MOV	A,R7
	RRC	A
	MOV	R7,A
	INC	R5
	ORL	A,R6
	JNZ	EQ1
	MOV	A,R2
	MOV	R5,A
	SJMP	AS4
EQ3:	MOV	A,R2
	JNB	ACC.7,EQ2
EQ4:	CLR	C
	LCALL	RR1
	ORL	A,R3
	JNZ	EQ1
	MOV	A,R5
	MOV	R2,A
AS4:	JB	F0,AS5
	MOV	A,R4
	ADD	A,R7
	MOV	R4,A
	MOV	A,R3
	ADDC	A,R6
	MOV	R3,A
	JNC	AS2
	LJMP	RR1
AS5:	CLR	C
	MOV	A,R4
	SUBB	A,R7
	MOV	B,A
	MOV	A,R3
	SUBB	A,R6
	JC	AS6
	MOV	R4,B
	MOV	R3,A
	LJMP	RLN
AS6:	CPL	PFA
	CLR	C
	MOV	A,R7
	SUBB	A,R4
	MOV	R4,A
	MOV	A,R6
	SUBB	A,R3
	MOV	R3,A
RLN:	MOV	A,R3
	ORL	A,R4
	JNZ	RLN1
	MOV	R2,#0C1H
	RET
RLN1:	MOV	A,R3
	JB	ACC.7,RLN2
	CLR	C
	LCALL	RL1
	SJMP	RLN
RLN2:	CLR	OV
	RET
RL1:	MOV	A,R4
	RLC	A
	MOV	R4,A
	MOV	A,R3
	RLC	A
	MOV	R3,A
	DEC	R2
	CJNE	R2,#0C0H,RL1E
	CLR	A
	MOV	R3,A
	MOV	R4,A
	MOV	R2,#0C1H
RL1E:	CLR	OV
	RET

RR1:	MOV	A,R3
	RRC	A
	MOV	R3,A
	MOV	A,R4
	RRC	A
	MOV	R4,A
	INC	R2
	CLR	OV
	CJNE	R2,#40H,RR1E
	MOV	R2,#3FH
	SETB	OV
RR1E:	RET

FMUL:	LCALL	MVR0
	MOV	A,@R0
	XRL	A,@R1
	RLC	A
	MOV	PFA,C
	LCALL	MUL0
	LJMP	MOV0
MUL0:	LCALL	MVR1
MUL1:	MOV	A,R3
	ORL	A,R4
	JZ	MUL6
	MOV	A,R6
	ORL	A,R7
	JZ	MUL5
	MOV	A,R7
	MOV	B,R4
	MUL	AB
	MOV	A,B
	XCH	A,R7
	MOV	B,R3
	MUL	AB
	ADD	A,R7
	MOV	R7,A
	CLR	A
	ADDC	A,B
	XCH	A,R4
	MOV	B,R6
	MUL	AB
	ADD	A,R7
	MOV	R7,A
	MOV	A,B
	ADDC	A,R4
	MOV	R4,A
	CLR	A
	RLC	A
	XCH	A,R3
	MOV	B,R6
	MUL	AB
	ADD	A,R4
	MOV	R4,A
	MOV	A,B
	ADDC	A,R3
	MOV	R3,A
	JB	ACC.7,MUL2
	MOV	A,R7
	RLC	A
	MOV	R7,A
	LCALL	RL1
MUL2:	MOV	A,R7
	JNB	ACC.7,MUL3
	INC	R4
	MOV	A,R4
	JNZ	MUL3
	INC	R3
	MOV	A,R3
	JNZ	MUL3
	MOV	R3,#80H
	INC	R2
MUL3:	MOV	A,R2
	ADD	A,R5
MD:	MOV	R2,A
	JB	ACC.7,MUL4
	JNB	ACC.6,MUL6
	MOV	R2,#3FH
	SETB	OV
	RET
MUL4:	JB	ACC.6,MUL6
MUL5:	CLR	A
	MOV	R3,A
	MOV	R4,A
	MOV	R2,#41H
MUL6:	CLR	OV
	RET

FDIV:	INC	R0
	MOV	A,@R0
	INC	R0
	ORL	A,@R0
	DEC	R0
	DEC	R0

⌨️ 快捷键说明

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