calculator.asm

来自「基于Multisim9的电子系统设计、仿真与综合应用(实例源文件)」· 汇编 代码 · 共 974 行 · 第 1/2 页

ASM
974
字号
; --------------------------------------------------------------
; Calculator Example 
;
; This program performs calculations of the form:
; 	operand1 operator operand2
; where the operator can be +,-,* or /.
; The operands 1 and 2 are positive integers between 0 and 9999.
; If the result of the calculations exceeds the range between
; 0 and 9999, it is considered an error.
;
; If an error occurs, "EEEE" will be applied to the output pins
; on ports P0 and P2.  The operands and operator are obtained by 
; reading the input signals received on port P1.
; --------------------------------------------------------------
$MOD51

$TITLE(TEST DEMO)

;
; Variables
;

NUM1L		DATA	020H	; low byte of first operand
NUM1H		DATA	021H	; high byte of first operand
OPERATOR	DATA	022H	; operator
NUM2L		DATA	023H	; low byte of second operand
NUM2H		DATA	024H	; high byte of second operand
EWB     DATA  0F8H  ;EWB TRACE SFR

; Program Start

reset:
        ; move stack pointer past register banks and variables
        MOV SP, #28H

	MOV P0, #00H
	MOV P2, #00H

	JMP readystate

; Initialize values in memory	
initVar:
	MOV NUM1L, #00H
	MOV NUM1H, #00H
	MOV OPERATOR, #0FH
	MOV NUM2L, #00H
	MOV NUM2H, #00H
	MOV R5, #00H
	MOV R6, #00H
	RET

; Getting first operand
getnum1:
	MOV A, R1
	MOV A, R5
	MOV NUM1L, A
	MOV A, R6
	MOV NUM1H, A
	
	CALL keyscan
	call displaynum

	MOV A, R1
	XRL A, #03H	; C pressed
	JZ readystate
	MOV A, R1
	XRL A, #02H	; = pressed
	JZ getoperator
	MOV A, R1
	JZ getnum1op	; operator pressed
	JMP getnum1	; continue getting first num

; Got first operand and operator
getnum1op:
	MOV R5, #00H
	MOV R6, #00H
	MOV A, R7
	MOV OPERATOR, A
	JMP getnum2

; Get operator
getoperator:
	MOV R5, #00H
	MOV R6, #00H
		
	CALL keyscan
	call displaynum

	MOV A, R1
	XRL A, #03H	; C pressed
	JZ readystate
	MOV A, R1
	XRL A, #02H 	; = pressed
	JZ getoperator
	MOV A, R1
	JZ gotop	; operator pressed
	JMP getnum1

; Got the operator
gotop:
	MOV A, R7
	MOV OPERATOR, A
	JMP getnum2

; First state that program goes to when started.
; Waiting for the first key press.
readystate:
	CALL initVar

	CALL keyscan
	CALL displaynum

	MOV A, R1
	XRL A, #03H
	JZ readystate	; C pressed
	MOV A, R1
	JZ readystate	; operator pressed
	MOV A, R1
	XRL A, #02H	; = pressed
	JZ readystate
	JMP getnum1

; Get first digit of second operand.
getnum2:
	MOV A, R5
	MOV NUM2L, A
	MOV A, R6
	MOV NUM2H, A

	CALL keyscan
	call displaynum
	
	MOV A, R1
	XRL A, #03H	; C pressed
	JZ readystate	
	MOV A, R1
	XRL A, #02H	; = pressed
	JZ getoperator
	MOV A, R1
	JZ gotop	; operator pressed
	JMP gettingnum2 ; continue getting second num

; Got first digit of second operand.  Continue
; getting subsequent digits of the operand or the next
; operator, = or C key press.
gettingnum2:
	MOV A, R5
	MOV NUM2L, A
	MOV A, R6
	MOV NUM2H, A

	CALL keyscan
	call displaynum

	MOV A, R1
	XRL A, #03H	; C pressed
	JZ readystate	
	MOV A, R1
	XRL A, #02H	; = pressed
	JZ calcgetop	; Go do calculation
	MOV A, R1 
	JZ calcgetnum2	; operator pressed; go do calculation
	JMP gettingnum2	

; calculate result then get next operator	
calcgetop:
	CALL calculate

	MOV A, R0
	XRL A, #0EEH
	JNZ calcgetopend
	MOV A, R1
	XRL A, #0EEH
	JZ readystate
calcgetopend: 
	MOV A, R0
	MOV NUM1L, A
	MOV A, R1
	MOV NUM1H, A
	JMP getoperator

; calculate result then get next number
calcgetnum2:
	CALL calculate
	
	MOV A, R0
	XRL A, #0EEH
	JNZ calcgetnum2end
	MOV A, R1
	XRL A, #0EEH
	JZ readystate
calcgetnum2end:
	MOV A, R0
	MOV NUM1L, A
	MOV A, R1
	MOV NUM1H, A
	MOV A, R7
	MOV OPERATOR, A
	MOV R5, #00H
	MOV R6, #00H
	JMP getnum2

; Perform +, -, * or / operations
; Input:
; Values stored in variables NUM1L, NUM1H, OPERATOR, NUM2L, NUM2H
; Output:
; R0 - low byte of result
; R1 - high byte of result
; Valid values of R1, R0 range from 0 to 270FH (9999 in base 10)
; In case of overflow or error, R0 and R1 will each contain #0EEh
calculate:
	PUSH ACC
	MOV A, R2
	PUSH ACC
	MOV A, R3
	PUSH ACC
	MOV A, R5
	PUSH ACC
	MOV A, R6
	PUSH ACC

	MOV R0, NUM1L
	MOV R1, NUM1H
	MOV R2, NUM2L
	MOV R3, NUM2H
calcAdd:
	MOV A, OPERATOR
	CJNE A, #0CH, calcSub
	CALL ADD16
	; check for overflow
	MOV A, #027H
	SUBB A, R1
	JC calcoverflow
	JNZ calcAddEnd
	MOV A, #0FH
	SUBB A, R0
	JC calcoverflow
calcAddEnd:
	JMP calcDisplay	
	
calcSub:
	MOV A, OPERATOR
	CJNE A, #08H, calcMul
	CALL SUB16
	MOV A, #027H
	SUBB A, R1
	JC calcoverflow
	JNZ calcSubEnd
	MOV A, #0FH 
	SUBB A, R0
	JNC calcSubEnd
	JMP calcoverflow
calcSubNeg:		; calculate the negative value in BCD 
	MOV A, R0	; (not used right now - negative values are
	MOV R2, A	; considered an overflow)
	MOV A, R1
	MOV R3, A
	MOV R0, #00H
	MOV R1, #00H
	CALL SUB16
	SETB C
calcSubEnd:
	JMP calcDisplay

calcMul:
	MOV A, OPERATOR
	CJNE A, #04H, calcDiv
	CALL UMUL16	
	; make sure that result is not greater than 270FH (9999 in base 10)
	MOV A, R3
	JNZ calcoverflow
	MOV A, R2
	JNZ calcoverflow
	
	MOV A, #027H
	SUBB A, R1
	JC calcoverflow
	JNZ calcMulEnd
	MOV A, #0FH
	SUBB A, R0
	JC calcoverflow
calcMulEnd:
	JMP calcDisplay

calcDiv:
	MOV A, OPERATOR 
	CJNE A, #00H, calcError
	; check divide by zero
	MOV A, R2
	JNZ calcDoDiv
	MOV A, R3
	JZ calcDivByZero
calcDoDiv:
	CALL UDIV16
	JMP calcDisplay

; error occurred
calcError:
; divide by zero error
calcDivByZero:
; overflow occurred
calcoverflow:
	MOV R0, #0EEH
	MOV R1, #0EEH
	MOV A, #0EEH
	MOV P2, A
	MOV P0, A
	CALL delay
	JMP calcEnd

; Display results of calculation.
; R0 and R1 contains low and high byte of result
calcDisplay:
	MOV A, R0
	MOV R5, A
	MOV A, R1
	MOV R6, A
	CALL HEXtoDEC
	MOV A, R5
	MOV P2, A
	MOV A, R6
	MOV P0, A
	CALL delay

calcEnd:
	POP ACC
	MOV A, R6
	POP ACC
	MOV A, R5
	POP ACC
	MOV A, R3
	POP ACC
	MOV A, R2
	POP ACC
	RET

; Returns key pressed in (row,col) format in R7
; For example: R7 = #028H if 1 was pressed on the keypad
;            Keypad 
; Row # -----------------
; 8     | 7   8   9   + |
; 4     | 4   5   6   - |
; 2     | 1   2   3   * |
; 1     | C   0   =   / |
;       -----------------
; Col #   8   4   2   1
keyscan:
	PUSH ACC
	MOV A, R0
	PUSH ACC
	MOV A, R1
	PUSH ACC
	MOV A, R3
	PUSH ACC

        MOV P1, #00FH

waitkeyuploop:
	MOV A, P1
	ANL A, #00FH
	XRL A, #00FH
	JNZ waitkeyuploop

        MOV P1, #00FH

anykeyloop:
        MOV A, P1
        ANL A, #00FH
        XRL A, #00FH
        JZ anykeyloop
        MOV R0, A
        XRL A, #00FH
        MOV R3, A

        call lineclear
        MOV P1, #0EFH
        MOV R1, #010H
        NOP
        MOV A, P1
        ANL A, #00FH
        XRL A, R3
	MOV R2,#000H
        JZ scanmatch

        call lineclear
        MOV P1, #0DFH
        MOV R1, #020H
        NOP
        MOV A, P1
        ANL A, #00FH
        XRL A, R3
	MOV R2, #001H
        JZ scanmatch

        call lineclear
        MOV P1, #0BFH
        MOV R1, #040H
        NOP
        MOV A, P1
        ANL A, #00FH
        XRL A, R3
	MOV R2, #002H
        JZ scanmatch

        call lineclear
        MOV P1, #07FH
        MOV R1, #080H
        NOP
        MOV A, P1
        ANL A, #00FH
        XRL A, R3
	MOV R2, #003H
        JZ scanmatch

        MOV P1, #00FH
        JMP keyscan
scanmatch:
        MOV A, R1
        ORL A, R0  	; combine into scancode

	MOV R7, A	; R7 contains value in (row,col) format
	
keyscanend:
	POP ACC
	MOV R3, A
	POP ACC
	MOV R1, A
	POP ACC
	MOV R0, A
	POP ACC
	RET

; Input:
; R7 contains last key pressed
; R2 contains last key pressed in converted number
; R5 and R6 contains current number in hex
; Output:
; R5 and R6 contains new number in hex 
displaynum:
	MOV A, R7

	MOV R4, A
	MOV A, R2
	MOV B, #04H
	MUL AB
	MOV R2, A
	MOV A, R4
	ANL A, #00FH
	MOV R4, #000H
getnumloop:
	INC R4
	RR A
	ANL A, #00FH
	JNZ getnumloop
	DEC R4
	MOV A, R2
	ADD A, R4
	MOV R1, A

checknum2:
	CJNE A, #02H,checknum5
	MOV A, #00H
	JMP numfound 
checknum5:
	CJNE A, #05H,checknum6
	MOV A, #03H
	JMP numfound 
checknum6:
	CJNE A, #06H,checknum7
	MOV A, #02H
	JMP numfound 
checknum7:
	CJNE A, #07H,checknum9
	MOV A, #01H
	JMP numfound 
checknum9:
	CJNE A, #09H,checknum10
	MOV A, #06H
	JMP numfound 
checknum10:
	CJNE A, #0AH,checknum11
	MOV A, #05H
	JMP numfound 
checknum11:
	CJNE A, #0BH,checknum13
	MOV A, #04H
	JMP numfound 

⌨️ 快捷键说明

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