Experiment 1 - Working with Registers

Programming is the process by which a task is broken down into a set of instructions that can be performed by a computer.  Typically, programs consist of instructional blocks classified in one of three ways or control structures: sequence, selection, or iteration.  Sequence means that instructions within a block are performed in a specified order.  Selection means that, within a block of instructions, a selection is made between alternative sub-blocks of instructions based on a condition. Iteration means that a block of instructions is performed repeatedly based on a condition.   Computer microprocessors like the Intel 8080 and its successors are designed to perform all three.  In Experiments 1, 2, and 3 we will explore sequence structure.  In later experiments, we will explore selection and iteration.

In the first few experiments, we will code our programs in machine language.  Our coding examples will be simple, short, and intended to illustrate the very basics of microprocessor operation.  In later experiments, as our programs grow more lengthy and complex, we will code with assembly language.  But to get started, we will flip switches and watch lights blink as in the old days!

In the Beginning . . .

The Intel 8080 microprocessor was released in 1974 and became one of the most popular microprocessors of its day.  The Intel 8080 is an 8-bit microprocessor, meaning that most of its operation centers around registers and memory that is 8-bits wide.  There are seven 8-bit, working registers.  The "A" register is called the accumulator because it receives or "accumulates" the results of arithmetic and logical operations.  The remaining working registers are designated B, C, D, E, H, and L.  They perform "scratchpad" duty, holding values for various operational and computational purposes.  The Intel 8080 can directly address 65,536 bytes of 8-bit memory in which programs and data are stored.  To communicate with the outside world, the Intel 8080 directly addresses up to 256 8-bit digital input/output (I/O) ports. 

The Intel 8080 is a primitive microprocessor by modern standards.  It consists of three functional units: 1) Registers (see above), 2) Arithmetic/Logic Unit (ALU), and 3) Control Circuitry.  Memory and peripherals are external.  By contrast, the ATMEL ATmega328 that we will work with later has the same three functional units plus on-chip memory of various types and several useful peripherals.  For a more complete description of the Intel 8080 architecture, refer to the user's manual.

The Intel 8080 has 78 machine language instructions.  Each instruction consists of one 8-bit code byte followed by none, one, or two additional 8-bit data bytes.  The code byte generally represents an operation and the data byte(s) represent a related operand.  For instance, the operation might be to add a constant value to the accumulator.  The "add immediate" code byte (the operation) would be followed by a data byte (the operand). The second operand would be in the accumulator.  This experiment will familiarize you with the Intel 8080's working registers and the instructions used to move data into, out of, and around them. 

When working with Intel 8080 machine language, octal turns out to be a good way to designate Intel 8080 code bytes.  The reason is that many Intel 8080 instructions are constructed around octal representation of the working registers.  The table below shows the binary and octal values associated with each register.

Register Reference Number ( r )
Register Binary Octal
A 111 7
M 1 011 6
L 101 5
H 100 4
E 011 3
D 010 2
C 001 1
B 000 0

1 M designates a "memory register" and is used to extend operations to indirectly addressed memory. We will explore its use in a later experiment.

Note:  For this experiment and when it is not otherwise obvious, the suffix B for binary and Q for octal will be used for constants other than decimal.  For instance, 100 (decimal) would be 01100100B (binary) and 144Q (octal).

To see an example of octal register referencing, consider the Intel 8080 "move immediate" instructions shown in the table below.  For immediate instructions, the code byte is "immediately" followed by a numeric data byte to be loaded (moved) into the working register referenced.  The middle digit in the MVI code byte is "r" as given in the Register Reference Table.  We could write the octal MVI code byte as "0r6" where r is the register reference number.  For instance, "MVI A" is "0 7 6" since r = 7 for register A.

Move Immediate Instructions
Instruction 0 r 6
Code Byte
00 r 110
Code Byte
(Split Binary)
MVI* A,v 076 00 111 110
MVI M,v 066 00 110 110
MVI L,v 056 00 101 110
MVI H,v 046 00 100 110
MVI E,v 036 00 011 110
MVI D,v 026 00 010 110
MVI C,v 016 00 001 110
MVI B,v 006 00 000 110

* In computer assembler coding, ainstruction mnemonic like MVI is a symbolic name for a machine language code byte .  Later, when we switch from machine to assembly coding, we'll use easier to remember instruction mnemonics and let the assembler make the code byte translation for us.

To take advantage of octal register referencing while machine coding, we will write code and data bytes in octal.   For addresses, we will split the address into two groups of octal digits.  The first group we refer to as the "page"; the second group we'll call the "location" on the page.  The Intel 8080's memory consists of 256 pages of 256 bytes each for a total of 256 * 256 = 65,536 bytes.  Each page, in turn, consists of 256 locations.  The first address in the Intel 8080's memory space is 000 000Q and the last address is 377 377Q.  We would read address 127 341Q as location 341Q on page 127Q.  The WhippleWay Front Panel 8080 conveniently spaces address check boxes and data LEDs in two and three-bit groups to make octal representation easier.

Suppose for example we want to program "MVI A, 10"; i.e., load the A register with decimal value 10.  The machine code would be written as follows:

Memory Address
( Split Octal)
000 000 076 The "7" refers to the A register while the "0" and "6" designate this as a "move immediate to register" instruction.
000 001   012 012Q is the octal equivalent of decimal 10; i.e.,  0 * 8^2 + 1 * 8^1 + 2 * 8^0 = 0 + 8 + 2 = 10.

We are about to begin using the Front Panel 8080.  Please become familiar with the operating specifications found here.

Try it!

Example 1.  Move the decimal value 10 to the A register and display the result in the Data LEDs.

  1. On the WhippleWay Front Panel 8080, uncheck all Memory check boxes, then click the Examine button. The Data indicators show the contents of split octal address 000 000Q.  
    Note: Memory contents are randomized and can be anything at start up!  Don't assume 000Q, 377Q, or anything in between!
  2. Set Memory check boxes A7...A0 to 076Q then click the Deposit button.  The Data indicators now show 076Q indicating that memory address 000 000Q contains the MVI A code byte.
  3. Set Memory check boxes A7...A0 to 012Q, then click Deposit Next.  Address 000 001Q should show data byte 012Q in the Data indicators.
  4. Click Reset to quickly get back to address 000 000Q.  The WhippleWay Front Panel 8080 is ready to execute the MVI A instruction.
  5. Click Single Step once. Address 000 002Q is displayed.  The move immediate instruction at 000 000Q has been executed.
  6. Click "Display A" in the lower right corner to show the contents of the A register in the Data LEDs.  It should be 012Q, the immediate data we loaded in register A!

Example 2.  Load register B with 125Q and then move it to A for display.

Change the "7" in 076Q to the appropriate r value for B in the Register Reference Table.  MVI B is then 006Q. To check whether it works, use the MOV (move) instruction to move data from the B to A for display.  For the Intel 8080, the move instruction is simply "1" followed by the destination register rd and the source register rs or "1 rd rs.".  MOV A,B is 170Q.  It's that simple.  Just remember the order is "destination" then "source"!

  1. Set all Memory check boxes to unchecked, then click the Examine button. The Data indicators show the contents of address 000 000Q.
  2. Set Memory check boxes A7...A0 to 006Q, then click the Deposit button.  The Data indicators should show 006Q, the MVI B instruction code byte.
  3. Set Memory check boxes A7...A0 to 125Q, then click Deposit Next.  Address 000 001Q should show Data 125Q.
  4. Set Memory check boxes A7...A0 to 170Q, then click Deposit Next.  Address 000 002Q should show Data 170Q.
  5. Click Reset to quickly get back to address 000 000Q.
  6. Click Single Step twice. Address 000 003Q is displayed.  Both the MVI B 125Q and MOV A,B instructions have been executed and in that sequence.
  7. Click Display A in the lower right corner to show the contents of the A register.  It should be 125Q!

Something to think about

The simple task we performed in Example 2 was to load a value in the B register and then move it to the A register.  This is an example of sequence structure; that is, a block of instructions each executed in a specific order.  Execution begins with the first instruction (MVI B, 125Q) and proceeds instruction-by-instruction until the last instruction (MOV A,B) is executed.  For it to conform strictly to sequence structure, neither entry after the first instruction nor exit before the last instruction is allowed. We will see later that not all tasks can be performed with sequence structure alone.  Selection and iteration structures will be required.

Continue to next Experiment - Click Here