; math16.asm #include #include code ;******************************************************************************* ; 16bit-Addition SUMMAND1_0:1 + SUMMAND2_0:1 = SUMME_0:1 ; wenn SUMMAND1 + SUMMAND2 >= 65536 -> STATUS,C = 1 addition_16_bit movf SUMMAND2_0,W movwf SUMME_0 movf SUMMAND2_1,W movwf SUMME_1 movf SUMMAND1_0,W addwf SUMME_0,F movf SUMMAND1_1,W btfsc STATUS,C ; überspringe, falls C nicht gesetzt incfsz SUMMAND1_1,W ; addiere C falls gesetzt, wenn Erg. addwf SUMME_1,F ; =0, dann überspr. add damit C erhalten bleibt return ;******************************************************************************* ; 16-Bit Subtraktion MINUEND_0:1 - SUBTRAHEND_0:1 = DIFFERENCE_0:1 ; C-Flag PIC-like, also wenn MINUEND < SUBTRAHEND ist, ist C-Flag NICHT gesetzt subtraction_16_bit movf MINUEND_0,W movwf DIFFERENCE_0 movf MINUEND_1,W movwf DIFFERENCE_1 movf SUBTRAHEND_0,W subwf DIFFERENCE_0,F movf SUBTRAHEND_1,W btfss STATUS,C ; überspringe, falls C gesetzt incfsz SUBTRAHEND_1,W ; addiere C falls nicht gesetzt, wenn Erg. subwf DIFFERENCE_1,F ; =0, dann überspr. add damit C erhalten bleibt return ;******************************************************************************* ; 8-Bit Multiplikation FACTOR1_0 * FACTOR2_0 = PRODUCT_0:1 ; C gesetzt, wenn obere 8 Bit des Produkts nicht 0 ; obere 8 Bit des Produkts in PRODUCT_1 multiplication_8_bit ;Prepare movlw 0x08 ; 8 Bit movwf BIT_COUNT clrf PRODUCT_0 clrf PRODUCT_1 clrf FACTOR1_1 mpl_8_loop ; neue Runde (oder 1. Runde) rrf FACTOR2_0,f ; unterstes Bit nach C btfss STATUS,C ; wenn C gesetzt, wird addiert goto mpl_8_factor2_0 ; sonst nicht ; addieren movf FACTOR1_0,w ; low byte addwf PRODUCT_0,f ; low byte add movf FACTOR1_1,w ; next byte btfsc STATUS,C ; überspringe falls C nicht gesetzt incfsz FACTOR1_1,w ; addiere C falls gesetzt addwf PRODUCT_1,f ; next byte add wenn Z nicht gesetzt mpl_8_factor2_0 bcf STATUS,C ; unterstes Bit mit 0 füllen rlf FACTOR1_0,f ; factor1 nach links schieben rlf FACTOR1_1,f decfsz BIT_COUNT,f ; nächste Stelle oder Ende goto mpl_8_loop ; eventuell C setzen movf PRODUCT_1,f ; Test des H-Teils auf 0 btfss STATUS,Z ; wenn 0, dann wird setzen von C übersp. bsf STATUS,C return ;******************************************************************************* ; 16-Bit Multiplikation FACTOR1_0:1 * FACTOR2_0:1 = PRODUCT_0:3 ; C gesetzt, wenn obere 16 Bit des Produkts nicht 0 ; obere 16 Bit des Produkts in PRODUCT_2:3 multiplication_16_bit ;Prepare movlw 0x10 ; 16 Bit movwf BIT_COUNT clrf PRODUCT_0 clrf PRODUCT_1 clrf PRODUCT_2 clrf PRODUCT_3 clrf FACTOR1_2 clrf FACTOR1_3 mpl_16_loop ; neue Runde (oder 1. Runde) rrf FACTOR2_1,f rrf FACTOR2_0,f ; unterstes Bit von FACTOR2 nach C btfss STATUS,C ; wenn C gesetzt, wird addiert goto mpl_16_factor2_0 ; sonst nicht ; verschobenen FACTOR1 zu PRODUCT addieren movf FACTOR1_0,w ; low byte addwf PRODUCT_0,f ; low byte add movf FACTOR1_1,w ; next byte btfsc STATUS,C ; überspringe falls C nicht gesetzt incfsz FACTOR1_1,w ; addiere C falls gesetzt addwf PRODUCT_1,f ; next byte add wenn Z nicht gesetzt movf FACTOR1_2,w ; next byte btfsc STATUS,C ; überspringe falls C nicht gesetzt incfsz FACTOR1_2,w ; addiere C falls gesetzt addwf PRODUCT_2,f ; next byte add wenn Z nicht gesetzt movf FACTOR1_3,w ; next byte btfsc STATUS,C ; überspringe falls C nicht gesetzt incfsz FACTOR1_3,w ; addiere C falls gesetzt addwf PRODUCT_3,f ; next byte add wenn Z nicht gesetzt mpl_16_factor2_0 bcf STATUS,C ; unterstes Bit mit 0 füllen rlf FACTOR1_0,f ; factor1 nach links schieben rlf FACTOR1_1,f rlf FACTOR1_2,f rlf FACTOR1_3,f decfsz BIT_COUNT,f ; nächste Stelle oder Ende goto mpl_16_loop bcf STATUS,C ; erst mal C löschen ; eventuell C setzen movf PRODUCT_2,f ; Test des unteren H-Teils auf 0 btfss STATUS,Z ; wenn 0, dann wird setzen von C übersp. bsf STATUS,C movf PRODUCT_3,f ; Test des oberen H-Teils auf 0 btfss STATUS,Z ; wenn 0, dann wird setzen von C übersp. bsf STATUS,C return ;******************************************************************************* ; 16-Bit Division, DIVIDEND_0:1 / DIVISOR_0:1 = QUOTIENT_0:1 ; DIVISOR_2:3 müssen definiert werden und werden genutzt ; aber müssen nicht auf 0 gesetzt werden, das macht die Routine selbst ; bei Division durch 0 ist STATUS.C gesetzt ; bei Quotient = 0 ist STATUS.Z gesetzt ; Rest in DIVIDEND_0/1 ; nicht direkt von außerhalb aufrufen wegen BSR division_16_bit ; Test auf Division durch 0 movf DIVISOR_0,F ; wenn 0, ist jetzt Z-Flag gesetzt bnz div_16_go ; wenn nicht 0 Division ausführen movf DIVISOR_1,F ; wenn 0, ist jetzt Z-Flag gesetzt bnz div_16_go ; wenn nicht 0 Division ausführen bsf STATUS,C goto div_16_end div_16_go ; prepare movlw 0x10 ; 16 Bit movwf BIT_COUNT movf DIVISOR_0,W ; divisor_0/1 nach divisor_2/3 movwf DIVISOR_2 movf DIVISOR_1,W movwf DIVISOR_3 clrf DIVISOR_0 ; divisor 0/1 löschen clrf DIVISOR_1 clrf QUOTIENT_0 ; quotient löschen clrf QUOTIENT_1 div_16_loop bcf STATUS,C ; oberstes Bit mit 0 füllen rrf DIVISOR_3,f ; Divisor 1 Bit nach rechts schieben rrf DIVISOR_2,f rrf DIVISOR_1,f rrf DIVISOR_0,f rlf QUOTIENT_0,f ; Quotient 1 Stelle nach links schieben rlf QUOTIENT_1,f rlf QUOTIENT_2,f rlf QUOTIENT_3,f ; Vergleich, ob Divisor größer ist movf DIVISOR_3,F ; nur Test auf 0 notwendig, oberer Teil des Dividend immer 0 btfss STATUS,Z ; überspringe, wenn oberer Teil des Divisor 0 war goto div_16_loop_end ; Divisor ist auf jeden Fall größer movf DIVISOR_2,F ; nur Test auf 0 notwendig, oberer Teil des Dividend immer 0 btfss STATUS,Z ; überspringe, wenn oberer Teil des Divisor 0 war goto div_16_loop_end ; Divisor ist auf jeden Fall größer movf DIVISOR_1,W subwf DIVIDEND_1,W btfss STATUS,C ; überspringe, wenn DIVISOR_1 nicht grö0er war goto div_16_loop_end ; DIVISOR_1 ist größer btfss STATUS,Z ; überspringe, wenn DIVISOR_1 gleich war goto div_16_loop_kl ; DIVISOR_1 ist kleiner movf DIVISOR_0,W subwf DIVIDEND_0,W btfss STATUS,C ; überspringe, wenn DIVISOR_0 nicht grö0er war goto div_16_loop_end ; Divisor ist größer div_16_loop_kl ; Quotient berechnen bsf QUOTIENT_0,0 ; in letzte Stelle des Quotient eine 1 schreiben ; neuen Dividend berechnen movf DIVISOR_0,W ; subtrahend_0 nach w subwf DIVIDEND_0,F ; subtrahend_0 von minuend_0 abziehen movf DIVISOR_1,W ; subtrahend_1 nach w btfss STATUS,C ; überspringe falls C gesetzt incfsz DIVISOR_1,W ; addiere 1, wenn Erg. 0, überspr. um C zu retten subwf DIVIDEND_1,F ; subtrahend_1 von minuend_1 abziehen div_16_loop_end ; nächste Schleife decfsz BIT_COUNT,F ; nächste Stelle oder Ende goto div_16_loop bcf STATUS,C div_16_end return ;******************************************************************************* global addition_16_bit global subtraction_16_bit global multiplication_8_bit global multiplication_16_bit global division_16_bit ;******************************************************************************* end