2
votes

I was asked to convert 8 bits binary to 3 digits of BCD.

I saw online people use DIV but I do not understand that way at all, why would I divide by #0AH?

If I was asked to subtract 16 bits by 16 bits using 2 pairs of 8 bit registers, do I need to transfer it to 2's comp using CPL and +1 or just use the SUBB command ?

R4-7 are the registers

        MOV A, R5
        SUBB A, R7
        JNC L1
        DEC R4
L1:     MOV 20H,A
        CLR C
        MOV A, R4
        SUBB A, R6
        MOV 21H,A
        END
1
0x0A is 10 so you divide by 10. The DIV will also return the remainder which is equal to the last decimal digit if you divide by 10. ex.: 123 % 10 = 3 which is the last digit.Eraklon
So if you would want to convert for example 83 (=b0101_0011) to BCD. Then you would essentially do this: (83 / 10) << 4 | (83 % 10) which is 8 << 4 | 3 which is 0b1000_0011 ->the BCD representation fo 83.Eraklon
As for the subtraction, the whole point of the SUBB is that you do not need to convert and you do not need to handle carry yourself. It's designed specifically for multi-byte subtraction.Jester

1 Answers

5
votes

Question 1: Why do I need to DIV by #0AH to get the BCD of a binary value?

More often than not each integer value in a computer (and a microcontroller is a computer) is stored as binary, these days. So there is nothing special to do here. If you want the BCD (binary coded decimal), you will need the hundreds, the tens, and the ones separated in 4 bits each. For this you will need to divide by 10 (and save the remainder), and this can be coded as #0AH. However, I would not write this, but write #10 that shows much clearer what is ment.

Let's assume that the number to convert is in the accumulator A, and you want the result in register pair R0 (MSByte) and R1 (LSByte). You need more than one register, because you get 3 digits that will be 12 bits wide in total.

DIV will divide A by B, and give the integer quotient in A and the remainder in B.

    MOV   B,#10
    DIV   AB      ; floor(number / 10) in A, 1s in B
    MOV   R1,B    ; 1s are now in R1 (bits 3 to 0)
    MOV   B,#10
    DIV   AB      ; floor(number / 100) in A, 10s in B
    MOV   R0,A    ; 100s are now in R0 (bits 3 to 0)
    MOV   A,B     ; 10s are now in ACC (bits 3 to 0)
    SWAP  A       ; 10s are now in bits 7 to 4 in ACC
    ORL   A,R1
    MOV   R1,A    ; 10s and 1s are now in R1

Question 2: Do I need to transfer [answerer: negate] the second operand by CPL and +1 or can I just use SUBB?

No, you just use SUBB. Before the first SUBB you will clear the carry flag.

Let's assume that the first operand (to subtract from, the "minuend") is in register pair R0 (MSByte) and R1 (LSByte), and the second operand (to subtract, the "subtrahend") is in register pair R2 (MSByte) and R3 (LSByte). The result (the "difference") should go in register pair R4 (MSByte) and R5 (LSByte).

    CLR   C
    MOV   A,R1
    SUBB  A,R3
    MOV   R5,A
    MOV   A,R0
    SUBB  A,R2    ; borrow bit from LSByte subtraction is taken into account
    MOV   R4,A

Final note: Please use a simulator to try the code, if you like to see details not described here.