﻿ Front Panel Project Intel 8080 Logical Operations | WhippleWay Software | Intel 8080 Emulator | Assembly Language | Learn Coding

Experiment 3 - Logical Operations

In this experiment, we will explore the Intel 8080's ability to perform bit-wise logic operations including NOT, OR, AND, and XOR (exclusive OR).  Like the ADD/SUB group, logic operations are performed on the A register with the result in A.  Also, as before, one operand is always in A; the other is either in a working register or an immediate (following) data byte.

Logic basics for the Intel 8080.

Before proceeding, let's review four common logical operators.  Below are truth tables that define operator results (T True or F False) for given operands "p" and "q".

 p NOT p T F F T
 p q p OR q T T T T F T F T T F F F
 p q p AND q T T T T F F F T F F F F
 p q p XOR q T T F T F T F T T F F F

Describing the operations in words is helpful.

• NOT - The result is the negation or complement of the operand; that is, a one becomes zero and a zero becomes one  Sometimes we say that the NOT operator "flips a bit".

• OR - The result is True if either or both operands are True.  A different but equally useful way of saying it is this:  the result is False only if both operands are False.

• AND - The result is True only if both operands are True.  Saying it differently, the result is False if either of the operands is False.

• XOR  - The result is True only if the operands are different.  Again said differently, the result is False only if the operands are the same.

For our digital logic applications, True is taken as logic 1 and False as logic 0.  "Bit-wise" means that Intel 8080 logic instructions operate individually on each bit of the A register with the result in the corresponding bit of A.  The Intel 8080 directly implements OR, AND, and XOR.  NOT is implemented using the XOR instruction.  Listed below are the Intel 8080 logic instructions.

Note: In the descriptions below, r is the Register Reference Number and v is an 8-bit data value.

ORI v    OR Immediate v with A.    The value in A is OR'ed bit-wise with the value v with result in A.  The code byte for ORI is 366Q followed by a data byte v.
Status bits affected - Sign, Zero, Parity. Carry and Auxiliary Carry are cleared (made zero).

ORA  r    OR contents of register r with A.   The value in A is OR'ed bit-wise with the value in register r with result in A.  The octal byte code for ORA is 26r.  For example, ORA H is 264Q.  "4" is the Register Reference Number for register H.
Status bits affected - Sign, Zero, Parity. Carry and Auxiliary Carry are cleared (made zero).

ANI v    AND Immediate v with A.    The value in A is AND'ed bit-wise with the value v with result in A.   The code byte for ANI is 346Q followed by a data byte of value v.
Status bits affected - Sign, Zero, Parity. Carry and Auxiliary Carry are cleared (made zero).

ANA  r    AND contents of register r with A    The value in A is AND'ed bit-wise with the value in register r with result in A.  The octal code byte for ANA is 24r.  For example, ANA H is 244Q.  "4" is the Register Reference Number for register H.
Status bits affected - Sign, Zero, Parity. Carry and Auxiliary Carry arecleared (made zero).

XRI v    XOR Immediate v with A.    The value in A is XOR'ed bit-wise with the value v with result in A.   The code byte for XRI is 356Q followed by a data byte of value v.
Status bits affected - Sign, Zero, Parity. Carry and Auxiliary Carry are cleared (made zero)o.

XRA  r    XOR contents of register r with A   The value in A is XOR'ed bit-wise with the value in register r with result in A.  The octal code byte for XRA is 25r.  For example, ORA H is 254Q.  "4" is the Register Reference Number for register H.
Status bits affected - Sign, Zero, Parity. Carry and Auxiliary Carry are cleared (made zero).

Logical operators are useful in manipulating, masking, and testing bits.  The examples below will demonstrate each application.

Try it!

Example 1 - Create and test code that performs each logic operation (OR, AND, and XOR) on the A register using an immediate data value.  Assume A is 10101010B and the immediate value is 00001111B.

000 000    076    MVI A, 10101010B      10101010BgA
000 001    252                                          10101010B = 252Q
000 002    366    ORI 00001111B            A OR 00001111BgA
000 003    017                                          00001111B = 017Q
000 004    166    HLT                               Halt execution

a) Enter the code above. Click Reset and Single Step through the program.  Click "Stop" and use the Display A button to check the value in the accumulator.  Use the Display Status button to display the status bits.  The table below gives the position of the status bits in the Data LEDs.  Compare the result against the table below for the OR example.

b) Repeat part a for AND by changing address 000 002Q to 346Q.

c) Repeat part a for XOR by changing address 000 002Q to 356Q.

d) Change address 000 002Q & 000 003Q to ANI 10000000B.  Single step through, and compare with the table below.

e) Change the immediate value at address 000 001Q to 00101010B and repeat.

 Part Logical Operation Result (Binary) Processor Status Word S Z x AC x P x C D7 D6 D5 D4 D3 D2 D1 D0 a 10101010 OR 00001111 10101111 1 0 0 0 0 1 1 0 b 10101010 AND 00001111 00001010 0 0 0 0 0 1 1 0 c 10101010 XOR 00001111 10100101 1 0 0 0 0 1 1 0 d 10101010 AND 10000000 10000000 1 0 0 0 0 0 1 0 e 00101010 AND 10000000 00000000 0 1 0 0 0 1 1 0

The "x" columns in the Processor Status Word are not significant and always have the values indicated.

Using a logic operator to manipulate data bits.

Logical operators can be used to manipulate bits. Consider the results of a) and b) in the table above and assume the bits in the accumulator represent logical data to be manipulated by the immediate operand.

1. Force bits to "1":  The OR operator forces bits 0-3 to "1" leaving bits 4-7 unchanged.  OR'ing with "1" results in a "1" regardless of the original value of the data bit.   OR'ing with "0" leaves data bit unchanged.

2. Force bits to "0":  The AND operator forces bits 4-7 to "0" leaving bits 0-3 unchanged.  AND'ing with "0" results in a "0" regardless of the original value of the data bit.  AND'ing with "1" leaves data bit unchanged.

3. Flip bits:  The XOR operator complements (negates) bits 0-3 leaving bits 4-7 unchanged.  XOR'ing with "1" flips the data bit.  XOR'ing with "0" leaves data bit unchanged.

Individual bits within a data byte are often used to control external devices.  By choosing the appropriate operator (OR, AND, or XOR) and operand, individual bits on an  I/O ports can be manipulated without affecting other bits.

Try it!

Example 2 - In a security application, assume that the lower 6 bits of a  output port control outdoor lights.  Setting a bit to one turns on a light; clearing a bit to zero turns the light off.  The table below shows the association of lights with particular bits.

 Light Bit Front Porch 0 Back Porch 1 West Front Flood 2 East Front Flood 3 West Back Flood 4 East Back Flood 5
1. Assuming all lights are off, create and test code that turns all lights on?

Let register A represent the light control byte.  If the lights are turned off, then all bits in A will be zero.  We can turn on all the bits using OR immediate (ORI) with 00111111B.

000 000    076    MVI A, 00000000B      00000000B  gA
000 001    000                                          00000000B = 000Q
000 002    366    ORI 00111111B            A OR 00111111BgA
000 003    077                                          00111111B = 077Q
000 004    166    HLT                               Halt execution

Click Reset and Single Step through the program.  Click "Stop" and use the Display A button to check that the value in the accumulator is 00111111B.  All lights are turned on.

2. Assuming all lights are off, turn on the front and back porch lights? OR immediate (ORI) with 00000011B to turn on porch lights.

Let register A represent the light control byte.  If the lights are turned off, then all bits in A are zero.  The front and back porch lights are bits 0 and 1 respectively.  We can turn just these bits on using OR immediate (ORI) with 00000011B.

000 000    076    MVI A, 00000000B      00000000B gA
000 001    000                                          00000000B = 000Q
000 002    366    ORI 00000011B           A OR 00000011BgA
000 003    003                                          00111111B = 003Q
000 004    166    HLT                               Halt execution

Click Reset and Single Step through the program.  Click "Stop" and use the Display A button to check that the value in the accumulator is 00000011B.

3. Assuming  all lights are on, turn off all but the front and back porch.

Let A represent the light control byte.  If all lights are turned on, then A is 00111111B.  We can turn off bits all except 0 and 1 using AND immediate (ANI) with 00000011B.  Bits 2 to 5 will be cleared leaving bits 0 and 1 unchanged.

000 000    076    MVI A, 00111111B      00111111B gA
000 001    077                                          00111111B = 077Q
000 002    346    ANI 00000011B            A AND 00000011BgA
000 003    003                                          00000011B = 003Q
000 004    166    HLT                               Halt execution

Click Reset and Single Step through the program.  Click "Stop" and use the Display A button to check that the value in the accumulator is 00000011B.

4. Regardless of the state of the lights, turn all lights off?

Assume A has some lights on (A = 00101010B).  AND immediate (ANI) with 00000000B clears all bits and turns all lights off.

000 000    076    MVI A, 000101010B    00101010B  gA
000 001    052                                          00101010B = 052Q
000 002    346    ANI 00000000B            A AND 00000000BgA
000 003    000                                          00000000B = 000Q
000 004    166    HLT                               Halt execution

Click Reset and Single Step through the program.  Click "Stop" and use the Display A button to check that the value in the accumulator is 00000000B.

Using a logic operator to mask data bits.

Logical operators can be used to mask groups of bits within a data byte. Consider the result of b) and the AND operator in the table above.  The effect of AND'ing with groups of 0's and 1's is to "mask off" the four upper bits leaving the four lower bits unchanged.  Suppose the four lower bits represents a four bit binary value while the four upper bits represent unrelated data of some sort.  The masking operation isolates the lower bits ready for further processing.

Try it!

Example 3.  Suppose that the lower five bits of a data byte indicate room temperature in degrees C  (0 to 31 °C)  .  Suppose further that the upper three bits indicate which room's temperature is in the lower five bits. Up to eight rooms (0 to 7) can be designated.  Use masking to isolate the two distinct pieces of data.

Assume room 2 with a temperature of 27 °C is in register A; then A is 01011011.  To get the temperature, we mask off (AND immediate) the upper three bits with 00011111B.

000 000    076    MVI A, 01011011B      01011011BgA
000 001    133                                          01011011B = 133Q
000 002    346    ANI 00011111B            A AND 00011111BgA
000 003    037                                          00011111B = 037Q
000 004    166    HLT                               Halt execution

Click Reset and Single Step through the program.  Click "Stop" and use the Display A button to check that the value in the accumulator is 00011011B or 27.

Similarly, the room number can be isolated by masking off the lower five bits.

To get the room number, we mask off (AND immediate) the lower five bits with 11100000B.

000 000    076    MVI A, 01011011B      01011011BgA
000 001    133                                          01011011B = 133Q
000 002    346    ANI 11100000B            A AND 11100000BgA
000 003    340                                          11100000B = 340Q
000 004    166    HLT                               Halt execution

Click Reset and Single Step through the program.  Click "Stop" and use the Display A button to check that the value in the accumulator is 01000000B or 64. To get the actual room number, we need a way to divide by 32 or by 2 five times.  In Experiment 2 we saw that ADD A multiplies by 2.  Looking ahead, the Intel 8080 has an instruction RRC (017Q) that rotates the A register contents once to the right, essentially dividing by 2.  Five RRCs will divide by 32 and give us the desired result. Here is the code.

000 000    076    MVI A, 01011011B      01011011BgA
000 001    133                                          01011011B = 133Q
000 002    346    ANI 11100000B            A AND 11100000BgA
000 003    340                                          11100000B = 340Q
000 004    017    RRC                              A/2gA
000 005    017    RRC                              A/2gA
000 006    017    RRC                              A/2gA
000 007    017    RRC                              A/2gA
000 010    017    RRC                              A/2gA
000 011    166    HLT                               Halt execution

Click Reset and Single Step through the program.  Click "Stop" and use the Display A button to check that the value in the accumulator is 00000010B or 2, the room number.

Using a logic operator to test data bits.

Look closely at the results of Example 1 parts d and e above.  In part d, we ANDed  10101010B with 10000000B.  We have, in effect, tested bit 7 of the first byte; that is, the result reflects the state of bit 7 ignoring the other bits.  Now look at the Z (Zero) status bit.  It is zero because the logical operation produced a non-zero result.  Consider part e.  Bit 7 of the data byte is zero, so ANDing with 10000000B results in 00000000B and the now the Z (Zero) status bit is a one.  By ANDing with 10000000B, we are "testing" bit 7 with the result indicated by the Z (ZERO) status bit.  Later, in Experiment 4, we will use the status of the zero or other PSW bits in selection structures to execute different blocks of code.  As we will see in the example below, testing with the AND need not be limited to a single bit.

Try it!

Example 4.  Suppose that the lower six bits of a data byte indicate the status of a vehicle's four doors, its cargo door, and its hood.  A zero bit value indicates the door is closed while a one indicates the door is open.  The chart below shows the specific association with particular bits.

 Door Bit Front Driver 0 Front Passenger 1 Rear Driver 2 Rear Passenger 3 Cargo 4 Hood 5
1. Is the cargo door open?

First, let's assume that front doors are both open, but the cargo door is closed.  Register A is then 00000011B. To test the cargo door, AND immediate with bit 4 a one or 00010000B.

000 000    076    MVI A, 00000011B      00000011BgA
000 001    003                                          00000011B = 003Q
000 002    346    ANI 00010000B            A AND 00010000BgA
000 003    020                                          000100000B = 020Q
000 004    166    HLT                               Halt execution

Click Reset and Single Step through the program.  Click "Stop" and use the Display Status button to check that the Z status bit LED (D6) is on indicating a Z (Zero) condition.  Note that other bit being one does not matter. Only bit 4, the cargo door bit, affects the result.

Change register A to 00010011B and test the cargo door again.

000 000    076    MVI A, 00010011B      00010011BgA
000 001    023                                          00010011B = 023Q
000 002    346    ANI 00010000B            A AND 00010000BgA
000 003    020                                          000100000B = 020Q
000 004    166    HLT                               Halt execution

Click Reset and Single Step through the program.  Click "Stop" and use the Display Status button to check that the Z status bit LED (D6) is not on indicating a NZ (Not Zero) condition and that the cargo door is open!

2. Is any door open?

Assuming again that only the front doors are both open, register A is then 00000011B. To test if any door is open, AND immediate with 00111111B.

000 000    076    MVI A, 00000011B      00000011B  gA
000 001    003                                          00000011B = 003Q
000 002    346    ANI 00010000B            A AND 00111111BgA
000 003    020                                          00111111B = 077Q
000 004    166    HLT                               Halt execution

Click Reset and Single Step through the program.  Click "Stop" and use the Display Status button to check that the Z status bit LED (D6) is not on indicating a NZ (Not Zero) condition and that at least one door is open.  We can say which one, but further programming could ferret this out.