Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

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.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top