汇编源码学习9-子程序设计-输入、输出大整数

;输入大整数,将其反序并由ASCII码值转换成数值,输入以非数字字符为结束符。
;输出大整数,将大整数反序,并转为ASCII码
ASSUME	SS:stack1
stack1	SEGMENT STACK
		DB		256 DUP(?)
stack1	ENDS
;子程序1:输入大整数,将其反序并由ASCII码值转换成数值,输入以非数字字符为结束符。
;入口参数:ES,DI,SI
;ES存放主函数的段地址,DI存放待处理大整型字符串的首地址,SI存放主调函数中长度变量的地址。
;出口:修改大整型和长度变量的值
;用到的寄存器:AX,DS,DI,CX,BX,SI,ES
data2	SEGMENT
		temp	DB 128 DUP(0)
		addrBI	DW ?	;存放传递过来的大整型字符串的首地址
		addrLEN	DW ?	;存放传递过来的长度变量的地址
data2	ENDS
code2	SEGMENT
inBI	PROC	FAR		;input bigint
		ASSUME	CS:code2,DS:data2
		;BEGIN寄存器保护
		PUSH	AX
		PUSH	DS
		PUSH	DI
		PUSH	CX
		PUSH	BX
		PUSH	SI
		PUSH	ES
		;END
		MOV		AX,data2
		MOV		DS,AX
		;保存主调函数传递过来的变量的地址
		MOV		[addrBI],DI
		MOV		[addrLEN],SI
		;BEGIN:输入模块
		LEA		DI,temp
		MOV		CL,0	;记录大整数的位数
		MOV		BL,1	;是否是首位,若首位是0,则继续是首位。1表示是首位,0表示不是
again2_1:
		MOV		AH,1
		INT		21H
		CMP		AL,'0'
		JB		over2_1
		CMP		AL,'9'
		JA		over2_1
		CMP		BL,1	;是否位首位
		JNE		NotFirst	;若不为首位,则继续往下
		CMP		AL,'0'
		JE		again2_1	;为首位,且首位为0,则忽略0,继续输入
NotFirst:
		MOV		BL,0	;将标志更改为“不是首位”
		MOV		[DI],AL
		INC		DI
		INC		CL
		JMP		again2_1
over2_1:
		CMP		AL,0DH	;如果是以Enter结束输入,则先输出一个换行符
		JNE		NotCR
		MOV		DL,0AH
		MOV		AH,02H
		INT		21H
		;END:输入模块结束
NotCR:	MOV		AX,DI	;临时保存DI
		MOV		DI,[addrLEN]
		MOV		ES:[DI],CL	;保存大整数长度
		MOV		DI,AX
		DEC		DI
		MOV		SI,[addrBI]
again2_2:
		MOV		AL,[DI]
		SUB		AL,30H
		MOV		ES:[SI],AL
		DEC		DI
		INC		SI
		DEC		CL
		CMP		CL,0
		JNE		again2_2
		;BEGIN:寄存器恢复
		POP		ES
		POP		SI
		POP		BX
		POP		CX
		POP		DI
		POP		DS
		POP		AX
		;END
		RET
inBI	ENDP
code2	ENDS
;子程序2:输出大整数,将大整数反序,并转为ASCII码
;入口参数:ES,DI,SI
;ES:主调函数的数据段段地址;DI:主调函数中大整型变量的首地址;SI:主调函数中大整型长度变量的地址。
;出口:修改大整型变量
;用到的寄存器:AX,DS,CX,DI,SI,DX,ES
data3	SEGMENT
		addrBI2		DW ?	;存放传递过来的大整型的首地址
		addrLEN2	DW ?	;存放传递过来的大整型长度变量的地址
data3	ENDS
code3	SEGMENT
outBI	PROC	FAR		;output bigint
		ASSUME	CS:code3,DS:data3
		;BEGIN寄存器保护
		PUSH	AX
		PUSH	DS
		PUSH	CX
		PUSH	DI
		PUSH	SI
		PUSH	DX
		PUSH	ES
		;END
		MOV		AX,data3
		MOV		DS,AX
		;用内存变量保存主调函数变量的地址
		MOV		[addrBI2],DI
		MOV		[addrLEN2],SI
		MOV		CL,ES:[SI]
		MOV		SI,DI	;DI存放的是传递过来的大整型的偏移地址
		MOV		CH,0
		ADD		SI,CX
		DEC		SI		;SI指向bigInt尾
again3_1:
		CMP		SI,DI
		JB		over3_1	;SI往回移动,DI往前移动,如果DI移动到SI前面,则循环停止
						;如果这里用JNA,则当长度为奇数时,最中间的数没有转为ASCII码
						;若为JAN,输入:1234567890123456789,12345678901,结果就会有问题
		MOV		AH,ES:[SI]
		ADD		AH,30H
		MOV		AL,ES:[DI]
		ADD		AL,30H
		MOV		ES:[SI],AL
		MOV		ES:[DI],AH
		DEC		SI
		INC		DI
		JMP		again3_1
over3_1:
		MOV		DI,[addrBI2]
		MOV		DX,DI
		ADD		DI,CX
		MOV		ES:[DI],'$(编译时去掉此处括号)'
		MOV		AX,ES
		PUSH	DS
		MOV		DS,AX	;INT 21H的9号功能默认DS:DX,所以除了修改DX的值外,还要修改DS的值
		MOV		AH,09H
		INT		21H
		POP		DS		;养成良好的编程习惯,恢复DS
		;BEGIN:寄存器恢复
		POP		ES
		POP		DX
		POP		SI
		POP		DI
		POP		CX
		POP		DS
		POP		AX
		;END
		RET
outBI	ENDP
code3	ENDS
;主程序
data1	SEGMENT
		bigInt	DB 128 DUP(0)
		len		DB 0
data1	ENDS
code1	SEGMENT
		ASSUME	CS:code1,DS:data1
start:	MOV		AX,data1
		MOV		DS,AX
		;调用大整数输入函数
		MOV		ES,AX		;传递段地址给子函数
		LEA		DI,bigInt	;传递变量bigInt的偏移地址给子函数
		LEA		SI,len		;传递变量len的偏移地址给子函数
		CALL	FAR PTR inBI
		;输出换行符和回车符
		MOV		DL,0AH
		MOV		AH,02H
		INT		21H
		MOV		DL,0DH
		MOV		AH,02H
		INT		21H
		;调用大整数输出函数
		MOV		AX,data1
		MOV		ES,AX		;传递段地址给子函数
		LEA		DI,bigInt	;传递变量bigInt的偏移地址给子函数
		LEA		SI,len		;传递变量len的偏移地址给子函数
		CALL	FAR	PTR	outBI
		MOV		AH,4CH
		INT		21H
code1	ENDS
		END		start

你可能感兴趣的:(汇编)