TinyELF

Chapter 2 - The ELF II

A microprocessor is an electronic device which is physically very small (hence the name "micro-" from the Greek word meaning small) which contains the heart of a computer. In fact, it is the complete computer except for the RAM and the I/O. There are many different microprocessors around, but we will be looking only at one: the RCA 1802. Everything I said in Chapter 1 is true of all computers, including all microprocessors. Most of what I say in this chapter is specific to the 1802, and much of it is limited to a particular computer, the Netronics ELF II, which contains an 1802 microprocessor.

The 1802 has a word size of 8 bits. All data in this computer comes in 8-bit pieces, which we call bytes. One byte can contain a single letter of the alphabet (or other typewriter character) or a small number (between 0 and 255). Most of the instructions for the 1802 will also fit into one byte each.

The basic ELF II comes with 256 bytes (or words) of RAM. You can buy more memory to expand this to 65,536 bytes. Inside the 1802 there are 20 registers, more or less. The lack of precision here is due to the fact that some of these registers are not accessible to you as the programmer and you may as well assume they do not exist; while others are not exactly one byte in size and might be counted once or twice, depending on your inclination. Instead of counting them, let us see exactly what the registers are, and what they can do in the computer:

D
This is the Accumulator. It is one byte (eight bits) and as we mentioned in Chapter 1, all the data that the computer manipulates for us is operated on in the D register. Just how important this register is will be seen in the following chapters as we look at the instructions.
R0-RF
There are sixteen 16-bit Address registers in the 1802. 16 bits can store any number between 0 and 65,535 so an address register is able to point to any single byte in the maximum amount of memory that the ELF II can handle. These are general-purpose address registers, and there are few restrictions on what they can address (i.e. point to) in memory. The Program Counter can be any one of them (you decide which). Others may point to data being computed, while still others may simply be temporary data storage and not used as addresses at all. We number these registers R0, R1, R2, ... RE, RF (using hexadecimal notation: 10=A, 11=B, 12=C, 13=D, 14=E, and 15=F; for a full description of hexadecimal notation see Appendix B). Thus, we can also address the address registers.
P
This is a 4-bit register which is the address of one of the address registers. Whichever register P points to is the Program Counter. Note that P is not the PC; it only points to the PC. The PC register in turn points to some byte in RAM, which is the next instruction to be executed. Since there are 16 address registers, four bits is exactly the right size to uniquely identify one of them. There are a few instructions in the 1802 which can modify P, but there are many instructions which affect the address register P points to.
X
This is another 4-bit register that points to an address register. The address register pointed to by X is used by the 1802 to address a byte in memory for most of the arithmetic and logical instructions, as well as the I/O instructions and certain others involving loads and stores.
T
This 8-bit register is for temporary storage of P and X. It is built into the 1802, but its use is very limited. There is only one instruction which stores T into memory, and no good way to load data into T. For now, just assume that T does not exist.
I, N
These two 4-bit registers together are sometimes called the Instruction Register, and they always hold the instruction the computer is currently executing. Since you, the programmer, have no say in how the instruction register is used, you may as well forget it exists. I only mention it because all the reference manuals for the 1802 make a big deal about the I and N registers; just ignore them.
DF
This is a single bit register in which is stored part of the result of arithmetic and some logical operations. It is normally called the Carry bit and I usually like to abbreviate it "C"; but RCA calls it "DF", so DF it is. We will discuss how DF is used more fully in the following chapters.
IE
This is a another one-bit register in the computer which remembers whether the computer will allow I/O devices to affect its operation without executing I/O instructions. When something like this happens (intentionally) we say the computer has been interrupted, and the bit that says whether the computer will let that happen is called the Interrupt Enable flag. The 1802 has instructions to set this flag to "yes" or "no", and to ask what its current state (answer) is. The use of this flag is discussed more fully in Chapter 6, when we talk about interrupts.

There are several varieties of instructions the 1802 can execute. All begin with a single byte, which defines what the computer is to do when it executes this instruction. We call this byte the Opcode. Recall that a single byte can contain a number between 0 and 255; it is often convenient to number all the possible instructions, so that each one is associated with some number in that range. This is in fact exactly the same as looking at the opcode of an instruction and thinking of it as a number instead of as an instruction. For example, a particular byte in memory might have the bit pattern "01010011". If we think of it as a number, we would say it is 53 in hexadecimal (which is 83 in decimal). If we think of it as a letter, we would say it is the ASCII code for the letter "S". If we think instead of it as an instruction opcode, we would say it is the "STR 3" instruction which tells the computer to store D into the RAM byte pointed to by R3 (address register 3). There are many other questions this one-byte datum could be the answer to, but they do not concern us here. The point is that instruction number 83 is a particular store instruction which uses address register 3.

Some of the bits in the opcode tell the computer what kind of instruction it is, while others may select one of the registers or further specify the operation. In the case of the 01010011 byte, the first four bits tell the 1802 that this is a store instruction, and the last four bits point to an address register. Thus all of the opcodes from 80 through 95 are store instructions, using different address registers.

Some of the instructions come with data attached. The 1802 can tell which these are by the particular bits in the opcode, so it knows to go back to memory for another byte. Other opcodes contain bits that tell the computer that there is an address (or a piece of an address) attached to the instruction, so the 1802 goes back to RAM for one or two more bytes as part of this instruction. When I describe each instruction, I will tell you exactly how many bytes the 1802 will expect to come with its opcode.

In a similar way, some of the instructions depend on X to indicate which address register to use, while others (like the store instruction mentioned) have that information as part of the opcode. Still others do not directly use any address register. Here also I will give the details when I describe the instructions.

In Chapters 3-6 we will be looking at exactly how the 1802 in the ELF II executes each instruction in its repertoire (the list of instructions the computer knows how to execute). But first let us get a general notion of how the computer works.

Look at your ELF II. You will notice three toggle switches (or possibly locking pushbuttons) on the right hand side near the edge of the board; the bottom switch (closest to you) is labeled "M/P" for "Memory Protect". When this switch is on (positioned away from you in the direction of the little arrow, or locked down), the RAM memory is protected from being accidentally changed by you or the computer; in other words, while the switch is on, nothing new can be stored into memory, even by those instructions or operations which normally would store into it.

The next switch is labeled "LOAD", and is used to load data (and programs) into the computer before running. This switch works with the third switch, labeled "RUN". When both the LOAD and RUN switches are off (towards you), the computer is reset, that is, put into a known initial state or condition. This is so that the computer will always start executing the first instruction of the program. Specifically, when the 1802 is reset, X and P are both set to point to R0, which is also set to zero so that it will point to the first byte in memory. IE is also set to the enabled state, but that does not concern us now.

When the switches are in the combination RUN off, LOAD on, M/P off, the computer is able to manually load bytes from the hex keypad. You push the keys corresponding to the hex code of the byte you want entered, then push the "I" (for "Input") key once. The byte that was entered into memory shows up on the two-digit hex display just above the keypad. For the next byte you repeat the sequence. We will call this combination of the switches the Load mode. The 1802, when operated in this way, uses address register R0 to point to the memory byte to be loaded next. Since this register is inside the 1802 you cannot see it, so you have to count the number of times you push the "I" key to know which memory byte will be loaded next. Later I will show you a few tricks to make it a little easier to know where you are. If you entered the Load mode from the Reset state (both RUN and LOAD off), you know that R0 points to memory address 0, which is the first location in memory. Therefore the first byte you enter will go into memory location 0, the second byte will go into location 1, the third into location 2, etc. If you ever lose count, you probably have to reset the computer (turn the LOAD switch off, then back on) and start over. I have done this many times myself, so you should not feel badly if this happens to you rather often.

You recall I said that the M/P switch protects memory from both the computer and you. Let's talk about you. If you enter the Load mode and then turn the M/P switch on, you will find that the computer thinks it is loading bytes into memory, but since memory is not changing, what you see on the hex display is not what you loaded, but what was there before. This is a convenient way to examine the contents of memory, so we'll call it the Examine mode. You can turn the M/P switch on and off as often as you like, thus switching between the load mode and the examine mode. Doing this does not affect R0 (you have to reset the computer for that), so you can examine a few bytes, store something new into the next byte, then go back to looking at what is already there after that. Thus if you make a mistake on the 13th byte of your program, you can correct the mistake without re-keying the whole program by resetting, examining the first 12 bytes (you already know they are right, but you can look at them anyway), then loading the 13th byte, and continuing. You will probably find that you make more than one mistake in a single program, so it is best to save all your fixups for a single pass. This way you only need to step through memory three or four times; once to load the original program, once to examine it and see where all the errors are, once to correct those errors, then finally one more time to make sure you got them all right. Obviously it is very important that you write down on a piece of paper exactly what hex codes you are going to put into each memory byte. More on this later.

After loading your program into the ELF II you probably want the computer to execute it. This is done by setting RUN on, and LOAD off. We will call this the Run mode. It is generally best to enter the Run mode from the Reset state. That is, turn both switches off, then turn the RUN switch on. Since P is 0 and address register R0 is also 0, the first instruction to be executed will be the byte you loaded into location 0. The second instruction will be the byte you loaded into location 1 (unless the first instruction was more than one byte; in that case the second instruction may come from memory location 2 or 3). Chapters 3-6 are a detailed description of how each instruction is executed, so I will say no more at this time.

The fourth possible combination of the RUN and LOAD switches is both on. This is called the Wait state because it is used to stop the computer from executing without resetting it. If you put the computer back in the Run mode, it will continue where it left off. Wait will also stop the computer from proceeding in the Load mode, but that is not of much value, since it is normally waiting for you to push the "I" key anyway. You cannot depend on switching the computer from Load to Run, or from Run to Load by going through Wait, because whatever the computer is doing when it enters the Wait state is not finished, and so it may not be able to properly start up in the other mode.

TinyELF Specific!

In TinyELF, the Wait mode has been replaced with Single Step mode. Single Step mode behaves the same as Wait mode, with two differences. First, if you're displaying graphics as described in Chapter 7, they'll continue to be displayed; Wait mode would have shown a blank screen. Second, you can execute instructions one-by-one by using the Step button on the CDP1802 State panel, available from TinyELF's Debug menu.

All of the programs given as examples in this book follow a fixed format. After you have used this format for a while you will begin to find that reading programs written in this format is much easier than when they are some other format. I strongly urge you to use the same format, at least until you get used to programming and find something better. Appendix C in the back of this book is a blank page ruled for coding this format; you may wish to use it to make several photocopies, or you may prefer to buy one or more pads of ruled forms from Netronics.

The Coding Form is divided into six columns, identified as: Location, Code, Label, Mnemonic, Operand, and Comments.

Location
The Location field is a four-digit hexadecimal number corresponding to the memory address of the byte on this line. On the forms, only the first line has all four digits, since the first three digits will be the same for every byte on the page. Also, the fourth digit is pre-numbered on the form to save you some writing.
Object
The Code field is a two-digit hexadecimal value representing the byte to be stored into that location in memory. Sometimes we will collapse several bytes into a single line if they are part of a single instruction.
Label
The Label field is used to give names to certain memory locations. This is for your benefit, so you can choose names to remind you what is important about this address.
Mnemonic
The Mnemonic (pronounced "knee-MAW-nick") field contains the two- three- or four-letter name of the instruction which is in this position. This is also for your benefit. The word "mnemonic" is derived from the name of the Greek goddess of memory, and the instruction mnemonic is a short, easily remembered, abbreviation of the full name of the instruction. When we talk about instructions in the following chapters we will normally use the mnemonic rather than the hex code. The only purpose of the hex object codes is to load the program into memory.
Operand
The Operand field is used to write down any information about this instruction that is not already implied in the mnemonic. We write it on the same line as the mnemonic, even though it may correspond to a byte in the next location of memory. This way all of the human-readable information about one instruction is on the same line.
Comments
The last field on the form is the largest, and you are expected to do the most writing in that part. It is called the Comments field, because here you explain to the world (or to yourself next week) what the program is supposed to do and why. Once you fully understand the operation of each instruction you should not be merely repeating in the comments what is obvious from the mnemonic. Instead you should use this space to explain what you think is in the registers, or where the data came from, or what you expect to do with the data three pages later. Write it as if to explain how the program works to someone who understands how the computer works (unless you are dealing with some obscure feature of the hardware that nobody understands), but who does not know what this program is supposed to do with the data or why; that person will be you, in six weeks. I know!

Those of you who are familiar with computers will immediately recognize that the format I am recommending is that printed out by computers when they run an Assembler program. An Assembler is a program that takes as input data, the human-readable version of a program (labels, mnemonics, operands, and comments) and outputs the appropriate machine language code with its addresses. When you start writing large programs, you may find one of these helpful.


EXERCISES

  1. Reset your ELF II, then put it into the Load mode. Key in Program 2.1, remembering to enter only the hex object code, not the addresses or mnemonics or labels. Do not worry about what is in memory after the end of the program (though you may want to examine some of it, just to see what it looks like). Reset the computer and put it into the Examine mode and check your work. When you have it in correctly, reset the computer again. Leaving the M/P switch on, put it in the Run mode for a few seconds, then reset the computer again and examine memory. Did anything change? (Hint: Take another look at the part of memory after your program.)

    Now reset it, turn the M/P switch off, then run the program. Examine memory again. What happened to the program? What about the rest of memory? We call this program a Memory Clear, because it clears (almost) all of memory to zeros. Notice that most of the program is still there! Occasionally I will suggest that you clear memory before trying some experiment; by that I mean, put Program 2.1 in and run it.

    By the way, don't worry about trying to understand these programs right now. I will explain how they work in Chapter 5.

  2. Now key in Program 2.2. Run it, then examine memory. How is this different from the Clear? If you do not particularly care what is in the part of RAM you are not using, this gives you a convenient way to step through memory without losing count. It also may help you to find bytes that are stored in strange parts of RAM (this often happens if you make a mistake in writing or keying in a program). We call this program a Memory Sequencer because it stores a sequence of numbers in (most of) memory.

  3. This exercise will help you to understand the Wait mode. Key in Program 2.3 and run it. Once every three or four seconds the Q light (next to the hex display) should blink briefly. After you have a feel for the timing of the blink, put the computer into the Wait state. Notice that the blinking stops. Return to the Run mode, and see that the time remaining to the next blink is finished out, but the blinking continues. This is easier to see if you flip the switch (into Wait) just before the next blink. You might, just for fun, try to hit the Wait switch while the blink is still on. This is quite difficult because it is only on for 1/80th of a second or so. In Chapter 3 you will learn how to turn the Q light on and off yourself, or rather how to instruct the computer to do it when you want it to.

        ..  PROGRAM 2.1 -- MEMORY CLEAR
        ..
0000 90 CLEAR:  GHI 0   .. REGISTER 0 HAS 0001
0001 AE         PLO 14  .. MAKE RE=0000
0002 BE         PHI 14
0003 EE LOOP:   SEX 14  .. EACH TIME, R14 IS -1
0004 73         STXD    .. D STILL HAS 00
0005 30         BR LOOP .. GO BACK FOR ANOTHER
0006 03


        ..  PROGRAM 2.2 -- MEMORY SEQUENCER
        ..
0000 90 SEQ:    GHI 0   .. THIS PART IS
0001 AE         PLO 14  ..   JUST LIKE CLEAR
0002 BE         PHI 14
0003 EE LOOP:   SEX 14
0004 8E         GLO 14  .. THIS IS ADDRESS VALUE
0005 73         STXD    ..   SO DATA=ADDRESS
0006 30         BR LOOP .. REPEAT UNTIL DONE
0007 03


        ..  PROGRAM 2.3 -- SLOW BLINK
        ..
0000 91 BLINK:  GHI 1   .. LOOK AT TIMER IN R1
0001 CE         LSZ     .. IS ZERO ONLY 1/256
0002 7A         REQ     .. IF NOT 00, Q OFF
0003 38         SKP
0004 7B         SEQ     .. WHILE ZERO, Q ON
0005 11         INC 1   .. BUMP COUNTER
0006 30         BR BLINK..   THEN REPEAT
0007 00

[ << Chapter 1 ] [ Index ] [ Chapter 3 >> ]



* (A Short Course In Programming is Copyright 1980 by Tom Pittman, and is reproduced in TinyELF's help book with the author's permission. Visit Tom's website.)