×
嵌入式 > 技术百科 > 详情

8位单片机加减乘法算法

发布时间:2020-05-27 发布时间:
|
;--------------------------------------------------------------------------------------

;Function:
;Description: Convert OP4 mantissa(BCD) to OP1 mantissa(Binary)
;Input: OP4 and R_Op1Count
;Output: OP1
;affect:OP2,R_RamTemp1
;--------------------------------------------------------------------------------------
F_Bcd2Binary:
 ;---------R_Op1Exp=R_Op4Exp---------
 lda R_Op4Exp   ;
 sta R_Op1Exp   ;
 jsr F_ClearOP1
 lda #0
 sta R_RamTemp1  ;loop counter
 clc
L_GetBinary:
 jsr F_ClearOp2 
 lda R_RamTemp1
 ror a
 tax
 lda R_Op4Number+1,x
 bcc L_GetLowNibble
;L_GetHighNibble:
 ror a
 ror a
 ror a
 ror a
L_GetLowNibble:
 and #0fh
 sta R_Op2Number+1   
 ldx R_RamTemp1  ;digit 0 pass directly
 beq L_EndOfMulTen  ;
L_MulTenLoop:
 jsr F_OP2MulTen  ;OP2=a*10^b
 dex    ;
 bne L_MulTenLoop  ;
L_EndOfMulTen:
 jsr F_OP1_ADD_OP2
 inc R_RamTemp1
 lda R_RamTemp1
 cmp R_Op1Count  ;R_Op1Count=total digits
 bcc L_GetBinary
;L_EndOfBcd2Binary:
 jsr F_NormalizeOP1  ;用于调整(去除)小数点后面(非零数字)的零

 rts

;--------------------------------------------------------------------------------------
;Function:
;Description: Convert OP1(Binary) to OP4(Binary)
;input:OP1
;output:OP4,R_Op1Count
;affect:OP2,R_RamTemp1
;--------------------------------------------------------------------------------------
F_Binary2Bcd:    ;;;;乘法出错时,需修改
     ;;;;R_OperTemp ;可暂存OP4高位
     ;;;;R_Op2Regter ;可暂存OP2高位
     ;;;;BcdCodeLength 改为16
 jsr F_ClearOp4_E
 jsr F_ClearOper  ;;zl
 lda #0
 sta R_RamTemp1  ;loop counter
L_AdjustBCD:
 jsr F_ClearOp2  ;clear OP2 first!
 ;;------------------------------;zl change
 lda R_Op1NumberTemp  ;
 cmp #2   ;
 bne L_Op1Div10  ;
 ;jsr F_ClearOp2Reg  ;;zl
 jsr F_OP1Div10Remainder2 ;Remainder=OP2,OP1=OP1/10
 jmp L_rere   ;
L_Op1Div10:    ;
 ;;------------------------------;
 jsr F_OP1Div10Remainder ;Remainder=OP2,OP1=OP1/10
L_rere:
 lda R_RamTemp1  ;
 clc
 ror a   ;
 tax    ;
 lda R_Op4Number+1,x  ;
 sta R_RamTemp2  ;
 lda R_Op2Number+1  ;
 bcc L_AddToBcdLowNibble ;
 rol a   ;
 rol a   ;
 rol a   ;
 rol a   ;
 and #0f0h   ;
 ora R_RamTemp2  ;
L_AddToBcdLowNibble:   ;
 sta R_Op4Number+1,x  ;
 inc R_RamTemp1  ;
 jsr F_CmpOP1Zero  ;
 bne L_AdjustBCD  ;
 ;--------adjust Exp part--------
 lda R_Op1Exp
 sta R_Op4Exp 
 ;-----adjust R_Op1Count------
 lda     #BcdCodeLength-1
        sta     R_Op1Count
        ;;------------------------------;zl change
 lda R_Op1NumberTemp  ;
 cmp #2   ;
 bne L_CheckOp1CountLoop ;     
 lda     #BcdCodeLength*2-1 ;
        sta     R_Op1Count  ;
        ;;------------------------------;
L_CheckOp1CountLoop:  
        lda     R_Op1Count
        clc
        ror     a
        tax    
        lda     R_Op4Number+1,x
      
        bcc     L_CheckLow
        and     #0f0h
        beq     L_AdjustOperandCount1
        jmp     L_CheckLTOne
L_CheckLow:
        and     #0fh
        beq     L_AdjustOperandCount1  
        jmp     L_CheckLTOne
L_AdjustOperandCount1:
        dec     R_Op1Count
        beq L_CheckLTOne    ;L_IncR_Op4Exp   ;now a=0
        jmp     L_CheckOp1CountLoop    
L_CheckLTOne:
        inc     R_Op1Count
        lda     R_Op4Exp
        and     #0fh
        cmp     R_Op1Count
        bcs     L_IncR_Op4Exp
        jmp     L_EndBinary2Bcd
L_IncR_Op4Exp:
        tax
        inx
        stx     R_Op1Count
L_EndBinary2Bcd:
 ;;------------------------------;zl change

 lda R_Op1NumberTemp  ;
 cmp #2   ;
 bne L_Binary2BcdEnd  ;
 jsr F_ErrorHighToLow ;;十六进制,不能直接将低位拿掉
 lda #0   ;
 sta R_Op1NumberTemp  ;
 ;;------------------------------;
L_Binary2BcdEnd:
 rts
;--------------------------------------------------------------------------------------
;Function:
;Description:Binary Add
;input:OP1,OP2
;output:OP1
;affect:OP3,R_RamTemp2
;--------------------------------------------------------------------------------------
F_FADD:
 sec
 lda R_Op2Exp
 and #0fh
 sta R_RamTemp2
 lda R_Op1Exp
 and #0fh
 sbc R_RamTemp2  ;R_Op1Exp-R_Op2Exp
 bne L_ExpNotEqual  ;R_Op1Exp=R_Op2Exp?
 ;----------R_Op1Exp=R_Op2Exp--------
 jsr F_CmpOP1OP2
 bcs L_ABS_OP1_GT_OP2 ;;相等
 ;------------OP2>OP1------------
 jsr F_OP1_To_OP3_E  ;exchange OP1 and OP2
 jsr F_OP2_To_OP1_E
 jsr F_OP3_To_OP2_E
 
 jmp L_ABS_OP1_GT_OP2  
L_ExpNotEqual:
 bcs L_ExpOP1GTOP2 ;1>2
L_ExpOP1LTOP2:   ;2>1
 sec
 lda R_Op1Exp
 and #0fh
 sta R_RamTemp2
 lda R_Op2Exp
 and #0fh
 sbc R_RamTemp2  ;abs(R_Op2Exp)-abs(R_Op1Exp)
 tax
L_AdjustOP1:
 jsr F_CmpOp1Exp7  ;;10000000
 bcs L_StopAdjustOP1
 jsr F_OP1MulTen
 inc R_Op1Exp
 dex
 bne L_AdjustOP1
 jsr F_CmpOP1OP2
 bcs L_ABS_OP1_GT_OP2
 ;------------OP2>OP1------------
 jsr F_OP1_To_OP3_E  ;exchange OP1 and OP2
 jsr F_OP2_To_OP1_E
 jsr F_OP3_To_OP2_E
 jmp L_ABS_OP1_GT_OP2
L_StopAdjustOP1:   ;imply OP1>OP2
 lda R_Op1Exp
 and #0fh 
 sta R_RamTemp2
 lda R_Op2Exp
 and #0fh 
 sbc R_RamTemp2  ;R_Op2Exp-R_Op1Exp
 tax
L_AdjustOP2_1:
 jsr F_OP2DivTen
 jsr F_OP3_To_OP2
 dex
 bne L_AdjustOP2_1
L_ABS_OP1_GT_OP2:
 lda R_Op1Exp
 eor R_Op2Exp
 and #0f0h 
 beq L_SignTheSame  ;Sign(OP1)=Sign(OP2)?
 jsr F_OP1_SBB_OP2  ;F_OP2_SBB_OP1
 jmp L_End_FADD
L_SignTheSame:
 jsr F_OP1_ADD_OP2
 jmp L_End_FADD
L_ExpOP1GTOP2:
 jsr F_OP1_To_OP3_E
 jsr F_OP2_To_OP1_E
 jsr F_OP3_To_OP2_E
 jmp L_ExpOP1LTOP2
L_End_FADD:   
 jsr F_CmpOp1Exp8   ;;当运算结果超过8位时,处理方法:
      ;;1.加法;再加1个寄存器,用于存放超走部分,然后每个寄存器的值移一位,第八位后加点
      ;;2.减法:不会出现错误情况,只会出现负数
      ;;3.乘法:再加四个寄存器,用于存放超走部分,最多超出7位,超出部分要加点
      ;;4.除法:此部分不会出现错误
 ;;bcs L_OverFlowTmp2
 ;;------------------------------
 bcc L_normal
 lda #1
 sta R_Op1NumberTemp
 lda R_KeyFlag
 ora #Error
 sta R_KeyFlag
 jsr F_NormalizeOP1
 rts
L_normal:
 ;;------------------------------
 lda #0
 sta R_Op1NumberTemp
 jsr F_NormalizeOP1
 rts
;--------------------------------------------------------------------------------------
;Function:
;input:OP1,OP2
;output:OP1
;affect:OP3,R_RamTemp2
;--------------------------------------------------------------------------------------
F_FSBB:
 lda R_Op2Exp
 eor #0f0h
 sta R_Op2Exp
 jsr F_FADD
 rts
L_OverFlowTmp2:
 jmp L_OverFlow
 
;--------------------------------------------------------------------------------------
;Function:
;Description:Binary Mul
; OP3=OP2,OP2=0
;
; OP2OP1=>C
    +)OP3
  --------------
;
;input:OP1,OP2
;output:OP1
;affect:OP3,OP4,R_RamTemp1
;--------------------------------------------------------------------------------------
F_FMUL:
 ldx #BcdCodeLength*8+1 ;#BcdCodeLength*4+1 zl change
 jsr R_Op2ToOp3  ;
 jsr F_ClearOp2  ;OP2OP1
L_FMUL_Loop:
 jsr F_Ror_Op2  ;
 ;jsr F_Ror_Op1_NC  ;
 ;;------------------------ ;;通过改变OP2的值来改变C的值,从而改变OP1的值
     ;;所以要再加四个寄存器来存高位部分
 ror R_Op1Number8  ;;;;;;;;;;;;;
 ror R_Op1Number7  ;;;;;;;;;;;;;
 ror R_Op1Number6  ;;;;;;;;;;;;;
 ror R_Op1Number5  ;;;;;;;;;;;;;
 
 ror R_Op1Number+4
 ror R_Op1Number+3
 ror R_Op1Number+2
 ror R_Op1Number+1
 
 bcc L_DoNothing  ;
 jsr F_OP2_ADD_OP3  ;
L_DoNothing:    ;
 dex    ;OP2OP1
 bne L_FMUL_Loop  ;OP3
 ;...............................;此部分是运算部分,可将寄存器加在此处 zl
 lda R_Op1Exp
 eor R_Op2Exp
 and #0f0h
 beq L_SameSign
 lda R_Op1Exp
 ora #0f0h
 sta R_Op1Exp
 jmp L_ADD_Exp
L_SameSign:
 lda R_Op1Exp
 and #0fh
 sta R_Op1Exp
L_ADD_Exp:
 clc
 lda R_Op2Exp 
 and #0fh  
 sta R_RamTemp1 
 lda R_Op1Exp 
 and #0fh  
 adc R_RamTemp1 
 sta R_RamTemp1  ;存放小数点的个数
 beq L_CheckOverFlow  ;;如果结果超过8位,要改变R_RamTemp1的值 zl
 ;-------R_RamTemp1>0---------
 jsr F_CmpOP2Zero
 bne L_NormalizeMUL
 jsr F_CmpOp1Exp8
 bcs L_NormalizeMUL  ;new
 lda R_RamTemp1  ;new
 cmp #8   ;new
 bcs L_NormalizeMUL  ;new
 jmp L_EndFMUL  ;new
 
L_NormalizeMUL:
 jsr F_OP2OP1DivTen
 dec R_RamTemp1
 beq L_CheckOverFlow
 lda R_RamTemp1
 cmp #8
 bcs L_NormalizeMUL
 jsr F_CmpOP2Zero
 bne L_NormalizeMUL
 jsr F_CmpOp1Exp8
 bcs L_NormalizeMUL
 
 jmp L_EndFMUL
L_CheckOverFlow:  
 jsr F_CmpOP2Zero 
 bne L_OverFlow222
 jsr F_CmpOp1Exp8
 ;;===================
 bcs L_OverFlow222
L_EndFMUL:
 lda R_Op1Exp
 and #0f0h
 ora R_RamTemp1
 sta R_Op1Exp
 jsr F_NormalizeOP1
 rts
L_OverFlow:
 lda R_KeyFlag
 ora #Error
 sta R_KeyFlag
 rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 999999999
L_OverFlow222:
 jsr L_OverFlow
 ;jsr F_ErrorHighToLow  ;;十六进制,不能直接将低位拿掉
 ;;------------------需修改
 lda R_Op1Exp
 and #0f0h
 ora R_RamTemp1
 sta R_Op1Exp
 lda #2
 sta R_Op1NumberTemp
 ;;------------------
 jsr F_NormalizeOP1
 rts
L_OverFlow3:
 jsr F_ClearOP1_E
 jmp L_OverFlow
;--------------------------------------------------------------------------------------
;Function:
;Description:Binary div
; Step1:
    <    -)OP2
   -----------
   OP3
;
; OP4=OP3
;
; Step2:
    <    -)OP2
   -----------
   OP3
; OP1=OP4,answer is OP1.OP3
;
;input: OP1,OP2
;output: OP1
;affect: OP3,OP4,R_RamTemp2
;--------------------------------------------------------------------------------------
F_FDIV:
 jsr F_CmpOP2Zero
 beq L_OverFlow3   ;;除以零时,显示错误加零 zl
 ;-------OP1.OP3=OP1/OP2---------
 jsr F_OP1_To_OP3   OP1OP3
 jsr F_ClearOP1  -OP2
 jsr F_DIV   ;
 jsr F_OP3_To_OP4  ;
 jsr F_ClearOP3  ;
 jsr F_DIV   ;answer is OP4.OP3
 jsr F_OP4_To_OP1  ;answer is OP1.OP3
 ;...............................
 sec
 lda R_Op2Exp   ;
 and #0fh   ;
 sta R_RamTemp2  ;
 lda R_Op1Exp   ;
 and #0fh   ;
 sbc R_RamTemp2  ;R_Op1Exp-R_Op2Exp
 sta R_RamTemp2
 bcs L_AdjustOP1OP3  ;R_Op1Exp>=R_Op2Exp
L_AdjExpToZero:
 jsr F_CmpOp1Exp7
 bcs L_OverFlow
 jsr F_Rol_OP3  
 jsr F_Rol_OP1_NC  ;
 jsr F_Op1ToOp2  ;
 jsr F_OP3_To_OP4
 jsr F_Rol_OP3  ;
 jsr F_Rol_OP1_NC  ;
 jsr F_Rol_OP3  ;
 jsr F_Rol_OP1_NC  ;
 jsr F_OP3_ADD_OP4
 jsr F_OP1_ADD_OP2_NC  ;
 
 inc R_RamTemp2    ;
 bne L_AdjExpToZero  ;
 ;tax
L_AdjustOP1OP3: 
 lda R_RamTemp2
 cmp #BcdCodeLength-1
 beq L_AnswerIsOP1
 
 jsr F_CmpOP3Zero
 beq L_AnswerIsOP1

 jsr F_CmpOp1Exp7
 bcs L_AnswerIsOP1
 
 jsr F_Rol_OP3  
 jsr F_Rol_OP1_NC  ;
 jsr F_Op1ToOp2  ;
 jsr F_OP3_To_OP4  ;
 jsr F_Rol_OP3  ;
 jsr F_Rol_OP1_NC  ;
 jsr F_Rol_OP3  ;
 jsr F_Rol_OP1_NC  ;
 jsr F_OP3_ADD_OP4  ;
 jsr F_OP1_ADD_OP2_NC ;OP1.OP3=OP1.OP3*10
 inc R_RamTemp2    ;
 jmp L_AdjustOP1OP3  ;
L_OverFlowTmp:    ;for F_FSQRT use
 jmp L_OverFlow
L_AnswerIsOP1:
 lda R_RamTemp2
 bmi L_OverFlowTmp
 lda R_Op1Exp
 eor R_Op2Exp
 and  #0f0h
 ora R_RamTemp2
 sta R_Op1Exp
 lda R_Op3Number+4
; cmp #98h
; bne L_FDIVEnd
; cmp #96h
; bne L_FDIVEnd
; cmp #7fh
; bne L_FDIVEnd
 cmp #ffh
 beq L_nextmingmei
 cmp #feh
 beq L_nextmingmei
 cmp #fch
 beq L_nextmingmei
 cmp #fbh
 beq L_nextmingmei
; lda R_Op3Number+4 ;+BcdCodeLength/2-1  ;check if OP3 is 999....
; cmp #fdh     ;999...
; bne L_FDIVEnd
L_nextmingmei:
 jsr F_ClearOp2
 jsr F_OP1_ADD_OP2_NC
L_FDIVEnd:
 ;--------adjust Exp part--------
 jsr F_NormalizeOP1
 rts

 

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
嵌入式设备网络安全的实际解决方案