8051 Arithmetic Operations Subtraction, Multiplication, Division, Decimal Arithmetic ,Example Programs, AND Summary

 

Subtraction

Subtraction can be done by taking the 2's complement of the number to be subtracted, the subtrahend, and adding it to another number, the minuend. The 8051, however, has com­mands to perform direct subtraction of two signed or unsigned numbers. Register A is the destination address for subtraction. All four addressing modes may be used for source addresses. The commands treat the carry flag as a borrow and always subtract the carry flag as part of the operation.

The following table lists the subtract mnemonics.

Mnemonic

Operation

 SUBB A,#n

Subtract immediate number n and the C flag from A; put the result in A

SUBB A,add

Subtract the contents of add and the C flag from A; put the result in A

 SUBB A,Rr

 Subtract Rr and the C flag from A; put the result in A

SUBB A,@Rp

Subtract the contents of the address in Rp and the C flag from A; put the result in A

Note that the C flag is set if a borrow is needed into bit 7 and reset otherwise. The AC flag is set if a borrow is needed into bit 3 and reset otherwise. The OV flag is set if there is a borrow into bit 7 and not bit 6 or if there is a borrow into bit 6 and not bit 7. As in the case for addition, the OV Flag is the XOR of the borrows into bit positions 7 and 6.

Unsigned and Signed Subtraction

Again, depending on what is needed, the programmer may choose to use bytes as signed or unsigned numbers. The carry flag is now thought of as a borrow flag to account for situations when a larger number is subtracted from a smaller number. The OV flag indi­cates results that must be adjusted whenever two numbers of unlike signs are subtracted and the result exceeds the planned signed magnitudes.

Unsigned Subtraction

Because the C flag is always subtracted from A along with the source byte, it must be set to 0 if the programmer does not want the flag included in the subtraction. If a multi-byte subtraction is done, the C flag is cleared for the first byte and then included in subsequent higher byte operations.

The result will be in true form, with no borrow if the source number is smaller than A, or in 2's complement form, with a borrow if the source is larger than A. These are not signed numbers, as all eight bits are used for the magnitude. The range of numbers is from positive 255d (C = 0, A= FFh) to negative 255d (C = I, A= 0th).

The following example demonstrates subtraction of larger number from a smaller number:

015d = 0000111 lb

SUBB  100d = 01 01100100b

-085d  1 10101011b= 171d

The C flag is set to I, and the OV flag is set to 0. The 2's complement of the result is 085d.

The reverse of the example yields the following result:

100d = 01100100b

015d = 00001111b

085d 01010101b = 085d

The C flag is set to 0, and the OV flag is set to 0. The magnitude of the result is in true form.

Signed Subtraction

As is the case for addition, two combinations of unsigned numbers are possible when sub­tracting: subtracting numbers of like and unlike signs. When numbers of like sign are subtracted, it is impossible for the result to exceed the positive or negative magnitude limits of +I 27d or - I 28d, so the magnitude and sign of the result do not need to be adjusted, as shown in the following example:

+ 100d = 01100100b    (Carry flag = 0 before SUBB)

SUBB +126d = 0111110b

-026d    11100110b = -026d

 

There is a borrow into bit positions 7 and 6; the carry flag is set to I, and the OV flag is cleared.


The following example demonstrates using two negative numbers:

-061d = 1100001 lb  (Carry flag = 0 before SUBB)

SUBB -116d = 11000011b

+055d 00110111b = +55d

There are no borrows into bit positions 6 or 7, so the OY and carry flags are cleared to zero.

An overflow is possible when subtracting numbers of opposite sign because the situa­tion becomes one of adding numbers of like signs, as can be demonstrated in the following example:

-099d = 10011101b   (Carry flag = 0 before SUBB)

SUBB + 100d = 01 01100100b

-199d 00111001b = +057d

Here, there is a borrow into bit position 6 but not into bit position 7; the OV flag is set to I, and the carry flag is cleared to 0. Because the OV flag is set to I, the result must be adjusted. In this case, the magnitude can be interpreted as the 2's complement of 7 ld, the remainder after a carry out of l 28d from I 99d. The magnitude is correct, and the sign needs to be corrected to a 1 .

The following example shows a positive overflow:

+087d = 0101011 lb   (Carry flag = 0 before SUBB)

SUBB -052d = 11001100b

+139d    1000101 lb = -I 17d

There is a borrow from bit position 7, and no borrow from bit position 6; the OV flag and the carry flag are both set to I. Again the answer must be adjusted because the OV flag is set to one. The magnitude can be interpreted as a +01 Id, the remainder from a carry out of I 28d. The sign must be changed to a binary 0 and the OV condition dealt with.

The general rule is that if the OV flag is set to I, then complement the sign bit. The OV flag also signals that the result is greater than - I 28d or +I 27d.

Again, it must be emphasized: When an overflow occurs in a program, an error has been made in the estimation of the largest number needed to successfully operate the pro­gram. Theoretically, the program could resize every number used, but this extreme proce­dure would tend to hinder the performance of the microcontroller.

Note that for all the examples in this section, it is assumed that the carry flag = 0 before the SUBB. The carry flag must be 0 before any SUBB operation that depends upon C = 0 is done.

The following table lists examples of SUBB multiple-byte signed arithmetic operations:

Mnemonic

Operation

MOV 0D0h,#00h

 Carry flag= 0

MOV A,#3Ah

A= 3Ah

MOV 45h,#13h

Address  45h = 13h

 SUBB A,45h

A = 27h; C = 0, OV = 0

SUBB A,45h

 A = 14h; C = 0, OV = 0

 SUBB A,#80h

 A = 94h; C = 1 , OV = 1

 SUBB A,#22h

 A= 71h; C = 0, OV = 0

 SUBB A,#0FFh

 A = 72h; C = 1 , OV = 0

CAUTION

Remember to set the carry flag to zero if it is not to be included as part of the subtraction operation.

 Multiplication and Division

The 8051 has the capability to perform 8-bit integer multiplication and division using the A and B registers. Register B is used solely for these operations and has no other use except as a location in the SFR space of RAM that could be used to hold data. The A register holds one byte of data before a multiply or divide operation, and one of the result bytes after a multiply or divide operation.

Multiplication and division treat the numbers in registers A and B as unsigned. The programmer must devise ways to handle signed numbers.

Multiplication

Multiplication operations use registers A and B as both source and destination addresses for the operation. The unsigned number in register A is multiplied by the unsigned number in register B, as indicated in the following table:

Mnemonic

Operation

MULAB

Multiply A by B: put the low-order byte of the product in A, put the high-order byte in B

The OV flag will be set if Ax B > FFh. Setting the OV flag does not mean that an error has occurred. Rather, it signals that the number is larger than eight bits, and the program­mer needs to inspect register B for the high-order byte of the multiplication operation. The carry flag is always cleared to 0.

The largest possible product is FEO I h when both A and B contain FFh. Register A contains 0lh and register B contains FEh after multiplication of FFh by FFh. The OV flag is set to 1 to signal that register B contains the high-order byte of the product; the carry flag is 0.

The following table gives examples of MUL multiple-byte arithmetic operations:

Mnemonic

Operation

MOV A,#7Bh

A= 7Bh

 MOV OFOh.#02h

 B = 02h

MULAB

A = 00h and  B = F6h: OV Flag = 0

MOV A,#0FEh

A = FEh

 MULAB

A = 14h and B = F4h: OV Flag =1

CAUTION

Note there is no comma between A and 8 in the MUL mnemonic.

Division

Division operations use registers A and B as both source and destination addresses for the operation. The unsigned number in register A is divided by the unsigned number in regis­ter B, as indicated in the following table:


Mnemonic

Operation

DIV AB

Divide A by B; put the integer part of quotient in register A and the integer part of the remainder in B

The OV flag is cleared to 0 unless B holds 00h before the DIV. Then the 0V flag is set to I to show division by 0. The contents of A and B, when division by 0 is attempted, are undefined. The carry flag is always reset.

Division always results in integer quotients and remainders, as shown in the following example: clip_image002[4]

When done in hex:

clip_image004[3]

The following table lists examples of DIV multiple-byte arithmetic operations:

Mnemonic

Operation

MOV A,#0FFh

A = FFh (255d)

MOV 0F0h,#2Ch

B = 2C (44d)

DIV AB

A = 05h and B = 23h [255d = (5 x 44) + 35]

DIV AB

A = 00h and B = 05h (05d = (0 x 35) + 5]

DIV AB

A = 00h and B = 00h [00d = (0 x 5) + 0J

DIV AB

A = ?? and B = ??; OV flag is set to one

CAUTION

The original contents of B (the divisor) are lost.

Note there is no comma between A and B in the DIV mnemonic.

Decimal Arithmetic

Most 8051 applications involve adding intelligence to machines where the hexadecimal numbering system works naturally. There are instances, however, when the application involves interacting with humans, who insist on using the decimal number system. In such cases, it may be more convenient for the programmer to use the decimal number system to represent all numbers in the program.

Four bits are required to represent the decimal numbers from 0 to 9 (0000 to 1001) and the numbers are often called Binary coded decimal (BCD) numbers. Two of these BCD numbers can then be packed into a single byte of data.

The 8051 does all arithmetic operations in pure binary. When BCD numbers are being used the result will often be a non-BCD number, as shown in the following example:

clip_image006[3]

Note that to adjust the answer, an 06d needs to be added to the result.


The opcode that adjusts the result of BCD addition is the decimal adjust A for addi­tion (DA A) command, as shown in the following table:

Mnemonic

Operation

DA A

Adjust the sum of two packed BCD numbers found in A register; leave the adjusted number in A.

The C flag is set to I if the adjusted number exceeds 99BCD and set to 0 otherwise. The DA A instruction makes use of the AC flag and the binary sums of the individual binary nibbles to adjust the answer to BCD. The AC flag has no other use to the programmer and no instructions-other than a MOV or a direct bit operation to the PSW-affect the AC flag.

It is important to remember that the DA A instruction assumes the added numbers were in BCD before the addition was done. Adding hexadecimal numbers and then using DA A will not convert the sum to BCD.

The DA A opcode only works when used with ADD or ADDC opcodes and does not give correct adjustments for SUBB, MUL or DIV operations. The programmer might best consider the ADD or ADDC and DA A as a single instruction and use the pair automat­ically when doing BCD addition in the 8051.

The following table gives examples of BCD multiple-byte arithmetic operations:

Mnemonic

Operation

MOV A,#42h

A= 42BCD

 ADD A,#13h

 A= 55h; C = 0

 DA A

A= 55h; C = 0

ADD A,#17h

 A= 6Ch; C = 0

 DA A

A = 72BCD; C = 0

ADDC A,#34h

A= A6h; C = 0

DA A

A = 06BCD; C =1

ADDC A,#1 lh

A = l SBCD; C = 0

DA A

 A = !&BCD; C = 0

CAUTION

All numbers used must be in BCD form before addition. Only ADD and ADDC are adjusted to BCD by DA A.

Example Programs

The challenge of the programs presented in this section is writing them using only opcodes that have been covered to this point in the book. Experienced programmers may long for some of the opcodes to be covered in Chapter 6, but as we shall see, programs can be written without them.

EXAMPLE PROBLEM 5.1

Add the unsigned numbers found in internal RAM locations 25h, 26h, and 27h together and put the result in RAM locations 30h (MSB) and 3lh (LSB).

• Thoughts on the Problem The largest number possible is FFh + FFh = 01 FEh + FFh = 02FDh, so that two bytes will hold the largest possible number. The MSB will be set to 0 and any carry bit added to it for each byte addition.


To solve this problem, use an ADD instruction for each addition and an ADDC to the MSB for each carry which might be generated. The first ADD will adjust any carry flag which exists before the program starts.

The complete program is shown in the following table:

Mnemonic

Operation

 MOV 3Jh,#00h

Clear the MSB of the result to 0

MOV A,25h

Get the first byte to be added from location 25h

ADD A,26h

Add the second byte found in RAM location 26h

MOV R0,A

 Save the sum of the first two bytes in RO

MOV A,#00h

Clear A to 00

ADDC A,3lh

Add the carry to the MSB; carry = 0 after this operation

MOV 3lh,A

Store MSB

MOV A,R0

Get partial sum back

ADD A,27h

 Form final LSB sum

 MOV 39h,A

Store LSB

MOV A,#00h

Clear A for MSB addition

ADDC A,31h

 Form final MSB

 MOV 3lh,A

Store final MSB

COMMENT

Notice how awkward it becomes to have to use the A register for all operations. Jump instruc­tions, which will be covered in Chapter 6, require less use of A.

EXAMPLE PROBLEM 5.2

Repeat problem 5.1 using BCD numbers.

• Thoughts on the Problem The numbers in the RAM locations must be in BCD before the problem begins. The largest number possible is 99d + 99d = I 98d + 99d = 297d, so that up to two carries can be added to the MSB.

The solution to this problem is identical to that for unsigned numbers, except a DA A must be added after each ADD instruction. If more bytes were added so that the MSB could exceed 09d, then a DA A would also be necessary after the ADDC opcodes.

The complete program is shown in the following table:

Mnemonic

Operation

MOV 3lh,#00h

Clear the MSB of the result to 0

 MOV A,25h

Get the first byte to be added from location 25h

ADD A,26h

Add the second byte found in RAM location 26h

 DAA

Adjust the answer to BCD form

MOV RO,A

Save the sum of the first two bytes in RO

MOV A,#OOh

 Clear A to 00

ADDC A,3lh

Add the carry to the MSB; carry = 0 after this operation

MOV 31h,A

Store MSB

MOV A,RO

Get partial sum back

 ADD A,27h

Form final LSB sum

DAA

Adjust the final sum to BCD

MOV 30h,A

Store LSB

MOV A,#Ooh

Clear A for MSB addition

 ADDC A,3lh

Form final MSB

 MOV 31h,A

Store final MSB

COMMENT

When using BCD numbers, DA A can best be thought of as an integral part of the ADD instructions.

EXAMPLE PROBLEM 5.3

Multiply the unsigned number in register R3 by the unsigned number on port 2 and put the result in external RAM locations 10h (MSB) and 11 h (LSB).

• Thoughts on the Problem The MUL instruction uses the A and B registers; the prob­lem consists of MOV es to A and B followed by MOVes to the external RAM. The com­plete program is shown in the following table:

Mnemonic

Operation

MOV A,0A0h

Move the port 2 pin data to A

MOV 0F0h,R3

Move the data in R3 to the B register

 MULAB

Multiply the data; A has the low order result byte

MOV R0.#1 lh

 Set RO to point to external RAM location l lh

MOV@R0,A

Store the LSB in external RAM

DEC R0

Decrement R0 to point to !0h

MOV A,0F0h

Move B to A

MOV@R0,A

Store the MSB in external RAM

coMMENT

Again we see the bottleneck created by having to use the A register for all external data transfers.

More advanced programs which do signed math operations and multi-byte multiplication and division will have to wait for the development of Jump instructions in Chapter 6.

Summary OF 8051 Arithmetic Operations

The 8051 can perform all four arithmetic operations: addition, subtraction. multiplication, and division. Signed and unsigned numbers may be used in addition and subtraction; an 0Y flag is provided to signal programmer errors in estimating signed number magnitudes needed and to adjust signed number results. Multiplication and division use unsigned numbers. BCD arithmetic may be done using the DA A and ADD or ADDC instructions.

The following table lists the arithmetic mnemonics:

Mnemonic

Operation

 ADD A. source

Add the source byte to A; put the result in A and adjust the C and OY flags

ADDC A, source

Add the source byte and the carry to A; put the result in A and adjust the C and OV flags

DA A

Adjust the binary result of adding two BCD numbers in the A register to BCD and adjust the carry flag

DEC source

Subtract a I from the source; roll from 00h to FFh

DIV AB

Divide the byte in A by the byte in B; put the quotient in A and the remainder in B; set the OV flag to I if B = 00h before the division

INC source

Add a 1 to the source; roll from FFh or FFFFh to 00h or 0000h

 MULAB

Multiply the bytes in A and B; put the high-order byte of the result in B, the low-order byte in A; set the OV flag to 1 if the result is > FFh

SUBB A. source

Subtract the source byte and the carry from A; put the result in A and adjust the C and OV flags


Problems

Write programs that perform the tasks listed using only opcodes that have been discussed in this and previous chapters. Use comments on each line of code and try to use as few lines as possible. All numbers may be considered to be unsigned numbers.

l. Add the bytes in RAM locations 34h and 35h: put the result in register R5 (LSB) and R6 (MSB).

2- Add the bytes in registers R3 and R4; put the result in RAM location 4Ah (LSB) and 4Bh (MSB).

3. Add the number 84h to RAM locations l 7h and 18h.

4. Add the byte in external RAM location 02CDh to internal RAM location l9h; put the result into external RAM location 0000h (LSB) and 00C1h (MSB).

5-8. Repeat Problems 1-4, assuming the numbers are in BCD format.

9. Subtract the contents of R2 from the number F3h; put the result in external RAM loca­tion 028Bh.

10. Subtract the contents of R l from R0; put the result in R7.

11. Subtract the contents of RAM location 13h from RAM location 2Bh: put the result in RAM location 3Ch.

12. Subtract the contents of TH0 from TH I: put the result in TL0.

13. Increment the contents of RAM location 13h. 14h. and 15h using indirect addressing only.

14. Increment TLI by I Oh.

15. Increment external RAM locations 0100h and 0200h.

16. Add a l to every external RAM address from 00h to 06h.

17. Add a l to every external RAM address from 0100h to 0106h.

18. Decrement TL0. THO, TL1, and TH l.

19. Decrement external RAM locations 0l23h and 01 BDh.

20. Decrement external RAM locations 45h and 46h.

21. Multiply the data in RAM location 22h by the data in RAM location l Sh; put the result in RAM locations 19h (low byte). and lAh (high byte).

22. Square the contents of R5; put the result in R0 (high byte), and RI (low byte).

23. Divide the data in RAM location 3Eh by the number l 2h; put the quotient in R4 and the remainder in R5.

24. Divide the number in RAM location 1 Sh by the data in RAM location 16h; put the result in external RAM location 7Ch.

25. Divide the data in RAM location 13h by the data in RAM location 14h, then restore the original data in l3h by multiplying the answer by the data in 14h.

Labels: