here is the four function calculator assembly code

Status
Not open for further replies.

shokoofeh

Newbie level 4
Joined
Sep 9, 2009
Messages
7
Helped
1
Reputation
2
Reaction score
0
Trophy points
1,281
Location
Iran
Activity points
1,429
It is tested and it works! you can calculate 2 digit numbers!
enjoy!!

FLAG EQU 30H ; Operand : + - * /
INPUTNUM EQU 31H ; Input Key Number
INPUTKEY EQU 32H ; Input Key Code
M1 EQU 34H ; Used in PackedBCD
M2 EQU 35H ; Used in PackedBCD
NUM1 EQU 40H ; Two digit in BCD
NUM2 EQU 41H ; Two digit in BCD
RESULTP EQU 42H ; Used for Floating Point Numbers
RESULTL EQU 43H ; Low Byte of Result
RESULTH EQU 44H ; High Byte of Result
DIGITS EQU 46H ; Number of Digits on 7seg
TEMP0 EQU 60H ; Temporary Variable
TEMP1 EQU 61H ; Temporary Variable
TEMP2 EQU 62H ; Temporary Variable
TEMP3 EQU 63H ; Temporary Variable

ORG 0000H
; Initializing
MOV M1,#0
MOV M2,#0
MOV FLAG,#0
MOV NUM1,#0
MOV NUM2,#0
MOV RESULTL,#0
MOV RESULTH,#0
MOV RESULTP,#0
CLR PSW.1 ; Positive number (0 = Pos. , 1 = Neg.)

keyup:
LCALL DisplayResult ;
LCALL Keyboard ;
CJNE A,#0FFH,keyup ; Key Up
readkey:
LCALL DisplayResult ;
LCALL Keyboard ;
CJNE A,#0FFH,keypressed ; Key Down
SJMP readkey ; No Key

keypressed:
MOV INPUTKEY,A ; Save Input Key
LCALL GetKeyNum ; Generate Key Number
MOV INPUTNUM,A ; Save Key Number
MOV R7,A ; R7 = Key Number
CJNE R7,#0FH,notenter ; Check Enter Key
LCALL Calculator ; Calculate
LJMP keyup ; Read Next Numbers or Operands

notenter:
MOV R7,INPUTNUM ;
CJNE R7,#0EH,notc ; Check 'ON/C' key (Clear)
MOV M1,#0 ; Clear 1st Digit
MOV M2,#0 ; Clear 2nd Digit
MOV RESULTP,#0 ; Clear Results Floating Point
MOV RESULTL,#0 ; Clear Results High Byte
MOV RESULTH,#0 ; Clear Results Low Byte
CLR PSW.1 ; Positive number
LCALL Clean7Seg ; Clear 7Seg
LJMP keyup ; Jump & Wait for Keys

notc:
MOV R7,INPUTNUM ; R7 = Key Number
CJNE R7,#0AH,notadd ; Check Add Key
MOV FLAG,#1 ; Flag = Add
MOV M1,#0 ; Clear 1st Digit
MOV M2,#0 ; Clear 2nd Digit
LJMP keyup ; Read Next Numbers

notadd:
MOV R7,INPUTNUM ; R7 = Key Number
CJNE R7,#0BH,notsubb ; Check Subtract Key
MOV FLAG,#2 ; Flag = Sub
MOV M1,#0 ; Clear 1st Digit
MOV M2,#0 ; Clear 2nd Digit
LJMP keyup ; Read Next Numbers

notsubb:
MOV R7,INPUTNUM ; R7 = Key Number
CJNE R7,#0CH,notmul ; Check Multiply
MOV FLAG,#3 ; Flag = Mul
MOV M1,#0 ; Clear 1st Digit
MOV M2,#0 ; Clear 2nd Digit
LJMP keyup ; Read Next Numbers

notmul:
MOV R7,INPUTNUM ; R7 = Key Number
CJNE R7,#0DH,is_number ; Check Division
MOV FLAG,#4 ; Flag = Div
MOV M1,#0 ; Clear 1st Digit
MOV M2,#0 ; Clear 2nd Digit
LJMP keyup ; Read Next Numbers

is_number:
MOV RESULTH,#0 ; Clear Results High Byte
MOV RESULTP,#0 ; Clear Results Low Byte
CLR PSW.1 ; Positive Number
LCALL PackedBCD ; Convert to BCD
LJMP keyup ; Read Next Numbers

; Converting to PackedPCB fuction
PackedBCD:
MOV A,M2 ; ACC = 2nd Digit
JNZ thirdnumber ; Check ACC (M2 = 0 if we have 3 Numbers)
SJMP packnumbers ;

thirdnumber:
MOV M1,#0 ; Clear 1st Digit
MOV M2,#0 ; Clear 2nd Digit
packnumbers:
MOV A,INPUTNUM ; ACC = Key Number
MOV M2,M1 ; Save 1st Digit
MOV M1,A ; M1 = Key Number
MOV A,M2 ; ACC = 1st Digit
SWAP A ; Swap ACC Nibbles
ORL A,M1 ; ACC[7..4] = 1st Digit & ACC[3..0] = 2nd Digit
MOV RESULTL,A ; Result Low Byte = Packed Numbers
MOV R7,FLAG ; R7 = Flag
CJNE R7,#0,nextnum ; Check Flag
MOV NUM1,A ; Flag = 0 --> 1st Number (before Pressing any Operand)
RET ;
nextnum:
MOV NUM2,A ; Flag != 0 --> 2nd Number
RET ;


; Calculating Fuction
Calculator:
MOV A,FLAG ; ACC = Flag
CJNE A,#1,dosub ; Check Flag
LCALL Addition ; Flag = 1 = Add
SJMP ret_calculator ; Return (& set values)
dosub:
CJNE A,#2,domul ; Check Flag
LCALL Subtraction ; Flag = 2 = Sub
SJMP ret_calculator ; Return (& set values)

domul:
CJNE A,#3,dodiv ; Check Flag
LCALL Multiply ; Flag = 3 = Mul
SJMP ret_calculator ; Return (& set values)

dodiv:
CJNE A,#4,ret_calculator ; Check Flag
LCALL Division ; Flag = 4 = Div

ret_calculator: ; Return (& set values)
MOV FLAG,#0
MOV M1,#0
MOV M2,#0
MOV NUM1,#0
MOV NUM2,#0
RET

Division:
MOV A,NUM1 ; ACC = 1st Number
ANL A,#0FH ; Mask 1st Digit
MOV R0,A ; Save ACC (2nd Digit)
MOV A,NUM1 ; ACC = 1st Number
ANL A,#0F0H ; Mask 2nd Digit
SWAP A ; Swap ACC Nibbles
MOV R1,A ; Save ACC (1st Digit)
MOV R2,#0 ; Clear R2 (High Bytes)
MOV R3,#0 ; Clear R3 (High Bytes)

MOV A,NUM2 ; ACC = 2nd Number
JNZ valid_division ; Check 2nd Number
MOV RESULTL,#0CBH ; (Division By Zero Error)
MOV RESULTH,#0ABH ; (Division By Zero Error)
MOV RESULTP,#0 ; (Division By Zero Error)
SJMP ret_division ; Return

valid_division:
ANL A,#0FH ; Mask 1st Digit
MOV R4,A ; Save ACC (2nd Digit)
MOV A,NUM2 ; ACC = 2nd Number
ANL A,#0F0H ; Mask 2nd Digit
SWAP A ; Swap ACC Nibbles
MOV R5,A ; Save ACC (1st Digit)
MOV R6,#0 ; Clear R6 (High Bytes)
MOV R7,#0 ; Clear R7 (High Bytes)
LCALL BCDDiv ; Integer Part of Division
MOV RESULTL,A ; Results Low Byte

; Remainder * 100
MOV R2,0H ; MOV R2,R0
MOV R3,1H ; MOV R3,R1
MOV R1,#0 ; Clear R1
MOV R0,#0 ; Clear R0

LCALL BCDDiv ; Floating Part of division
MOV RESULTP,A ; Results Floating Part
MOV RESULTH,#0 ; Results High Byte = 0

ret_division:
CLR PSW.1 ; Positive Number
RET ;

;(R3R2R1R0)/(R7R6R5R4)
; Remainder: R3R2R1R0
; Quotient: A
; with serial subtracting
BCDDiv:
MOV B,#0 ; Clear B
mainpart:
INC B ; Increment B
CLR C ; Clear Carry
MOV TEMP0,R0 ; Save R0
MOV TEMP1,R1 ; Save R1
MOV TEMP2,R2 ; Save R2
MOV TEMP3,R3 ; Save R3
MOV A,R0 ; ACC = 1st Number's 2nd Digit
SUBB A,R4 ; 1st Number's 2nd Digit - 2nd Number's 2nd Digit
JNC nocarry1 ; Check Carry (Borrow)
ADD A,#10 ; Result += 10
nocarry1:
MOV R0,A ; R0 = Result
MOV A,R1 ; ACC = 1st Number 1st Digit
SUBB A,R5 ; 1st Number's 1st Digit - 2nd Number's 1st Digit
JNC nocarry2 ; Check Carry (Borrow)
ADD A,#10 ; Result += 10
nocarry2:
MOV R1,A ; R1 = Result
MOV A,R2 ; ACC = R2
SUBB A,R6 ; R2 - R6
JNC nocarry3 ; Check Carry (Borrow)
ADD A,#10 ; Result += 10
nocarry3:
MOV R2,A ; R2 = Result
MOV A,R3 ; ACC = R3
SUBB A,R7 ; R3 - R7
MOV R3,A ; R3 = Result
JNC mainpart ; Check Last Carry (Borrow)

;Quotient
DEC B
MOV A,B
LCALL ConvertDEC2BCD ; ACC in BCD , B in DEC
;Remainder
MOV R0,TEMP0 ; R0 = R0 Before Calling this Function
MOV R1,TEMP1 ; R1 = R1 Before Calling this Function
MOV R2,TEMP2 ; R2 = R2 Before Calling this Function
MOV R3,TEMP3 ; R3 = R3 Before Calling this Function
RET

Subtraction:
CLR C ; Clear Carry
MOV A,NUM1 ; ACC = 1st Number
LCALL ConvertBCD2DEC ; Convert ACC to Decimal
MOV TEMP1,A ; Save ACC (Converted 1st Number)
MOV A,NUM2 ; ACC = 2nd Number
LCALL ConvertBCD2DEC ; Convert ACC to Decimal
MOV TEMP2,A ; Save ACC (Converted 2nd Number)
MOV A,TEMP1 ; ACC = 1st Number
SUBB A,TEMP2 ; 1st Number - 2nd Number
JNC subresult ; Check Carry (Borrow)
CPL A ; Converte to
ADD A,#1 ; 2's Complement
SETB PSW.1 ; Negative Number
subresult:
LCALL ConvertDEC2BCD ; Convert to BCD
MOV RESULTL,A ; Result Low Byte
MOV RESULTP,#0 ; Result Floting Point
MOV RESULTH,#0 ; Result High Byte
RET ;

; Convert to BCD
ConvertDEC2BCD:
MOV B,#10 ; Divider
DIV AB ; A = A / 10 , B = A % 10
SWAP A ; Swap Nibbeles
ORL A,B ; A[7..4] = A / 10 , A[3..0] = A%10
RET ;

; Convert to Decimal
ConvertBCD2DEC:
MOV TEMP0,A ; Save A
ANL A,#0F0H ; Mask ACC.3-ACC.0
SWAP A ; Swap Nibbles
MOV R1,A ; Save ACC (2nd Digit)
MOV A,TEMP0 ; Use Copy of ACC
ANL A,#0FH ; Mask ACC.7-ACC.4
MOV R0,A ; Save ACC (1st Digit)
MOV B,#10 ; Divider
MOV A,R1 ; ACC = R1 (2nd Digit)
MUL AB ; ACC = 2nd Digit / 10
ADD A,R0 ; ACC = 2nd Digit / 10 + 1st Digit
RET

Addition:
MOV A,NUM1 ; ACC = 1st Number
ADD A,NUM2 ; 1st Number + 2nd Number
DA A ; Decimal Adjust
JNC lowbyte ; Check Carry
MOV RESULTH,#1 ; Set Result High Byte
lowbyte:
MOV RESULTL,A ; Result Low Byte
CLR PSW.1 ; Positive Number
MOV RESULTP,#0H ; Result Floting Point
RET ;

Multiply:
MOV A,NUM1 ; ACC = 1st Number
ANL A,#0F0H ; Mask ACC.3-ACC.0
SWAP A ; Swap Nibbles
MOV R1,A ; R1 = 1st Number's 2nd Digit
MOV A,NUM1 ; ACC = 1st Number
ANL A,#0FH ; Mask ACC.7-ACC.4
MOV R0,A ; R0 = 2nd Number's 1st Digit
MOV A,NUM2 ; ACC = 2nd Number
ANL A,#0F0H ; Mask ACC.3-ACC.0
SWAP A ; Swap Nibbles
MOV R3,A ; R3 = 2nd Number's 2nd Digit
MOV A,NUM2 ; ACC = 2nd Number
ANL A,#0FH ; Mask ACC.7-ACC.4
MOV R2,A ; R2 = 2nd Number's 1st Digit

LCALL BCDMul ;

MOV RESULTL,R4 ; Result Low Byte
MOV A,R5 ; ACC = R5
SWAP A ; Swap Nibbles
ORL RESULTL,A ; Result Low Byte[7..4] = R5 , Result Low Byte[3..0] = R4
MOV RESULTH,R6 ; Result High Byte
MOV A,R7 ; ACC = R7
SWAP A ; Swap Nibbles
ORL RESULTH,A ; Result High Byte[7..4] = R5 , Result High Byte[3..0] = R4
CLR PSW.1 ; Positive Number
MOV RESULTP,#0 ; Result Floting Point
RET ;


;R7R6R5R4 = (R1R0)*(R3R2)
BCDMul:
;R4 = R0 * R2
MOV A,R0
MOV B,R2
MUL AB
MOV B,#10
DIV AB
MOV R4,B
MOV 60H,A ;C1

;R5 = R1*R + C1 + R3*R0
;Part 1
;R5 = R1*R2 + C1
MOV A,R1
MOV B,R2
MUL AB
ADD A,60H
MOV R5,A

;Part2
;R5 += R3*R0
MOV A,R3
MOV B,R0
MUL AB
ADD A,R5
MOV B,#10
DIV AB
MOV R5,B
MOV 60H,A ;C2

;R6 = R3*R1 + C2
;R7 = C3
MOV A,R3
MOV B,R1
MUL AB
ADD A,60H
MOV B,#10
DIV AB
MOV R7,A ;C3
MOV R6,B
RET

; Displaying Results on 7Segments
DisplayResult:
MOV R0,#RESULTP ; Pointer --> Result Floting Point
MOV R1,#3 ; Counter (number of 7Segments)
pushit:
MOV A,@R0 ; ACC = mem[R0]
ANL A,#0FH ; Mask ACC.7-ACC.4
PUSH ACC ; Push ACC
MOV A,@R0 ; ACC = Flo
ANL A,#0F0H ; Mask ACC.3-ACC.0
SWAP A ; Swap Nibbles
PUSH ACC ; Push ACC
INC R0 ; Increment Pointer
DJNZ R1,pushit ; Check Counter (Decrement Counter)

; Remove Start Zero
MOV R1,#0 ; Counter
; Searching Digits
searchbits:
MOV A,R1 ; ACC = R1 (Counter)
CJNE A,#4,compare0 ; Check Counter
DEC R1 ; Decrement Counter
SJMP no0found ;
compare0: ;
POP B ; POP B
MOV A,B ; ACC = B
JNZ no0found ; Check ACC
INC R1 ; Increment Counter
SJMP searchbits ; Searching Digits

no0found:
PUSH B ; PUSH B
CLR C ; Clear Carry
MOV A,#6 ; ACC = 6
SUBB A,R1 ; ACC = 6 - R1
MOV DIGITS,A ; Digit = ACC (Digit Number)
MOV A,RESULTP ; ACC = Result Floting Point
JNZ write_floating_result ; Check Result Floting Point
JB PSW.1,n_result ; Check Sign (1 = Negative)
write_normal_result: ;
MOV A,DIGITS ; ACC = Digit
SUBB A,#2 ; ACC = Digit - 2
MOV DIGITS,A ; Digit -= 2
MOV B,#11110111B ; 1st 7Seg

L1:
POP ACC ; POP ACC
XCH A,B ; A = B , B = A
RL A ; Rotate ACC Left
MOV P3,A ; Select 7Seg
XCH A,B ; A = B , B = A
LCALL BcdTo7Seg ; Converting BCD to 7Seg
MOV P1,A ; P1 = 7Seg Parts
LCALL ShortDelay ; Short Delay
DJNZ DIGITS,L1 ; Repeat Results Until first 7Seg

; Clear stack
POP ACC ; POP ACC
POP ACC ; POP ACC
RET

; Negative Result
n_result:
MOV A,DIGITS ; ACC = Digit Number
SUBB A,#2 ; ACC = Digit Number - 2
MOV DIGITS,A ; Digit Number -= 2
MOV P3,#11101111B ; Select first 7Seg
MOV P1,#40H ; Show '-' (7Seg's g)
LCALL ShortDelay ; Short Delay
MOV B,#11101111B ; select 7seg

L2:
POP ACC ; POP ACC
XCH A,B ; A = B , B = A
RL A ; Rotate ACC Left
MOV P3,A ; Select 7Seg
XCH A,B ; A = B , B = A
LCALL BcdTo7Seg ; Convert BCD to 7Seg
MOV P1,A ; P1 = 7Seg Parts
LCALL ShortDelay ; Short Delay
DJNZ DIGITS,L2 ; Repeat Results Until first 7Seg

;clear stack
POP ACC ; POP ACC
POP ACC ; POP ACC
RET

write_floating_result:
MOV A,DIGITS ; ACC = Digit Number
SUBB A,#2 ; ACC = Digit Number - 2
MOV R6,A ; Location of point
MOV R5,#0 ; Clear R5 (Counter)
MOV B,#11110111B ; 1st 7Seg

L3:
MOV R4,#0 ; Clear R4
INC R5 ; Increment R5
MOV A,R5 ; ACC = R5
CJNE A,06H,popit ; Check Counter
MOV R4,#10000000B ; Active Point on 7Seg
popit:
POP ACC ; POP ACC
XCH A,B ; A = B , B = A
RL A ; Rotate ACC Left
MOV P3,A ; Select 7Seg
XCH A,B ; A = B , B = A
LCALL BcdTo7Seg ; Converting BCD to 7Seg
ORL A,R4 ; Add Point (On or Off)
MOV P1,A ; 7Seg Parts
LCALL ShortDelay ; Short Delay
DJNZ DIGITS,L3 ; Repeat Results Until first 7Seg
RET


; Clean 7Segments
Clean7Seg:
MOV P3,#00001111B ; All 7Segments
MOV P1,#0 ; Turn off 7Seg
MOV RESULTH,#0 ; Result High Byte
MOV RESULTL,#0 ; Result Low Byte
MOV RESULTP,#0 ; Result Floting Point
RET


Keyboard:
MOV P2,#0F0H ; Set Rows to Zero & Columns as Input
LCALL ShortDelay ; Short Delay
MOV A,P2 ; Read Port
CJNE A,#0F0H,scanrows ; Check if any Key Pressed
MOV A,#0FFH ; Return Null
RET ;

scanrows:
MOV R0,#4 ; Counter for Scaning
MOV R1,#11101111B ; P2.4 is first Column (before first Rotate Bit 5 should Set to 0)
nextrow:
MOV A,R1 ; Rotating
RR A ; R1
MOV R1,A ;
MOV P2,A ; Send to Port
LCALL ShortDelay ; Short Delay
MOV A,P2 ; Read Port
ANL A,#0F0H ; Mask Columns
CJNE A,#0F0H,findcol ; Check if Pressed key is in this Row
DJNZ R0,nextrow ; Check Next Row (Decrease Counter)
MOV A,#0FFH ; Return Null
RET ;

findcol:
MOV R2,#0 ; Clear
nextcol:
CLR C ; Clear Carry
RLC A ; Rotate Left Through Carry
JNC calculate ; Check Carry (= ACC bit 7)
INC R2 ; Increase Counter
SJMP nextcol ; Check ACC Next Bit

calculate:
CLR C ; Clear Carry
MOV A,#4 ; Calculate
SUBB A,R0 ; Row
MOV B,#4 ; Set B for
MUL AB ; Calculating Key
ADD A,R2 ; Key = 4 * (Row) + (Column)
RET

ShortDelay:
MOV TEMP0,#20 ; Set 1st Counter
shortloop: ;
MOV TEMP1,#20 ; Set 2nd Counter
DJNZ TEMP1,$ ; Delay Loop
DJNZ TEMP0,shortloop ;
RET


; Returns Key Number using LookUp Table
GetKeyNum:
INC A ; Increment (Because of 'RET' Instruction)
MOVC A,@A+PC ; Load from LookUp Table
RET ;
; Table:
DB 7,8,9,0DH
DB 4,5,6,0CH
DB 1,2,3,0BH
DB 0EH,0,0FH,0AH


; Converting BCD to 7Segment , with LookUp Table
BcdTo7Seg:
INC A ; Increment (Because of 'RET' Instruction)
MOVC A,@A+PC ; Load from LookUp Table
RET ;
DB 3FH,06H,5BH,4FH,66H,6DH,7CH,07H,7FH,67H ; 0-9 on 7Seg
DB 01111001B,01110000B,01011100B ; Ero --> Error

END
 

Wow! Impressive!
Did you write this all by yourself or is it taken from somewhere?
 

Nikunj Tanna said:
Nice,

I mostly work with C rather than assembly. I rarely make codes in assembly. It's great.
Mostly I use mikroBASIC, with which I've written HUGE programs. Assembly just gets too tedious to code as you have to write too much. But for short programs, I use assembly a lot as it is the most efficient.
 

yes, I did it my self, it was my course(microprocessor) project! but it took alot of time though! )
 

hey kindly if possible, can u send me some shorter code for calc that excludes 7- segment display and easier to understand? i need it as soon as possible. Please mail me at leo1inmail@gmail.com. Thanx for the effort.
 

Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…