# Why this code wasn't written in a much simpler way?

I have came across a question while working on assembly language. Here is the question:

Assume that bit P2.2 is used to control an outdoor light and bit P2.5 a light inside a building. Show how to turn on the outside light and turn off the inside one.

Solution given:

SETB C            ; CY = 1
ORL C, P2.2       ; CY = P2.2 ORed w/ CY
MOV P2.2, C       ; turn it on if not on
CLR C             ; CY = 0
ANL C, P2.5       ; CY = P2.5 ANDed w/P2.5
MOV P2.5,C        ; turn it off if not off


I just felt like it would do just the same job to code:

SETB P2.2
CLR P2.5


What's wrong with that?

• Maybe just didactics- showing how to use the carry bit as an accumulator. There's no advantage that I can see in this particular case. This looks like 8051 assembly code. Sep 1, 2017 at 20:01
• @SpehroPefhany But as far as I know, the Acc register is used in some cases since it is the only register that supports some instructions like DA, RR, RL etc. I don't think this is the case here. Am I wrong? Sep 1, 2017 at 20:11
• The carry is one bit wide. You might want to use it as an accumulator in some cases such as ladder logic evaluation. Sep 1, 2017 at 20:18

You are right in that it appears the code you show is silly. Perhaps whatever machine this runs on can't do immediate operations to set bits on I/O ports, and that that's why something like SETB P2.2 isn't possible.

Still setting the CY bit to 1, then ORing anything into it is just plain silly. The same goes for setting the CY bit to 0, then ANDing something into it. Clearly the CY bit can be directly copied into a I/O pin bit, since the code does that. At most this should be 4 instructions, certainly not 6.

• So I can say that if a bit is bit-addressable, I am allowed to use bit instructions on whatever bit is it, right? Sep 1, 2017 at 20:03
• @İlk: Not necessarily. There might be restriction like the bit instructions only work on certain registers, certain "near" memory, and the like. Without knowing the processor, we can't say for sure whether SETB P2.2 would have been possible. However, SETB C followed by MOV P2.2, C, is clearly possible. Sep 1, 2017 at 20:12
• @OlinLathrop: The processor is almost certainly some 8051 variant, and the instruction set for those would allow the same locations to be used for SETB bit and CLR bit instructions as for MOV bit,C. Further, while using discrete instructions to read an I/O port, update the value, and write it back will yield different semantics from using read-modify-write instructions, the bitwise instructions all use the same read-modify-write semantics on I/O ports. Sep 1, 2017 at 20:48

The code is almost certainly for a processor using the 8051 instruction set. On that processor, the code variation you give would have the same effect as the original except that it would run faster. Executing "ORL C,P2.2" when carry is set will have no observable effect except to waste some number of cycles (two CPU cycles totaling 24 clock cycles on an 8051 if I recall correctly; likely a different number on some other variants). Likewise with executing "ANL C,P2.5" when carry is clear. Although there may be some kinds of processor where a request to read some I/O locations would have some observable effect, I don't think any 8051-style processor has ever had such behavior for any bit-addressable I/O locations, much less for bits of P2.

Perhaps the purpose of the code was to demonstrate the ORL C,bit and ANL C,bit instructions, but this seems like a weird example to demonstrate them.

The assembly code given is likely compiler-generated. It is the unoptimized version of the following C statements, where P2_2 and P2_5 are the bit-addressable objects:

P2_2 |= 1;
P2_5 &= 0;


This may seem equivalent to P2_2 = 1; and P2_5 = 0;, but it isn't if the bit-addressable registers are volatile objects. A read-modify-write operation on a volatile object must perform the read and the write, in that order. This ensures that any side-effects from reading or writing the register actually occur.

Although I know of no 8051 bit-addressable register with side-effects, a compiler cannot assume there isn't or won't ever be one.

• Good point about possibly being compiler-generated. However, it then moves the question to why someone would write P2_2 |= 1 instead of just P2_2 = 1. Sep 2, 2017 at 15:20

The real difference between these may be subtle.

In your simplified answer the logic is read the port, set or clear the bit value and then write it back out to the port. Note the whole port could be re-written here.

The solution on the other hand uses the MOV bit instruction which may operate in a rather different manner.

Without going into the details of the particular part used here it is difficult to determine if there is a difference, or if it matters.

Or it could just be the instructor decided to make you think.... which is after all.. his real job.

The only answer is that the processor does not support 1 bit instructions directly. However, when the carry bit is used, it knows it is only one bit being manipulated.