📄 calc.asm
字号:
call initialize ; initialise the Keybuffer and the LCD dislay.
mov oldopcode,#00
mov opcounter,#00 ; Start back at zero operations performed.
call bufferclear ; Clear the Keybuffer.
mov decimalcnt,#00h
jmp co_setflags
co_setflags: mov pctopflag,#00h ; Set/Clear the appropriate flags.
mov memopflag,#00h
mov equalsflag,#00h
mov arithopflag,#00h
co_done: call resetsign ; Reset the sign to it's default state ( positive )
mov status,#01h ; Status = 1 'cause it's an operator press.
pop DPL ; Restore the Datapointer.
pop DPH
ret
;---------------------------------------------------------------------------------
;EQUALOP - Subroutine to handle the equals operation.
;---------------------------------------------------------------------------------
equalop: push DPH ; Preserve the Datapointer.
push DPL
mov mode,#1 ; DPTR addresses the Keybuffer.
call getmode
mov R5,equalsflag ; Check for repeat Equals presses.
cjne R5,#1,eo_stattest
jmp eo_multiple ; If repeated goto multiple.
eo_multiple: call clearscreen ; Repeat Operations.
mov mode,#3 ; Use oldnumbuffer (holding last number)
call inputnum ; Input the last number.
mov mode,#1 ; Address the Keybuffer.
call getmode
call retrieveop ; Perform the operation and output.
mov R5,errorflag ; Test for errors.
cjne R5,#1,eo_input1
mov errorflag,#0 ; Error found - don't input the number. Clear errorflag ( of no further use ).
jmp eo_setflags
eo_input1: call inputnum ; No error so we can input the number safely.
jmp eo_setflags
eo_stattest: mov R5,status
cjne R5,#1,eo_single ; If status = 1 goto single else test the operator flags.
eo_pcttest: mov R5,pctopflag ; If percentage op then treat the same as multiple press.
cjne R5,#1,eo_memory
jmp eo_multiple
eo_memory: mov mode,#1 ; If memory press adjust the bufferctr accordingly.
mov R5,memcounter
mov bufferctr,R5 ; Run through to eo_single
eo_single: mov digitcode,#0 ; Single Equals.
call storedigit ; Terminate the ( second )number.
mov mode,#1
call inputnum ; Input the second (second )number.
mov copyfrom,#1
mov copyto,#3
call buffercopy ; Copy the (second) number.
call retrieveop ; Execute the operation and output the result.
mov R5,errorflag
cjne R5,#1,eo_input ; Test for errors.
mov errorflag,#0 ; Error found. Don't put result back on stack.
jmp eo_setflags ; Clear the errorflag - we don't need it anymore.
eo_input: call inputnum ; No error - put result back on stack and continue.
eo_setflags: mov equalsflag,#01h ; Set/Clear the appropriate flags.
mov memopflag,#00h
mov arithopflag,#00h
mov pctopflag,#00h
eo_done: call resetsign ; Reset the sign to it's default state ( positive ).
mov status,#01h ; Operator press so Status = 1.
pop DPL
pop DPH ; Reatore the Datapointer.
ret
;---------------------------------------------------------------------------------
;SIGNOP - Subroutine to change the sign of the number entered. This is a special case -
; We treat this as a digit press and not as an operator press. This is a bit of a
; fudge to ensure that we get the proper visual output on the LCD screen after the next
; keypress ( Screen is cleared on a *op* - *digit* sequence which we don't want here ).
;---------------------------------------------------------------------------------
signop: mov mode,#1 ; DPTR addresses the Keybuffer.
call getmode
mov R4,memopflag
cjne R4,#1,so_initialize ; Test for MRC press immediately prior to this.
mov R4,memcounter ; MRC pressed so adjust the bufferctr accordingly.
mov bufferctr,R4
so_initialize: mov R2,signflag ; R2 holds the signflag
mov R7,bufferctr ; Preserve the bufferctr in R7
so_toggle: cjne R2,#0,so_negative ; If R2 = 0 then positive else negative
mov R2,#1 ; If positve change to negative
jmp so_continue
so_negative: mov R2,#0 ; If negative change to positive
so_continue: cjne R2,#0,so_enterneg
mov digitcode,#020h ; If positive output a space.
mov bufferctr,#00h ; Output in buffer position 0.
call storedigit
jmp so_status
so_enterneg: mov digitcode,#02Dh ; If negative output a minus sign.
mov bufferctr,#00h ; Output in buffer position zero.
call storedigit
so_status: mov R4,status ; If the status is one we need to change it to zero
cjne R4,#1,so_complete ; for a correct visual display on the next keypress
mov status,#0 ; If status is zero we do not change anything.
so_complete: mov bufferctr,R7 ; Restore the bufferctr.
call bufferoutput ; Output the buffer to the LCD display.
mov signflag,R2 ; Set the signflag.
ret
;---------------------------------------------------------------------------------
;PERCENTOP - Subroutine to work out the percentage.Arithmetically (num1*num2/100) is good for
; +,- ,* but we use (num1*100)/num2 to set up the divide case. Ordering the inputs on the
; stack is important for the non - commutitive operators ( -,/).
;---------------------------------------------------------------------------------
percentop: mov R4,memopflag ; Test for *num1* - *op* - *mrc* - *pct*
cjne R4,#1,po_stattest
jmp po_continue
po_stattest: mov R4,status ; Test for *num1* - *op* - *num2* -*pct*
cjne R4,#1,po_continue
ret ; If *op* - *pct* do nothing.
po_continue: mov R5,oldopcode
cjne R5,#02Fh,po_standard ; Test for Divide Case.
mov mode,#4 ; Address the Hundred buffer
call inputnum ; Input 100.
call floating_mul ; Gives us (num1 * 100).
mov R5,memopflag
cjne R5,#1,po_divok
mov mode,#1
mov R5,memcounter ; Adjust the bufferctr for memory buffer contents.
mov bufferctr,R5
po_divok: mov digitcode,#0 ; Terminate the number.
call storedigit
mov mode,#1 ; Address the Keybuffer.
call inputnum ; Input the number.
call floating_div ; Divide.
call floating_point_output ; Output in Keybuffer.
call bufferoutput ; Output to LCD Display.
call inputnum ; Put result back on the stack.
jmp po_setflags ; End up with (num1*100) / num2.
po_standard: mov R5,memopflag
cjne R5,#1,po_stok
mov mode,#1
mov R4,memcounter ; Adjust the bufferctr as appropriate.
mov bufferctr,R4
mov digitcode,#0 ; Null terminate.
call storedigit
po_stok: mov mode,#1 ; We can do this for the other 3 cases.
call inputnum
call floating_mul
mov mode,#4
call inputnum
call floating_div ; We now have (num1*num2/100)
;Multiplication: We effectively have what we want from above. i.e (num1*num2/100 ).
mov R5,oldopcode
cjne R5,#02Ah,po_sub ; Test for Multiplication.
mov mode,#1 ; Address the Keybuffer.
call getmode
call floating_point_output ; Output to the Keybuffer.
call bufferoutput ; Output to the LCD display.
mov digitcode,#0
call storedigit ; Terminate.
call inputnum ; Put result back on the stack.
jmp po_setflags
; Subtraction: We need to rearrange the numbers on the stack into the proper order before executing.
po_sub: cjne R5,#02Dh,po_add ; Test for Subtraction.
mov mode,#1 ; Address the Keybuffer.
call getmode
call floating_point_output ; Output to the Keybuffer.
mov mode,#3 ; Address the oldnumbuffer.
call inputnum ; Input the number
mov mode,#1 ; Address the keybuffer.
call inputnum ; Input the number.
call retrieveop ; Execute the operation.
call inputnum ; Input the result.
jmp po_setflags
; Addition : Input the number from oldnumbuffer and execute.
po_add: cjne R5,#02Bh,po_done ; Test for Addition.
mov mode,#3 ; Address the oldnumbuffer.
call inputnum ; Input.
mov mode,#1 ; Address the Keybuffer.
call getmode
call retrieveop ; Execute the operation and output.
call inputnum ; Put the result back on the stack.
jmp po_setflags
po_setflags: mov memopflag,#00h ; Set/Clear the appropriate flags.
mov equalsflag,#00h
mov arithopflag,#00h
mov pctopflag,#01h
po_done: mov status,#01h ; Set status as it's an operator press.
mov mode,#1
call getmode ; Address the Keybuffer.
ret
;============================================
;************ MEMORY OPERATORS **************
;============================================
;------------------------------------------------------------------------------
;MEMRECALL - 1 press recalls the memory buffer - 2 consecutive presses clears
; the memory buffer.Memory Contents are stored in the MemoryBuffer.
;------------------------------------------------------------------------------
memrecall: mov R5,memocc ; Test for an empty buffer
cjne R5,#0,mr_validate ; If the memory buffer is empty and MRC is pressed
mov mode,#2 ; then initialise the buffer to zero and output to screen.
call getmode
call bufferclear
mov bufferctr,#00h
mov digitcode,#030h
call storedigit
call bufferoutput
jmp mr_setflags
mr_validate: mov R5,memopflag
cjne R5,#0,mr_consecutive ; test for two consecutive mrc presses.
mov mode,#2 ; Display the contents of the memorybuffer
call getmode
mov R4,memcounter ; Adjust the bufferctr.
mov bufferctr,R4
call bufferoutput ; Output to the LCD display.
mov mode ,#1 ; Address the Keybuffer.
call getmode ; Note that we do not input the number onto the stack here
call bufferclear ; but rather copy it into the Keybuffer. The Stack handling operations
mov copyfrom,#2 ; are handled inside the arithmetic op subroutine or the percent subroutine
mov copyto,#1 ; which are the only cases where we might need this number on the stack.
call buffercopy
mov memopflag,#1 ; Set the flag to indicate a MRC press.
jmp mr_setflags
mr_consecutive: mov mode,#2 ; Consecutive MRC presses so clear the memorybuffer.
call getmode
call bufferclear
mov status,#1
call cancelop
mov memopflag,#0 ; Nothing in Memorybuffer so reset.
mov memocc,#0
mr_setflags: mov equalsflag,#00h ; Clear opflags as appropriate.
mov arithopflag,#00h
mov pctopflag,#00h
mr_done: mov mode,#1 ; Address the Keybuffer
call getmode
mov bufferctr,#00h ; Clear the Bufferctr.
mov status,#1 ; Operator press so set Status = 1.
ret
;---------------------------------------------------------------------------------
;MEMPLUS - Subroutine to add the entered number to the value in the memory buffer.
;---------------------------------------------------------------------------------
memplus: mov mode,#2 ; Address the MemoryBuffer as we are as performing
call getmode ; addition on it's contents.
call inputnum ; Input the contents of the memorybuffer (num1)
call bufferclear
mov mode,#1 ; Input the number entered thru keypad (num2)
call inputnum
call bufferclear ; Clear the Keybuffer
call floating_add ; Perform num1+num2 and output to memorybuffer
mov mode,#2 ; Address Memorybuffer.
call getmode
call floating_point_output
mov R3,bufferctr
mov memcounter,R3 ; Take the length of the outputed number and put in memcounter.
mov memocc,#1 ; Indicate that a number is now in the memorybuffer.
mov mode ,#1 ; Copy the result back into the keybuffer and display.
call getmode
call bufferclear
mov copyfrom,#2
mov copyto,#1
call buffercopy
call bufferoutput
mp_setflags: mov memopflag,#00h ; Clear the appropriate flags.
mov equalsflag,#00h
mov arithopflag,#00h
mov pctopflag,#00h
mp_done: mov status,#1 ; Operator press so set Status = 1.
ret
;--------------------------------------------------------------------------------------
;MEMSUB - Subroutine to subtract the entered number from the value in the memorybuffer.
;---------------------------------------------------------------------------------------
memsub: mov mode,#2
call inputnum ;Input the contents of the memorybuffer (num1)
call bufferclear
mov mode,#1 ; Input the number entered thru keypad (num2)
call inputnum
call bufferclear
call floating_sub ; Perform num1 - num2
mov mode,#2
call getmode
call floating_point_output
mov R3,bufferctr
mov memcounter,R3
mov memocc,#1 ; Indicate that a number is now in the memorybuffer.
mov mode ,#1 ; Copy the result back into the keybuffer and display.
call getmode
mov copyfrom,#2
mov copyto,#1
call bufferclear
call buffercopy
call bufferoutput
ms_setflags: mov memopflag,#00h
mov equalsflag,#00h
mov arithopflag,#00h
mov pctopflag,#00h
ms_done: mov status,#1
ret
;======================================
;******* UTILITY FUNCTIONS ************
;======================================
;---------------------------------------------------------------------------------
;STOREDIGIT - Subroutine to store a digit. DPTR addresses the KEYBUFFER.
;---------------------------------------------------------------------------------
storedigit: call getmode
push DPH
push DPL
mov R5,bufferctr ; move the buffercounter into R5
mov R4,mode ; If we are going into the errorbuffer we allow 25 digits
cjne R4,#6,sd_entry ; This allows accurate comparison for bounds checking.
cjne R5,#24,sd_test0
jmp sd_continue
sd_test0: jc sd_continue
jmp sd_done
sd_entry: cjne R5,#8,sd_test ; test to be sure that a maximum of 8 digits go in the buffer (sign + 8)
jmp sd_decimal
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -