## Binary to BCD

It is often necessary to need to use binary coded decimal in programs. But the questions is how can we take a binary number and covert in to BCD efficiently. Well, the three methods below show how to convert up to a 16 bit binary number into 4 bit binary coded decimal stored in 5 separate registers.

For example, consider the number B'00001010 11111111' (2815). After processing the original number, the BCD data will be held in the following resulting registers. Label address' have been assigned to the registers for understandability.

- TENS_THOUS - B'00000000' (0)
- THOUS - B'00000010' (2)
- HUNS - B'00001000' (8)
- TENS - B'00000001' (1)
- ONES - B'00000101' (5)

Each of the three methods have advantages and disadvantages. The most notable being execution cycles verse program memory. The double dabble method uses an almost fixed instruction cycle count with little variation but requires more than twice as much program memory. The decrement increment method has the advantage of low program memory space, but as the number to convert gets larger, the execution time sky-rockets. Before I explain each of the methods, here is a comparison table with respect to the program memory requirement verse the execution cycles. See below for an explanation of each method along with source code.

## 8 Bit Variation |
||||

Dummy Number DEC & BIN | Method | Program Memory | Execution Cycles | |
---|---|---|---|---|

1 (1 bit) | B'00000001' | Method 1 - Decrement & Increment | 16 | 17 |

Method 2 - Double Dabble (Using Indirect Addressing) | 34 | 304 | ||

Method 3 - Double Dabble (Without Indirect Addressing) | 38 | 192 | ||

15 (4 bit) | B'00001111' | Method 1 - Decrement & Increment | 16 | 104 |

Method 2 - Double Dabble (Using Indirect Addressing) | 34 | 304 | ||

Method 3 - Double Dabble (Without Indirect Addressing) | 38 | 193 | ||

63 (6 bit) | B'00111111' | Method 1 - Decrement & Increment | 16 | 407 |

Method 2 - Double Dabble (Using Indirect Addressing) | 34 | 304 | ||

Method 3 - Double Dabble (Without Indirect Addressing) | 38 | 194 | ||

255 (8 bit) | B'11111111' | Method 1 - Decrement & Increment | 16 | 1,622 |

Method 2 - Double Dabble (Using Indirect Addressing) | 34 | 304 | ||

Method 3 - Double Dabble (Without Indirect Addressing) | 38 | 196 | ||

## 16 Bit Variation |
||||

Dummy Number DEC & BIN | Method | Program Memory | Execution Cycles | |

1 (1 bit) | B'00000000 00000001' | Method 1 - Decrement & Increment | 27 | 24 |

Method 2 - Double Dabble (Using Indirect Addressing) | 44 | 909 | ||

Method 3 - Double Dabble (Without Indirect Addressing) | 59 | 609 | ||

15 (4 bit) | B'00000000 00001111' | Method 1 - Decrement & Increment | 27 | 111 |

Method 2 - Double Dabble (Using Indirect Addressing) | 44 | 909 | ||

Method 3 - Double Dabble (Without Indirect Addressing) | 59 | 610 | ||

63 (6 bit) | B'00000000 00111111' | Method 1 - Decrement & Increment | 27 | 414 |

Method 2 - Double Dabble (Using Indirect Addressing) | 44 | 909 | ||

Method 3 - Double Dabble (Without Indirect Addressing) | 59 | 611 | ||

255 (8 bit) | B'00000000 11111111' | Method 1 - Decrement & Increment | 27 | 1,629 |

Method 2 - Double Dabble (Using Indirect Addressing) | 44 | 909 | ||

Method 3 - Double Dabble (Without Indirect Addressing) | 59 | 613 | ||

1023 (10 bit) | B'00000011 11111111' | Method 1 - Decrement & Increment | 27 | 6,501 |

Method 2 - Double Dabble (Using Indirect Addressing) | 44 | 909 | ||

Method 3 - Double Dabble (Without Indirect Addressing) | 59 | 616 | ||

65535 (16 bit) | B'11111111 11111111' | Method 1 - Decrement & Increment | 27 | 415,575 |

Method 2 - Double Dabble (Using Indirect Addressing) | 44 | 909 | ||

Method 3 - Double Dabble (Without Indirect Addressing) | 59 | 626 |

## Method 1 - Decrement & Increment

### How It Works:

This method is one I came up with prior to learning about the Double Dabble algorithm. It is very basic in concept and works by decrementing the original number and incrementing a register called ONES. With every overflow from 9 to 10, the ONES register is reset and a register called TENS is incremented. You can start to understand the simplicity of this method and realise that it doesn't take much code alteration to adapt the routine to smaller or larger numbers.

Pro's

- Uses the most basic instructions and will work on any device
- Very low program memory used (see table above)

Con's

- Processing time varies significantly (see table above)
- Extensive processing time for large numbers (>8 bit) (see table above)

### Source Code: 8 Bit Variation

To use this code, add the General Purpose Register labels to the Constant Block. Copy from 'BIN_TO_BCD_8BIT' routine to the bottom and paste in your program. Don't forget to add a RETURN at the bottom if using as a sub-routine. Finally, load your binary number to be converted into BIN_TO_BCD_LO and call BIN_TO_BCD_8BIT.

CBLOCK H'20' COUNT1 BIN_TO_BCD_LO HUNS TENS ONES ENDC LOAD_DUMMY_NUMBER MOVLW B'11111111' MOVWF BIN_TO_BCD_LO BIN_TO_BCD_8BIT INCF BIN_TO_BCD_LO ; Pre-load low byte register + 1 CLRF HUNS ; HUNS = 0000 0000 MOVLW D'246' ; Move decimal '246' to W RESET_TENS MOVWF TENS ; TENS GPR = 1111 0101 RESET_ONES MOVWF ONES ; ONES GPR = 1111 0101 DEC_ORIGINAL DECFSZ BIN_TO_BCD_LO, F ; Decrement BIN_TO_BCD_LO register GOTO INC_RESULT ; Not 0, GOTO INC_RESULT GOTO ADJUST_RESULT ; Is 0, done, GOTO ADJUST_RESULT INC_RESULT INCFSZ ONES, F ; Increment ONES register, skip if 0 (overflow) GOTO DEC_ORIGINAL ; Not 0, repeat decrement of original number INCFSZ TENS, F ; Is 0, Increment TENS register skip if 0 GOTO RESET_ONES ; Not 0, repeat decrement of original number & reset the ONES register to D'246' INCF HUNS, F ; TENS overflowed, Increment HUNS skip if 0 GOTO RESET_TENS ; Not 0, repeat decrement of original number & reset the ONES and TENS registers to D'246' ADJUST_RESULT SUBWF TENS, F ; W still holds D'246 so subtract it from TENS register to determine how many 'TENS' (0-9) SUBWF ONES, F ; W still holds D'246 so subtract it from ONES register to determine how many 'ONES' (0-9)

### Source Code: 16 Bit Variation

CBLOCK H'20' COUNT1 BIN_TO_BCD_HI BIN_TO_BCD_LO TENS_THOUS THOUS HUNS TENS ONES ENDC LOAD_DUMMY_NUMBER MOVLW B'11111111' MOVWF BIN_TO_BCD_HI MOVLW B'11111111' MOVWF BIN_TO_BCD_LO BIN_TO_BCD_16BIT INCF BIN_TO_BCD_LO ; Pre-load low byte register + 1 INCF BIN_TO_BCD_HI ; Pre-load high byte register + 1 CLRF TENS_THOUS ; TENS_THOUS = 0000 0000 MOVLW D'246' ; Move decimal '246' to W RESET_THOUS MOVWF THOUS ; THOUS GPR = 1111 0101 RESET_HUNS MOVWF HUNS ; HUNS GPR = 1111 0101 RESET_TENS MOVWF TENS ; TENS GPR = 1111 0101 RESET_ONES MOVWF ONES ; ONES GPR = 1111 0101 DEC_ORIGINAL DECFSZ BIN_TO_BCD_LO, F ; Decrement BIN_TO_BCD_LO register GOTO INC_RESULT ; Not 0, GOTO INC_RESULT DECFSZ BIN_TO_BCD_HI, F ; Decrement BIN_TO_BCD_HI register GOTO INC_RESULT ; Not 0, skip next instruction GOTO ADJUST_RESULT ; Is 0, done, GOTO ADJUST_RESULT INC_RESULT INCFSZ ONES, F ; Increment ONES register, skip if 0 (overflow) GOTO DEC_ORIGINAL ; Not 0, repeat decrement of original number INCFSZ TENS, F ; Is 0, Increment TENS register skip if 0 GOTO RESET_ONES ; Not 0, repeat decrement of original number & reset the ONES register to D'246' INCFSZ HUNS, F ; TENS overflowed, Increment HUNS skip if 0 GOTO RESET_TENS ; Not 0, repeat decrement of original number & reset the ONES and TENS registers to D'246' INCFSZ THOUS, F ; HUNS overflowed, Increment THOUS GOTO RESET_HUNS ; Not 0, repeat decrement of original number & reset the ONES, TENS & HUNS registers to D'246' INCF TENS_THOUS, F ; THOUS overflowed, Increment TENS_THOUS GOTO RESET_THOUS ; Repeat decrement of original number & reset the ONES, TENS & HUNS & THOUS registers to D'246' ADJUST_RESULT SUBWF THOUS, F ; W still holds D'246 so subtract it from THOUS register to determine how many 'THOUS' (0-9) SUBWF HUNS, F ; W still holds D'246 so subtract it from HUNS register to determine how many 'HUNS' (0-9) SUBWF TENS, F ; W still holds D'246 so subtract it from TENS register to determine how many 'TENS' (0-9) SUBWF ONES, F ; W still holds D'246 so subtract it from ONES register to determine how many 'ONES' (0-9)

## Method 2 & 3 - Double Dabble

### How It Works:

This method is one I came across while searching the net for a better way to convert binary to BCD. I won't go into depth here because there are many pages that explain how it works but basically it uses a smart shift and add system. One place to check out how it works is wikipedia.

Method 2 & 3 are almost the same, the only difference being one uses indirect addressing and the other doesn't. Depending on which device you select for your project/system may determine which method you use. Although something to note, even though the non indirect addressing method uses slightly more program memory space it processes roughly 30% faster. See the pro's and con's for each method below.

### Method 2 - Double Dabble (Using Indirect Addressing)

Pro's

- Relatively low program memory used (see table above)
- Process time is constant no matter what the number (see table above)

Con's

- Can only be used on devices with indirect addressing
- Process's slower that the non indirect addressing method (see table above)

### Source Code: 8 Bit Variation

To use this code, add the General Purpose Register labels to the Constant Block. Copy from 'BINARY_TO_PACKED_BCD' routine to the bottom and paste in your program. Don't forget to add a RETURN at the bottom if using as a sub-routine. Finally, load your binary number to be converted into BIN_TO_BCD_LO and call BINARY_TO_PACKED_BCD.

CBLOCK H'20' COUNT1 BIN_TO_BCD_LO HUNS TENS ONES ENDC LOAD_DUMMY_NUMBER MOVLW B'11111111' MOVWF BIN_TO_BCD_LO BINARY_TO_PACKED_BCD ; 8 Bit Double Dabble Algorithm to obtain 3 x 4-bit BCD numbers, packed into 2 separate 8-bit registers (ONE & HUNS) CLRF ONES ; Clear packed BCD registers CLRF HUNS ; MOVLW D'8' ; Set countdown register (RLF must be repeated x times where x = binary number length, although binary number must be left justified in BIN_TO_BCD_LO if less than 8 bits) MOVWF COUNT1 ; Store in GPR labelled COUNT1 BIN2BCD_LOOP ; Loop rotate file registers and decrement count register BCF STATUS, C ; Clear carry flag for RLF RLF BIN_TO_BCD_LO, F ; Shift all registers 1 bit left using the carry bit of the status register to carry the MSB off the end of one register into the LSB of the next register RLF ONES, F ; RLF HUNS, F ; DECF COUNT1, F ; Decrement countdown register BTFSC STATUS, Z ; What that the last time OR is zero flag set? GOTO UNPACK_BCD ; Yes, move on to unpacking the result registers. No, skip this instruction and continue LOAD_FOR_BCD_TEST ; Test prospective BCD digits. If >=5, add 3 (as per double dabble algorithm) MOVLW ONES ; Move ONES register address to W MOVWF FSR ; Store ONES register address in File Select Register CALL ADJUST_BCD_DIGITS ; Call ADJUST_BCD_DIGITS to check if prospective BCD register is equal to or greater than 5 MOVLW HUNS ; Test and adjust second packed BCD byte MOVWF FSR ; CALL ADJUST_BCD_DIGITS ; GOTO BIN2BCD_LOOP ; Finish test and adjust, go back and continue rotating ADJUST_BCD_DIGITS MOVLW 0X03 ; (I refer to ONES in the description below but it is what ever is loaded into the FSR prior the calling sub routine) ADDWF INDF, W ; Add 3 with the contents of ONES register, store in W MOVWF TENS ; Store in TENS. TENS IS ONLY USED AS A TEMPORARY STORAGE REGISTER HERE AS IT IS NOT CURRENTLY BEING USED AND TO SAVE ON GPR USEAGE. SUBSTITE TENS WITH 'TEMP' TO SAVE CONFUSION BTFSC TENS, 3 ; Test TENS register to check if more than 7. If the ONES register had 5 or greater, the TENS register will have 8 or greater after the addition MOVWF INDF ; If ONES was equal to or greater than 5, adjust ONES by adding 3. W register still holds ONES + 3 so MOVe W to F MOVLW 0X30 ; Repeat for upper nibble of FSR in question ADDWF INDF, W ; MOVWF TENS ; BTFSC TENS, 7 ; MOVWF INDF ; RETURN ; UNPACK_BCD ; Unpack the 2 result registers into 3 separate registers each holding the 4 bit BCD number in the lower 4 bits and masking the upper 4 bits SWAPF ONES, W ; Swap nibbles of ONES register so that BCD for tens number is in the lower 4 bits, store in W register leaving original register unchanged ANDLW B'00001111' ; Mask upper nibble so all that is left is the tens BCD number in the lower 4 bits MOVWF TENS ; Store result in TENS MOVLW B'00001111' ; Mask upper nibbles of ONES it only contain BCD in lower 4 bits (no need to mask upper nibble of HUNS as the upper 4 bits are never altered) ANDWF ONES, F ;

### Source Code: 16 Bit Variation

CBLOCK H'20' COUNT1 BIN_TO_BCD_HI BIN_TO_BCD_LO TENS_THOUS THOUS HUNS TENS ONES ENDC LOAD_DUMMY_NUMBER MOVLW B'11111111' MOVWF BIN_TO_BCD_HI MOVLW B'11111111' MOVWF BIN_TO_BCD_LO BINARY_TO_PACKED_BCD ; 16 Bit Double Dabble Algorithm to obtain 5 x 4-bit BCD numbers, packed into 3 separate 8-bit registers CLRF ONES ; Clear packed BCD registers CLRF HUNS ; CLRF TENS_THOUS ; MOVLW D'16' ; Set countdown register (RLF must be repeated x times where x = binary number length, although binary number must be left justified in BIN_TO_BCD_LO:BIN_TO_BCD_HI if less than 16 bits) MOVWF COUNT1 ; Store in GPR labelled COUNT1 BIN2BCD_LOOP ; Loop rotate file registers and decrement count register BCF STATUS, C ; Clear carry flag for RLF RLF BIN_TO_BCD_LO, F ; Shift all registers 1 bit left using the carry bit of the status register to carry the MSB off the end of one register into the LSB of the next register RLF BIN_TO_BCD_HI, F ; RLF ONES, F ; RLF HUNS, F ; RLF TENS_THOUS, F ; DECF COUNT1, F ; Decrement countdown register BTFSC STATUS, Z ; What that the last time OR is zero flag set? GOTO UNPACK_BCD ; Yes, move on to unpacking the result registers. No, skip this instruction and continue LOAD_FOR_BCD_TEST ; Test prospective BCD digits. If >=5, add 3 (as per double dabble algorithm) MOVLW ONES ; Move ONES register address to W MOVWF FSR ; Store ONES register address in File Select Register CALL ADJUST_BCD_DIGITS ; Call ADJUST_BCD_DIGITS to check if prospective BCD register is equal to or greater than 5 MOVLW HUNS ; Test and adjust second packed BCD byte MOVWF FSR ; CALL ADJUST_BCD_DIGITS ; MOVLW TENS_THOUS ; Test and adjust third packed BCD byte MOVWF FSR ; CALL ADJUST_BCD_DIGITS ; GOTO BIN2BCD_LOOP ; Finish test and adjust, go back and continue rotating ADJUST_BCD_DIGITS MOVLW 0X03 ; (I refer to ONES in the description below but it is what ever is loaded into the FSR prior the calling sub routine) ADDWF INDF, W ; Add 3 with the contents of ONES register, store in W MOVWF TENS ; Store in TENS. TENS IS ONLY USED AS A TEMPORARY STORAGE REGISTER HERE AS IT IS NOT CURRENTLY BEING USED AND TO SAVE ON GPR USEAGE. SUBSTITE TENS WITH 'TEMP' TO SAVE CONFUSION BTFSC TENS, 3 ; Test TENS register to check if more than 7. If the ONES register had 5 or greater, the TENS register will have 8 or greater after the addition MOVWF INDF ; If ONES was equal to or greater than 5, adjust ONES by adding 3. W register still holds ONES + 3 so MOVe W to F MOVLW 0X30 ; Repeat for upper nibble of FSR in question ADDWF INDF, W ; MOVWF TENS ; BTFSC TENS, 7 ; MOVWF INDF ; RETURN ; UNPACK_BCD ; Unpack the 3 result registers into 5 separate registers each holding the 4 bit BCD number in the lower 4 bits and masking the upper 4 bits SWAPF ONES, W ; Swap nibbles of ONES register so that BCD for tens number is in the lower 4 bits, store in W register leaving original register unchanged ANDLW B'00001111' ; Mask upper nibble so all that is left is the tens BCD number in the lower 4 bits MOVWF TENS ; Store result in TENS SWAPF HUNS, W ; Repeat for HUNS register ANDLW B'00001111' ; MOVWF THOUS ; MOVLW B'00001111' ; Mask upper nibbles of ONES and HUNS so they only contain BCD in lower 4 bits ANDWF ONES, F ; ANDWF HUNS, F ;

### Method 3 - Double Dabble (No Indirect Addressing)

Pro's

- Fairly constant and low process time (see table above)
- Works on most devices

Con's

- Take up the most program memory space of the 3 methods (see table above)

### Source Code: 8 Bit Variation

To use this code, add the General Purpose Register labels to the Constant Block. Copy from 'BINARY_TO_PACKED_BCD' routine to the bottom and paste in your program. Don't forget to add a RETURN at the bottom if using as a sub-routine. Finally, load your binary number to be converted into BIN_TO_BCD_LO and call BINARY_TO_PACKED_BCD.

CBLOCK H'20' COUNT1 BIN_TO_BCD_LO HUNS TENS ONES ENDC LOAD_DUMMY_NUMBER MOVLW B'11111111' MOVWF BIN_TO_BCD_LO BINARY_TO_PACKED_BCD ; 8 Bit Double Dabble Algorithm to obtain 3 x 4-bit BCD numbers, packed into 2 separate 8-bit registers (ONE & HUNS) CLRF ONES ; Clear packed BCD registers CLRF HUNS ; MOVLW D'8' ; Set countdown register (RLF must be repeated x times where x = binary number length, although binary number must be left justified in BIN_TO_BCD_LO if less than 8 bits) MOVWF COUNT1 ; Store in GPR labelled COUNT1 BIN2BCD_LOOP ; Loop rotate file registers and decrement count register BCF STATUS, C ; Clear carry flag for RLF RLF BIN_TO_BCD_LO, F ; Shift all registers 1 bit left using the carry bit of the status register to carry the MSB off the end of one register into the LSB of the next register RLF ONES, F ; RLF HUNS, F ; DECF COUNT1, F ; Decrement countdown register BTFSC STATUS, Z ; What that the last time OR is zero flag set? GOTO UNPACK_BCD ; Yes, move on to unpacking the result registers. No, skip this instruction and continue ; Test prospective BCD digits. If >=5, add 3 (as per double dabble algorithm) TEST_DIGIT_0 ; (xxxxxxxx xxxx1111) MOVLW B'00001111' ; Move 00001111 to W register ANDWF ONES, W ; Use to mask upper nibble of ONES, store result in W register SUBLW 0X04 ; Subtract W from decimal 4 BTFSC STATUS, C ; Test carry bit of status register to check if W < 5 GOTO TEST_DIGIT_1 ; Digit 0 < 5, do not add 3 MOVLW 0X03 ; Digit 0 >=5, add 3 to digit 0 ADDWF ONES, F ; There is never a digit carry TEST_DIGIT_1 ; (xxxxxxxx 1111xxxx) MOVLW B'11110000' ; Check next digit using similar method above ANDWF ONES, W ; SUBLW 0X40 ; BTFSC STATUS, C ; GOTO TEST_DIGIT_2 ; MOVLW 0X30 ; ADDWF ONES, F ; TEST_DIGIT_2 ; (xxxx1111 xxxxxxxx) MOVLW B'00001111' ; Check next digit using similar method above ANDWF HUNS, W ; SUBLW 0X04 ; BTFSC STATUS, C ; GOTO BIN2BCD_LOOP ; MOVLW 0X03 ; ADDWF HUNS, F ; GOTO BIN2BCD_LOOP ; Digit 4 <5, finished checking and adjusting digits, loop again UNPACK_BCD ; Unpack the 2 result registers into 3 separate registers each holding the 4 bit BCD number in the lower 4 bits and masking the upper 4 bits SWAPF ONES, W ; Swap nibbles of ONES register so that BCD for tens number is in the lower 4 bits, store in W register leaving original register unchanged ANDLW B'00001111' ; Mask upper nibble so all that is left is the tens BCD number in the lower 4 bits MOVWF TENS ; Store result in TENS MOVLW B'00001111' ; Mask upper nibbles of ONES it only contain BCD in lower 4 bits (no need to mask upper nibble of HUNS as the upper 4 bits are never altered) ANDWF ONES, F ;

### Source Code: 16 Bit Variation

CBLOCK H'20' COUNT1 BIN_TO_BCD_HI BIN_TO_BCD_LO TENS_THOUS THOUS HUNS TENS ONES ENDC LOAD_DUMMY_NUMBER MOVLW B'11111111' MOVWF BIN_TO_BCD_HI MOVLW B'11111111' MOVWF BIN_TO_BCD_LO BINARY_TO_PACKED_BCD ; 16 Bit Double Dabble Algorithm to obtain 5 x 4-bit BCD numbers, packed into 3 separate 8-bit registers CLRF ONES ; Clear packed BCD registers CLRF HUNS ; CLRF TENS_THOUS ; MOVLW D'16' ; Set countdown register (RLF must be repeated x times where x = binary number length, although binary number must be left justified in BIN_TO_BCD_LO:BIN_TO_BCD_HI if less than 16 bits) MOVWF COUNT1 ; Store in GPR labelled COUNT1 BIN2BCD_LOOP ; Loop rotate file registers and decrement count register BCF STATUS, C ; Clear carry flag for RLF RLF BIN_TO_BCD_LO, F ; Shift all registers 1 bit left using the carry bit of the status register to carry the MSB off the end of one register into the LSB of the next register RLF BIN_TO_BCD_HI, F ; RLF ONES, F ; RLF HUNS, F ; RLF TENS_THOUS, F ; DECF COUNT1, F ; Decrement countdown register BTFSC STATUS, Z ; What that the last time OR is zero flag set? GOTO UNPACK_BCD ; Yes, move on to unpacking the result registers. No, skip this instruction and continue ; Test prospective BCD digits. If >=5, add 3 (as per double dabble algorithm) TEST_DIGIT_0 ; (xxxxxxxx xxxxxxxx xxxx1111) MOVLW B'00001111' ; Move 00001111 to W register ANDWF ONES, W ; Use to mask upper nibble of ONES, store result in W register SUBLW 0X04 ; Subtract W from decimal 4 BTFSC STATUS, C ; Test carry bit of status register to check if W < 5 GOTO TEST_DIGIT_1 ; Digit 0 < 5, do not add 3 MOVLW 0X03 ; Digit 0 >=5, add 3 to digit 0 ADDWF ONES, F ; There is never a digit carry TEST_DIGIT_1 ; (xxxxxxxx xxxxxxxx 1111xxxx) MOVLW B'11110000' ; Check next digit using similar method above ANDWF ONES, W ; SUBLW 0X40 ; BTFSC STATUS, C ; GOTO TEST_DIGIT_2 ; MOVLW 0X30 ; ADDWF ONES, F ; TEST_DIGIT_2 ; (xxxxxxxx xxxx1111 xxxxxxxx) MOVLW B'00001111' ; Check next digit using similar method above ANDWF HUNS, W ; SUBLW 0X04 ; BTFSC STATUS, C ; GOTO TEST_DIGIT_3 ; MOVLW 0X03 ; ADDWF HUNS, F ; TEST_DIGIT_3 ; (xxxxxxxx 1111xxxx xxxxxxxx) MOVLW B'11110000' ; Check next digit using similar method above ANDWF HUNS, W ; SUBLW 0X40 ; BTFSC STATUS, C ; GOTO TEST_DIGIT_4 ; MOVLW 0X30 ; ADDWF HUNS, F ; TEST_DIGIT_4 ; (xxxx1111 xxxxxxxx xxxxxxxx) MOVLW B'00001111' ; Check next digit using similar method above ANDWF TENS_THOUS, W ; SUBLW 0X40 ; BTFSC STATUS, C ; GOTO BIN2BCD_LOOP ; MOVLW 0X03 ; ADDWF TENS_THOUS, F ; GOTO BIN2BCD_LOOP ; Digit 4 <5, finished checking and adjusting digits, loop again UNPACK_BCD ; Unpack the 3 result registers into 5 separate registers each holding the 4 bit BCD number in the lower 4 bits and masking the upper 4 bits SWAPF ONES, W ; Swap nibbles of ONES register so that BCD for tens number is in the lower 4 bits, store in W register leaving original register unchanged ANDLW B'00001111' ; Mask upper nibble so all that is left is the tens BCD number in the lower 4 bits MOVWF TENS ; Store result in TENS SWAPF HUNS, W ; Repeat for HUNS register ANDLW B'00001111' ; MOVWF THOUS ; MOVLW B'00001111' ; Mask upper nibbles of ONES and HUNS so they only contain BCD in lower 4 bits ANDWF ONES, F ; ANDWF HUNS, F ;