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

📄 cal(16dos).asm

📁 一个带有图形界面的计算器程序
💻 ASM
字号:
;TITLE CALCULATOR

;--------------------------------------------------------------------------------------------------------------------------------
;	Purpose	
;	Programmer	Sun
;	FileName	.ASM

;--------------------------------------------------------------------------------------------------------------------------------
.286
	.MODEL	SMALL
	.STACK	128
	.DATA
;DEFINITIONS
MAX	EQU	0CH
LENTH	DB	MAX
RESULT1	DB	MAX DUP(0)
RESULT2	DB	MAX DUP(0),'$'
NUM1	DB	31H,30H,30H,30H,30H,30H,30H,30H,30H,32H,35H,38H,'$'		;A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11 A12
NUM2	DB	30H,30H,31H,30H,30H,30H,30H,30H,30H,30H,30H,30H,'$'		;B1 B2 B3 B4 B5 B6 B7 B8 B9 B10 B11 B12
SIGN	DB	'*','$'
ADDRESS1	DW	?
ADDRESS2	DW	?
ADDRESS3	DW	?
ADDRESS4	DW	?,'$'
NUMBER	DB	?
FLAG	DW	0001H

TEMP1	DB	MAX DUP(0)
TEMP2	DB	MAX DUP(0),'$'
TEMP3	DB	MAX DUP(0),'$'
;--------------------------------------------------------------------------------------------------------------------------------

	.CODE
START	PROC	NEAR
	MOV	AX,@DATA
	MOV	DS,AX
	MOV	ES,AX 
;--------------------------------------------------------------------------------------------------------------------------------
;CODES		
	
	
;;---------------------------modify the input from ASCII to binary code
	
	ENTER	2,0
	LEA	AX,NUM1
	MOV	WORD PTR [BP-2],AX
	CALL	ASCIITOBIN
	LEAVE

	ENTER	2,0
	LEA	AX,NUM2
	MOV	WORD PTR [BP-2],AX
	CALL	ASCIITOBIN
	LEAVE

;;---------------------------

	CMP	SIGN,2AH
	JNZ	A10
	ENTER	8,0
	LEA	AX,NUM1
	MOV	WORD PTR [BP-2],AX	;transmit the address of array num1
	LEA	AX,NUM2
	MOV	WORD PTR [BP-4],AX	;transmit the address of array num2
	LEA	AX,RESULT1
	MOV	WORD PTR [BP-6],AX	;transmit the address of array result1
	LEA	AX,RESULT2
	MOV	WORD PTR [BP-8],AX	;transmit the address of array result2
	CALL	MULTIPLICATION
	LEAVE
	JMP	A40
A10:
	CMP	SIGN,2BH
	JNZ	A20
	ENTER	6,0
	LEA	AX,NUM1
	MOV	WORD PTR [BP-2],AX
	LEA	AX,NUM2
	MOV	WORD PTR [BP-4],AX
	LEA	AX,RESULT2
	MOV	WORD PTR [BP-6],AX
	CALL	ADDITION
	LEAVE
	JMP	A40
A20:
	CMP	SIGN,2DH
	JNZ	A30
	ENTER	6,0
	LEA	AX,NUM1
	MOV	WORD PTR [BP-2],AX
	LEA	AX,NUM2
	MOV	WORD PTR [BP-4],AX
	LEA	AX,RESULT2
	MOV	WORD PTR [BP-6],AX
	CALL	SUBTRACTION
	LEAVE
	JMP	A40
A30:
	CMP	SIGN,2FH
	JNZ	A40
	ENTER	8,0
	LEA	AX,NUM1
	MOV	WORD PTR [BP-2],AX
	LEA	AX,NUM2
	MOV	WORD PTR [BP-4],AX
	LEA	AX,RESULT1
	MOV	WORD PTR [BP-6],AX
	LEA	AX,RESULT2
	MOV	WORD PTR [BP-8],AX
	CALL	DIVITION
	LEAVE
A40:	
	
;;---------------------------modify the output binary code from to ASCII

	CMP	SIGN,2AH
	JZ	B10
	
	CMP	SIGN,2FH
	JZ	B20
	
	CMP	SIGN,2BH
	JZ	B30

	CMP	SIGN,2DH
	JZ	B30

	JMP	B40
B10:
	MOV	AL,LENTH		;modify LENTH
	SHL	AL,01H
	MOV	LENTH,AL

	ENTER	2,0
	LEA	AX,RESULT1
	MOV	WORD PTR [BP-2],AX
	CALL	BINTOASCII
	LEAVE

	MOV	AL,LENTH		;modify LENTH
	SHR	AL,02H
	MOV	LENTH,AL
	JMP	B40
B20:
	ENTER	2,0
	LEA	AX,RESULT1
	MOV	WORD PTR [BP-2],AX
	CALL	BINTOASCII
	LEAVE
B30:
	ENTER	2,0
	LEA	AX,RESULT2
	MOV	WORD PTR [BP-2],AX
	CALL	BINTOASCII
	LEAVE
B40:
	
	
;;---------------------------

	MOV	AH,09H
	LEA	DX,result1
	INT	21H

	MOV	AH,4CH
	INT	21H
	RET
START	ENDP

;--------------------------------------------------------------------------------------------------------------------------------

ASCIITOBIN	PROC	NEAR
	PUSH	ADDRESS1
	PUSHA
	PUSHF

	MOV	AX,[BP-2]
	MOV	ADDRESS1,AX

;;---------------------------initialize array temp[] as 00000...

	LEA	DI,TEMP3
	MOV	CH,00H
	MOV	CL,LENTH

ASCIITOBIN10:
	MOV	AL,00H
	MOV	BX,CX
	MOV	[DI+BX-1],AL
	DEC	CX
	JNZ	ASCIITOBIN10

;;---------------------------

	MOV	CH,00H
	MOV	CL,LENTH
	MOV	DI,ADDRESS1
ASCIITOBIN20:
	MOV	AL,[DI]
	AND	AL,0FH
	MOV	[DI],AL
	INC	DI
	DEC	CX
	JNZ	ASCIITOBIN20 

	MOV	CH,00H
	MOV	CL,LENTH
	MOV	DI,ADDRESS1

ASCIITOBIN30:			;NUM=(...(NUM[0]*0AH+NUM[1])*0AH)*...)+NUM[MAX-1]
				;temp1=temp1*0AH+NUM[i]

;;;	NUM is an array of ASCII '0'~'9', therefor the value: NUM=(...(NUM[0]*10+NUM[1])*10)*...)+NUM[MAX-1] is 
;;;	smaller than FFF...F (MAX F). TEMP3 is enough for NUM as hexadecimal code

	MOV	DL,BYTE PTR [DI]

	ENTER	5,0		;TEMP1=TEMP3*0AH
	LEA	AX,TEMP3
	MOV	WORD PTR [BP-2],AX
	MOV	AH,0AH      
	MOV	BYTE PTR [BP-3],AH
	LEA	AX,TEMP1
	MOV	WORD PTR [BP-5],AX
	CALL	MULTIPLY
	LEAVE
	
	PUSH	CX
	PUSH	DI
	MOV	CH,00H		;TEMP3=TEMP1[LENTH,2*LENTH-1]
	MOV	CL,LENTH		
	LEA	DI,TEMP3
	LEA	SI,TEMP2
	REP	MOVSB
	POP	DI
	POP	CX

	PUSHF			;save ZF
	MOV	BH,00H		;TEMP3=TEMP3+NUM[i]
	MOV	BL,LENTH
	MOV	AL,BYTE PTR TEMP3[BX-1]
	ADD	AL,DL
	MOV	BYTE PTR TEMP3[BX-1],AL
	DEC	BX
ASCIITOBIN40:
	ADC	BYTE PTR TEMP3[BX-1],00H
	DEC	BX
	JNZ	ASCIITOBIN40
	POPF			;pop ZF

	INC	DI
	DEC	CX
	JNZ	ASCIITOBIN30

	MOV	CH,00H
	MOV	CL,LENTH
	MOV	DI,ADDRESS1
	LEA	SI,TEMP3
	REP	MOVSB

	POPF
	POPA
	POP	ADDRESS1
	RET
ASCIITOBIN	ENDP

;--------------------------------------------------------------------------------------------------------------------------------

BINTOASCII	PROC	NEAR
	PUSH	ADDRESS1
	PUSHA
	PUSHF
	

	
	
	MOV	AX,[BP-2]
	MOV	ADDRESS1,AX
	MOV	SI,ADDRESS1

	MOV	CH,00H
	MOV	CL,LENTH
	LEA	DI,TEMP1
	REP	MOVSB

;;;RESULT is not set to 000...0 because there will be more numbers in an uncompressed BCD code than a hexadecimal code,
;;;thus, the old numbers in RESULT will all be replace in the process
	MOV	SI,ADDRESS1	;start division
	MOV	CH,00H
	MOV	CL,LENTH
	ADD	SI,CX
	MOV	DH,0AH
	
BINTOASCII10:	
;	a division round starts
;	in every division, the quotient will be same in temp1 sequently as a divident later, and the last reminder
;	will be saved as result(the ASCII code)
	MOV	CH,00H
	MOV	CL,LENTH
	LEA	DI,TEMP1
	MOV	AH,00H		;AH is set to 00H, later the remind of a early division will be left in AH
	MOV	DL,00H		;DL is used to save CX(DL=CL) the first time when the quotient AL!=0
	
	
BINTOASCII20:
	MOV	AL,[DI]
	DIV	DH		;AX/DH, leaving quotient in AL, reminder in AH
	CMP	AL,00H		;the quotient AL!=0 ?
	JZ	BINTOASCII30
	CMP	DL,00H		;DL is modified to 00H at the beginning
	JNZ	BINTOASCII30
	MOV	DL,CL		;save CX: the first time when quotient AL!=0

BINTOASCII30:
	MOV	[DI],AL		;save the quotient AL, TEMP1 will be used as a divident later
	INC	DI
	DEC	CX
	JNZ	BINTOASCII20

	DEC	SI
	MOV	[SI],AH		;AH is the last reminder of a division round(a division round is between BINTOASCII10)
	
	
	CMP	DL,00H
	JNZ	BINTOASCII10
	
	MOV	CH,00H
	MOV	CL,LENTH
	MOV	DI,ADDRESS1


	
BINTOASCII40:
	MOV	AL,[DI]
	OR	AL,30H
	MOV	[DI],AL
	INC	DI
	DEC	CX
	JNZ	BINTOASCII40
	
	

	POPF
	POPA
	POP	ADDRESS1
	RET
BINTOASCII	ENDP

;--------------------------------------------------------------------------------------------------------------------------------

ADDITION	PROC	NEAR
	PUSH	ADDRESS1
	PUSH	ADDRESS2
	PUSH	ADDRESS3
	PUSHA
	PUSHF


	MOV	AX,[BP-2]
	MOV	ADDRESS1,AX
	MOV	AX,[BP-4]
	MOV	ADDRESS2,AX
	MOV	AX,[BP-6]
	MOV	ADDRESS3,AX
	CLC

	MOV	CH,00H
	MOV	CL,LENTH
A50:
	MOV	BX,CX
	MOV	SI,ADDRESS2
	MOV	AH,[SI+BX-1]
	MOV	DI,ADDRESS1
	MOV	AL,[DI+BX-1]

	ADC	AH,AL
	MOV	SI,ADDRESS3
	MOV	[SI+BX-1],AH
	DEC	CX
	JNZ	A50	
				;the problem of overflow is unsolved
	POPF
	POPA
	POP	ADDRESS3
	POP	ADDRESS2
	POP	ADDRESS1
	RET
ADDITION	ENDP

;------------------------------------------------

SUBTRACTION	PROC	NEAR
	PUSH	ADDRESS1
	PUSH	ADDRESS2
	PUSH	ADDRESS3
	PUSHA
	PUSHF
	
	MOV	AX,[BP-2]
	MOV	ADDRESS1,AX
	MOV	AX,[BP-4]
	MOV	ADDRESS2,AX
	MOV	AX,[BP-6]
	MOV	ADDRESS3,AX
	
	MOV	CL,LENTH
	MOV	CH,00H
A60:
	MOV	BX,CX
	MOV	SI,ADDRESS1
	MOV	AH,[SI+BX-1]
	MOV	SI,ADDRESS2
	MOV	AL,[SI+BX-1]
	SBB	AH,AL
	MOV	SI,ADDRESS3
	MOV	[SI+BX-1],AH
	DEC	CX
	JNZ	A60
				;the problem of overflow is unsolved
	POPF
	POPA
	POP	ADDRESS3
	POP	ADDRESS2
	POP	ADDRESS1
	RET
SUBTRACTION	ENDP

;------------------------------------------------

MULTIPLICATION	PROC	NEAR
	PUSH	ADDRESS1
	PUSH	ADDRESS2
	PUSH	ADDRESS3
	PUSH	ADDRESS4
	PUSHA
	PUSHF

	MOV	AX,[BP-2]
	MOV	ADDRESS1,AX
	MOV	AX,[BP-4]
	MOV	ADDRESS2,AX
	MOV	AX,[BP-6]
	MOV	ADDRESS3,AX
	MOV	AX,[BP-8]
	MOV	ADDRESS4,AX

					;CCCCCC=AAA*BBB
	MOV	CH,00H
	MOV	CL,LENTH
	MOV	DI,ADDRESS2
A70:
	ENTER	5,0
	MOV	AX,ADDRESS1
	MOV	WORD PTR [BP-2],AX
	MOV	AH,[DI]
	MOV	BYTE PTR [BP-3],AH
	LEA	AX,TEMP1
	MOV	WORD PTR [BP-5],AX
	CALL	MULTIPLY			;AAA*B
	LEAVE

	ENTER	2,0
	MOV	AX,ADDRESS3
	MOV	WORD PTR [BP-2],AX
	CALL	MOVERESULT
	LEAVE
	

	MOV	AL,LENTH		;modify LENTH
	SHL	AL,01H
	MOV	LENTH,AL
	ENTER	6,0
	MOV	AX,ADDRESS3
	MOV	WORD PTR [BP-2],AX
	LEA	AX,TEMP1
	MOV	WORD PTR [BP-4],AX
	MOV	AX,ADDRESS3
	MOV	WORD PTR [BP-6],AX
	CALL	ADDITION		;CCCCCC=CCCCCC+AAA*B
	LEAVE
	MOV	AL,LENTH		;modify LENTH
	SHR	AL,01H
	MOV	LENTH,AL

	INC	DI
	DEC	CX
	JNZ	A70

	POPF
	POPA
	POP	ADDRESS4
	POP	ADDRESS3
	POP	ADDRESS2
	POP	ADDRESS1
	RET
MULTIPLICATION	ENDP

;------------------------------------------------

DIVITION	PROC	NEAR
	PUSH	ADDRESS1
	PUSH	ADDRESS2
	PUSH	ADDRESS3
	PUSH	ADDRESS4
	PUSHA
	PUSHF

	MOV	AX,[BP-2]
	MOV	ADDRESS1,AX
	MOV	AX,[BP-4]
	MOV	ADDRESS2,AX
	MOV	AX,[BP-6]
	MOV	ADDRESS3,AX
	MOV	AX,[BP-8]
	MOV	ADDRESS4,AX
	
	MOV	CH,00H
	MOV	CL,LENTH
	MOV	DI,ADDRESS4
	MOV	SI,ADDRESS1
	REP	MOVSB

	MOV	CH,00H
	MOV	CL,LENTH
	MOV	SI,ADDRESS4
	ADD	SI,CX
	MOV	AL,CL
	MOV	DH,08H
	MUL	DH
	MOV	CX,AX

A80:
	ENTER	2,0		;SHL result
	MOV	AX,ADDRESS3
	MOV	WORD PTR [BP-2],AX
	CALL	SHLRESULT
	LEAVE

	ENTER	6,0		;examine if RESULT1>NUM2
	MOV	AX,ADDRESS2
	MOV	WORD PTR [BP-2],AX
	MOV	AX,ADDRESS3
	MOV	WORD PTR [BP-4],AX
	MOV	FLAG,0000H
	LEA	AX,FLAG
	MOV	[BP-6],AX
	CALL	BIGER
	LEAVE
	CMP	FLAG,1111H		;result=result+01h
	JNZ	A90
	
	MOV	AL,[SI-1]
	ADD	AL,01H
	MOV	[SI-1],AL

	ENTER	6,0
	MOV	AX,ADDRESS3
	MOV	WORD PTR [BP-2],AX
	MOV	AX,ADDRESS2
	MOV	WORD PTR [BP-4],AX
	MOV	AX,ADDRESS3
	MOV	WORD PTR [BP-6],AX
	CALL	SUBTRACTION		;result1=result1-num2
	LEAVE
A90:
	DEC	CX
	JNZ	A80

	POPF
	POPA
	POP	ADDRESS4
	POP	ADDRESS3
	POP	ADDRESS2
	POP	ADDRESS1
	RET
DIVITION	ENDP

;------------------------------------------------

MULTIPLY	PROC	NEAR
	PUSH	ADDRESS1
	PUSH	ADDRESS2
	PUSHA
	PUSHF
	
	MOV	AX,[BP-2]
	MOV	ADDRESS1,AX
	MOV	AH,[BP-3]
	MOV	NUMBER,AH
	MOV	AX,[BP-5]
	MOV	ADDRESS2,AX	
	
;;---------------------------initialize array temp[] as 00000...

	MOV	DI,ADDRESS2
	MOV	CH,00H
	MOV	CL,LENTH
	SHL	CX,01H
A100:
	MOV	AL,00H
	MOV	BX,CX
	MOV	[DI+BX-1],AL
	DEC	CX
	JNZ	A100

;;---------------------------

	
	MOV	CH,00H
	MOV	CL,LENTH
	MOV	DI,ADDRESS1
A110:	
	PUSHF			;save ZF
	MOV	AL,[DI]		;temp=temp*10H+Ai*Bi         temp->ADDRESS2
	MOV	AH,00H
	MUL	NUMBER		;DX=Ai*Bi
	MOV	DX,AX	

	ENTER	2,0		;temp=temp*10H
	MOV	AX,ADDRESS2
	MOV	WORD PTR [BP-2],AX
	CALL	MOVERESULT
	LEAVE

	MOV	BH,00H		;temp=temp+Ai*Bi
	MOV	BL,LENTH
	SHL	BX,01H
	MOV	SI,ADDRESS2
	MOV	AL,BYTE PTR [SI+BX-1]
	MOV	AH,BYTE PTR [SI+Bx-2]
	ADD	AX,DX
	MOV	BYTE PTR [SI+BX-1],AL
	MOV	BYTE PTR [SI+BX-2],AH
	DEC	BX
	DEC	BX			
A120:
	ADC	BYTE PTR [SI+BX-1],00H
	DEC	BX
	JNZ	A120
	POPF			;pop ZF
	

	INC	DI
	DEC	CX
	JNZ	A110

	POPF
	POPA
	POP	ADDRESS2
	POP	ADDRESS1	
	RET
MULTIPLY	ENDP

;------------------------------------------------

MOVERESULT	PROC	NEAR
	PUSH	ADDRESS1
	PUSHA
	
	MOV	AX,[BP-2]
	MOV	ADDRESS1,AX

	MOV	CH,00H
	MOV	CL,LENTH
	SHL	CX,01H
	DEC	CX

	MOV	DI,ADDRESS1
A130:
	INC	SI
	MOV	AH,BYTE PTR [DI+1]
	MOV	BYTE PTR [DI],AH
	INC	DI
	DEC	CX
	JNZ	A130
	MOV	AH,00H
	MOV	BYTE PTR [DI],AH

	POPA
	POP	ADDRESS1
	RET
MOVERESULT	ENDP

;------------------------------------------------

BIGER	PROC	NEAR
	PUSH	ADDRESS1
	PUSH	ADDRESS2
	PUSH	ADDRESS3
	PUSHA
	PUSHF

	MOV	AX,[BP-2]
	MOV	ADDRESS1,AX
	MOV	AX,[BP-4]
	MOV	ADDRESS2,AX
	MOV	AX,[BP-6]
	MOV	ADDRESS3,AX

	MOV	CH,00H
	MOV	CL,LENTH
	MOV	DI,ADDRESS1
	MOV	SI,ADDRESS2
A140:
	MOV	AH,[DI]
	MOV	AL,[SI]
	CMP	AH,AL
	JNZ	A150
	INC	DI
	INC	SI
	DEC	CX
	JNZ	A140
A150:
	CMP	AH,AL
	JNBE	A155		;FLAG is set to 0000H before this function is called
	MOV	AX,1111H
	MOV	DI,ADDRESS3
	MOV	[DI],AX
A155:
	POPF
	POPA
	POP	ADDRESS3
	POP	ADDRESS2
	POP	ADDRESS1
	RET
BIGER	ENDP

;------------------------------------------------

SHLRESULT	PROC	NEAR
	PUSH	ADDRESS1
	PUSHA
	PUSHF

	MOV	AX,[BP-2]
	MOV	ADDRESS1,AX

	MOV	DI,ADDRESS1
	MOV	CH,00H
	MOV	CL,LENTH
	SHL	CX,01H
	CLC
A160:
	MOV	BX,CX
	MOV	AL,[DI+BX-1]
	RCL	AL,01H
	MOV	[DI+BX-1],AL
	DEC	CX
	JNZ	A160	

	POPF
	POPA
	POP	ADDRESS1
	RET
SHLRESULT	ENDP

;------------------------------------------------

	END START

⌨️ 快捷键说明

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