TinyELF

Chapter 3 - I/O and Branches

Beginning in this chapter, every program I introduce will consist only of instructions you know about and at most one new instruction (which will be marked with a double asterisk **). This way you can be sure you understand exactly what the new instruction is doing. Each program will be designed to give you a feel about what this instruction does, and how it might be expected to work together with other instructions. Do not advance to the next program until you fully understand all the material that goes before it.

Each instruction is presented in a standard format. First I will give you a test program which you can key into your ELF II to demonstrate the operation of the particular instruction. Associated with this program will be a discussion of just what you should look for when running this program, and perhaps some hints about further experiments. Following this will be a formal definition of the instruction for future reference. This will have a title line in bold face with the instruction mnemonic, hex opcode, the type of operand (if any), and a short descriptive name. The following are the operand types which the 1802 uses, but do not be overly concerned about understanding them now; I will explain each one when you first use it:

--    (No operand)
r     Address register, R0-RF
p     I/O Port number, 1-7
b     Immediate data byte
a     One-byte address
aa   Two-byte address

Let us start with a very simple program. It has one byte:

        ..  PROGRAM 3.1 -- TEST IDL
        ..
0000 00         IDL     .. **

Key this program into your ELF II, then switch it to Run mode. Did you see anything happen? Try pushing some of the keys. Any results? If you put this instruction in carefully, the computer should just sit there doing nothing, idle. In fact, the instruction is called the IDLE instruction, because it stops the computer. Since this program does nothing else, there is nothing to see. How can you tell the computer is actually stopped? You can't; you have to take my word for it. It is important that you realize that the ELF II does not tell you it has stopped. If you had an oscilloscope you could look at the SC0 line on the CPU chip; it toggles up and down while the computer is running; you might even want to wire up an LED to tell you that it is toggling, so that you will know when your computer has stopped. That is outside the scope of this book, so for now, you have to believe that the IDL instruction really does what it is supposed to. Later on we will try some experiments to see how it differs from the other instructions.

IDL Idle 00
Stop the execution of instructions, and wait for an interrupt or DMA to resume.

Now that you understand all about the IDL instruction, we will use it at the end of the next test program:

        ..  PROGRAM 3.2 -- TEST SEQ
        ..
0000 7B         SEQ     .. **
0001 00         IDL     .. STOP

Key this program in, and run it. What happened? Obviously, since there is only one more instruction than in the previous program, that instruction is what causes the Q light to go on. The Q is a kind of funny bit of memory inside the 1802 which is connected to the outside world. Therefore we can say that SEQ is an Output instruction: It outputs a "1" or "yes" or "on" to that part of the circuit that lights the little LED.

SEQ Set Q 7B
Set the Q flip-flop in the 1802 on, and set the Q output pin high.

You will notice that this next program looks very similar:

        ..  PROGRAM 3.3 -- TEST REQ
        ..
0000 7A         REQ     .. **
0001 00         IDL     .. STOP

When you run this program, what happens to Q? You say you cannot tell the difference between this program and the first one? That is because Q is being set to "0" or "off" by the REQ instruction, but it is already off because Reset turns it off. Moral of the story: If an instruction commands the computer to do something that has already been done, it does it again, but you have no way of being sure of the fact. Try this program instead:

        ..  PROGRAM 3.4 -- TEST REQ AFTER SEQ
        ..
0000 7B         SEQ     .. TURN IT ON FIRST
0001 7A         REQ     .. TURN IT OFF AGAIN
0002 00         IDL     .. THEN STOP

When you run this program, turn the lights out in the room and put your thumb over the hex digit display, then flip the Run switch on while watching the Q light carefully. You might see a very faint blink of light. Computers are fast! If you do not see anything, try 50 or 100 SEQ's followed by one REQ and the IDL; a 1 millisecond flash of light is easier to see than 11 microseconds. The point is, the SEQ turned the Q light on, then the REQ turned it off. Thus the REQ is also a sort of output instruction.

REQ Reset Q 7A
Turn the Q flip-flop in the 1802 off, and set the Q output pin low.

Now the computer is able to tell us about what it is doing. Let's complete the loop by looking at an input instruction.

        ..  PROGRAM 3.5 -- TEST B4
        ..
0000 7B         SEQ     .. TELL THE WORLD
0001 37         B4  4   .. **
0002 04
0003 7A         REQ     .. TURN Q OFF!!
0004 00         IDL     .. STOP

When you key in this program and run it, what happens to Q? Does it look any different from program 3.4? Now reset the computer, and while holding the "I" key depressed, flip it into Run mode again. What happened to Q this time? Why did it not go off? To convince yourself that the "I" key has no effect on the REQ instruction, put program 3.4 back in, and run it with the "I" key depressed. Obviously, the new instruction we added in program 3.5 is somehow looking at the "I" key, and making the REQ instruction not work. For the next experiment, clear memory (i.e. run program 2.1, or key in 256 00's by hand). Then key in this program:

        ..  PROGRAM 3.6 -- TEST B4 DESTINATION
        ..
0000 7B         SEQ     .. TURN IT ON
0001 37         B4  18  .. **
0002 12
0003 7A         REQ     .. TURN Q OFF
0004 00         IDL     .. STOP HERE
0005 00         IDL     .. (SPACE FILLER)
0006 00         IDL
0007 00         IDL
0008 00         IDL
0009 00         IDL
000A 00         IDL
000B 00         IDL
000C 00         IDL
000D 00         IDL
000E 00         IDL
000F 00         IDL
0010 00         IDL
0011 00         IDL
0012 7A         REQ     .. Q OFF HERE TOO
0013 00         IDL     .. STOP ALSO
0014 00         IDL     .. ETC...

Be sure you count the IDL's very carefully when you key this program in. Now when you run it, Q should blink on and then off (you may not see it blink in bright light) whether you start with the "I" key depressed or not. Now go in and modify the third byte of this program (the hex 12 in memory location 0002) to hex 13, and try again. Notice that now the Q light stays on if you run the program with "I" depressed. Now change memory location 0013 (this is the 20th byte, which is the next one after the REQ in location 0012) from IDL (00) to REQ (hex 7A), and try the program again. Finally, change the REQ in memory location 0003 to an IDL (00) and run the program to see how pressing the "I" key affects it. By now you should have noticed that when the "I" key is not pressed, the next instruction after the B4 is executed in sequence, but if the "I" key is pressed the next instruction to be executed is the one whose address is in the byte immediately following the B4 opcode. If you are not yet convinced of this, try putting an SEQ at any place in the first 256 bytes of memory you like, with zeros (IDL instructions) elsewhere, and a B4 instruction (hex 37) in the first byte. When the second byte has the hexadecimal equivalent of the location where you put the SEQ, then running the program with "I" depressed turns Q on; otherwise Q stays off.

We call the B4 a branch instruction because the flow of program execution takes one branch of a fork when B4 is executed. That is, depending somehow on the "I" key, the computer either takes the next instruction in sequence, or it starts executing instructions from some other part of memory. The exact place in memory where it goes for that next instruction is defined in the byte immediately following the opcode, and the two bytes together are one instruction.

We also say that the B4 instruction is an Input instruction, because it causes the internal memory of the computer to change depending on conditions external to the computer itself. In this case the memory that is changed is the Program Counter register. The external condition that the 1802 sees is called EF4 (for External Flag 4). If you look on the schematic for the ELF II computer, you will see that the "I" key is connected (somewhat indirectly) to the EF4 pin on the CPU. As you might guess, there are also EF1, EF2 and EF3 pins, but on the basic ELF II some of these are not connected to anything, and others are hard to observe. I hope you can assume that B1, B2, and B3 work the same way as B4, but look instead at their own EF lines.

B1 a Branch on External Flag 1 34 aa
B2 a Branch on External Flag 2 35 aa
B3 a Branch on External Flag 3 36 aa
B4 a Branch on External Flag 4 37 aa
If the corresponding external flag line is True (i.e. the pin is electrically low), then take as the next instruction the one found at the address which is in the second byte of the instruction. If the flag is False, advance to the next instruction in sequence and ignore the address in the second byte of this instruction.

We say "the branch is taken" when the address is used to determine the location in memory of the next instruction. You will recall that the PC is actually a 16-bit register, but there are only 8 bits in the address part of the B4 instruction. We cheat a little bit here; the low 8 bits of the PC get replaced by the branch address, and the high 8 bits are left unchanged. Later in this chapter we will look at branch instructions that replace the entire PC with a new address.

All of the conditional branches in the 1802 have a matched set of branches which test for the reverse condition. In other words, instead of testing for EF4 true as B4 does, we can also test for EF4 false. If you want to see how this works, put program 3.5 or 3.6 back into the computer, but change the 37 to 3F and see how it runs differently. As you become familiar with the 1802 instruction set, you will discover that the branch instructions are paired in such a way that the true version differs from the false version in only one bit position of the opcode; that bit is 0 for the branch if true, 1 for the branch if false.

BN1 a Branch on Not External Flag 1 3C aa
BN2 a Branch on Not External Flag 2 3D aa
BN3 a Branch on Not External Flag 3 3E aa
BN4 a Branch on Not External Flag 4 3F aa
If the corresponding external flag line is False (i.e. the pin is high electrically), then take as the next instruction the one found at the address which is in the second byte of the instruction. If the flag is True, advance to the next instruction in sequence and ignore the address in the second byte of this instruction.

Well you might say, if the 1802 can branch when a condition is true, and it can branch when the condition is false, is there some way we can convince it to branch always? The answer is obviously yes, as the next program shows:

        ..  PROGRAM 3.7 -- TEST BR
        ..
0000 7A         REQ     .. Q OFF
0001 3F         BN4 4   .. TEST EF4
0002 04
0003 7B         SEQ     .. Q ON IF EF4
0004 30         BR  0   .. **
0005 00

When you first run this program, it will not look particularly different from the other programs that do nothing. But now, push the "I" key without resetting the computer, then release it. What happened to the Q light? The computer did not stop! When the program counter reached location 0004, it simply branched back to location 0000 and repeated what it had just done. We call this a loop. Notice that every time through the loop Q is turned off, but only if EF4 is true (i.e. the BN4 does not branch) is it turned on. If Q is turned off every time through the loop, why is it on (unblinking) when the program is running? To help answer that question, try flipping the computer into the wait state a few times while you hold the "I" key down. Notice how sometimes the Q goes off and sometimes it gets just a little brighter. What you are doing is stopping the computer at various points in the loop. Can you predict which times Q will be on when you stop it? (I can't).

BR a Branch unconditionally 30 aa
Take as the next instruction, the one whose address is the second byte of the BR instruction.

As I said earlier, the two-byte branch instructions only have one byte of address with which to modify the PC. The 1802 also has three-byte branch instructions which replace the entire PC with the contents of the two bytes following the opcode; the first byte is the most significant eight bits, and the second is the least significant eight bits. Try to convince yourself this is true by clearing memory, then storing a single SEQ somewhere. Put a hex C0 in location 0000 and the address of the SEQ (in hex) in bytes 0001 and 0002. When you run the program, Q should come on if and only if the address of the SEQ exactly matches the address in those two bytes. Notice that it does not depend on the "I" key.

LBR aa Long Branch unconditionally C0 aaaa
Take as the next instruction, the one whose address is the second and third bytes of the LBR instruction.

Exercise: What happens when a branch instruction branches to itself? See if you can think of a test program to show this happening. Hint: try a BN4.

We have seen an example of an output instruction and an input instruction in the 1802. Yet neither is called "input" or "output". This is because there are other instructions which also do input or output. Key in the following program:

        ..  PROGRAM 3.8 -- TEST OUT
        ..
0000 64         OUT 4   .. **
0001 00                 .. (DATA TO BE OUTPUT)
0002 3F         BN4 0   .. LOOP BACK
0003 00
0004 64         OUT 4   .. **
0005 11                 .. (DATA TO BE OUTPUT)
0006 30         BR  2   .. LOOP BACK
0007 02

When you run this program, watch the hex display. Then push the "I" key and see what happens to it. By changing the contents of locations 0001 and 0005, convince yourself that the OUT 4 instruction puts the contents of the next byte out on the hex display. Later on we will see that this is true only if P=X, which in this case is true (both are set to zero by reset). Try as an experiment, OUT 2 (hex 62) in location 0000; what happened to the display? If you try OUT 1 you may find that the whole program goes crazy; I will explain why in Chapter 7.

Now clear memory (run program 2.1) and key in program 3.9:

        ..  PROGRAM 3.9 -- TEST INP
        ..
0000 3F         BN4 *   .. WAIT FOR "I"
0001 00
0002 6C         INP 4   .. **
0003 7B         SEQ     .. WATCH THIS!!
0004 00         IDL     .. STOP
0005 00

Before you run this program (if you already ran it, go back and verify that the program is still there) turn on the M/P switch. This is important, because this program modifies itself! I will have more to say about programs that modify themselves later. Run the program once with the M/P switch on, so you can see how it works. Notice that Q does not come on until you push the "I" key. (Why?) Now push the "0" key twice and run the program again (with M/P still on). Is it any different? Reset the computer and convince yourself that the program is still all there (i.e. go into the Examine mode and look at it). Now you are ready to run the program with the M/P s witch off. While the computer is still reset, push the "0" key twice, and turn off the M/P switch. Now run the program: When you push the "I" key, what happens to Q? To find out why, (be sure to turn the M/P switch back on and) examine your program. What happened to the SEQ instruction in location 0003? Run the program again, and before pushing the "I" key, be sure the M/P is off again, and push the "7" key, then the "B" key. Now what happened? Try running the program a few more times, but each time push a different sequence of keys: try 7,A; 6,4; 3,0. Reset the computer each time and examine 0003 to convince yourself that whatever pair of keys you push shows up in the byte following the INP 4 instruction. Try another experiment: change the INP 4 to INP 2 (hex 6A); does the keypad have any effect on what goes into location 0003 now?

As you should have noticed by now, both the INP and OUT instructions have the left hex digit 6. The right digit is between 1 and 7 for OUT and between 9 and F for INP. As it turns out, the same bit which determines whether a conditional branch tests the true or false of a condition also determines whether an I/O instruction with left digit 6 is OUT or INP. You can think of it this way: If the bit is "0" it is "OUT"; if the bit is "1" it is "INP" (relating 0=O, 1=I). We do not yet have any way to prove it on your computer, but input and output use the X register to select an address register to point to the memory byte being input or output. In Chapter 4 we will try to nail that aspect down. Meanwhile you should notice that the OUT instruction increments R0 when the byte is output (go back and look at Program 3.8: Did the computer ever use the byte to be output as an instruction? Convince yourself by looking at OUT 4 followed by 00= IDL or 7B=SEQ). Notice that in our examples R0 was both Program Counter and data pointer. In the case of the INP instruction, however, whatever was input into memory following the INP 4 instruction was also executed as another instruction; in other words, when the INP used R0, R0 was not incremented, so the next instruction fetch (which is also using R0 as PC) will fetch out the same byte which was just input. Be sure you understand this difference.

OUT p Output from memory (p = 1 to 7) 6p
Output on the port p, the memory byte pointed to by the address register pointed to by X, then increment the address register.

INP p Input to memory and D (p = 9 to F) 6p
Input from the port p, a byte to be stored into the memory location pointed to by the address register pointed to by X, and also place the byte into D.

For both the OUT and INP instructions, the low three bits of p come out on the "N" lines of the 1802 chip; these may or may not be decoded into seven separate ports; if not, then only three ports are distinguishable (1, 2, and 4).

Program 3.10 is rather complicated, and I would recommend that you sequence memory before keying it in. This will help you to place the two pieces which are located at some distance from the beginning. You will also notice that I have arranged it so that each OUT instruction outputs a byte with its own address. This can serve as a check on your keying: After keying in the 64, turn on the M/P switch and examine the next byte; it should already be correct. When you get to location 000F, switch into Examine mode and step through memory to location 002F, then go back to the Load mode for location 0030. Do the same for 0034 to 0079. The first byte after the end of your program should be at 007E.

        ..  PROGRAM 3.10 -- CONDITIONAL BRANCHES
        ..
0000 37         B4  *   .. WAIT FOR "I" RELEASE
0001 00
0002 64         OUT 4   .. ANNOUNCE OURSELVES
0003 03         ,03
0004 7B         SEQ     .. ALSO TURN ON Q
0005 3F         BN4 *   .. WAIT FOR "I"
0006 05
0007 6C         INP 4   .. GET INSTRUCTION
0008 7A         (REQ)   .. DO IT **
0009 30         BR 122  .. GOTO 7A
000A 7A         (REQ)   .. Q OFF IF EXECUTED
000B 64         OUT 4   .. ANNOUNCE "HERE"
000C 0C         ,0C
000D 30         BR  0   .. DO IT AGAIN
000E 00
        ..
0030 64         OUT 4   .. ANNOUNCE "HERE"
0031 31         ,31
0032 30         BR  0   .. GO BACK
0033 00
        ..
007A 64         OUT 4   .. ANNOUNCE "HERE"
007B 7B         ,7B
007C 30         BR  0   .. GO BACK TO FRONT
007D 00

Examine this program carefully before running it. Notice that there are four OUT instructions, but each one should output a different value. Therefore you should always know where the program was executing by what you see on the hex display. The program contains no instructions which you do not understand, so you should be fully convinced about what it will do when you run it, before you run it. In particular, you should be convinced that as coded, there is no way for the program to output either "0C" or "31"; it should alternate between "7B" and "03" as you push and release the "I" key. Turn on the M/P switch and verify that this is so by running the program. Notice that as long as the M/P switch is on, none of the other keys have any effect. Notice also that the REQ instruction in location 0008 turns off the Q when you push the "I" key.

Now turn off the M/P switch. The program should be waiting for you to push the "I" key, which you know because the hex display shows "03". First push the keys "7", "B", and then "I". Push and release "I" a few times so you know what is happening. What happened to Q? Is anything else different? Now push "7", then "A". Convince yourself that you are able to key in the opcode that the computer will execute when you push the "I" key. Remember, the INP instruction is inputting a byte into the memory location pointed to by the PC, so that byte input from the keypad becomes the next opcode. Experiment with a few opcodes that you understand, like 00=IDL. What happened? Notice that the computer is no longer running, so it cannot respond to the "I" key. Reset and try again with 30=BR. What happened this time? Why? Look again at the program, and try to convince yourself that the computer did exactly what it should have done. First it executed an INP instruction which input the 30 into memory location 0008 (if you don't believe it, reset the computer and examine location 0008). Then it executed the byte in 0008, which is the opcode of a BR instruction. But this is a two-byte instruction, so location 0009 is fetched to be used as an address. 0009 also contains 30 (it is the opcode of another BR instruction, but the computer does know that at this time). So the computer branches to location 0030, which is an OUT 4 instruction.

Now let's try some new opcodes. Remember I said that each branch instruction had a paired opcode which branches on the false of the same condition? It is bit 3 of the opcode that makes the difference (that is an 8 in the second digit: 0-7 has a zero in bit 3; 8-F has a one in bit 3). You already know about the difference between 37=B4 and 3F=BN4. Does it work for 30 (which is branch always)? Is there a "branch never"? Try it. If the opcode in 0008 is "branch never" then what is the next instruction to be executed? No, it is not in 0009, because all branch instructions are two bytes, even if the branch is not taken (to convince yourself of that, review what you learned about the B4 instruction). We thought that location 000A was the second byte of a BR instruction, but it seems that the computer thinks it is the next opcode. So off goes Q, and pretty soon the OUT 4 at 000B gets executed.

There is a moral to this lesson, besides what you learn about the new instructions. That is, the computer is the final judge of what your program is going to do. It does not matter much if you think that such and such a location in memory is part of a two-byte instruction; when the computer fetches the second byte during an opcode fetch then it is an opcode. As in religion, if you want to avoid being surprised at the end, you have to follow the rules laid down by the final judge.

But what good is a "branch never"? Not much, as such. However, do notice that the second byte has no effect on its execution (it never uses the branch address), so we can put anything we want there. In fact, if it is a one-byte instruction, then the 38 instruction effectively skips over it, so we call this instruction SKP for "skip". It does not do anything the BR instruction could not do, but it does it in one byte instead of two.

SKP Skip one byte 38
The one-byte instruction following the SKP opcode is skipped.

Program 3.10 is not set up to demonstrate the operation of long branches, but you can try the "long branch never". What would you expect to happen? In other words, what will be the next instruction after a C8 opcode? Try it. How is this different from 38=SKP? If Q does not go off, then obviously the REQ "instruction" in 000A is not being executed. Since you see "0C" on the hex display, you have to assume that the BR in 0009 is not being executed either, but that the OUT 4 in 000B is being executed. We call the C8 opcode a "Long Skip" because it skips two bytes.

LSKP Long Skip C8
Skip the two bytes following the opcode.

Let me quickly introduce you to the instruction that does nothing. Try the opcode "C4" in Program 3.10. What happens? Obviously it is not a skip or branch, because the branch in 0009-000A is executed. It does not turn Q off; it does not output anything that you can see. You will have to take my word for it that it does nothing else. We use it when we want the computer to kill some time, or we want to leave some space in a program for later additions, or we want to remove an instruction without moving the whole program back down.

NOP No Operation C4
This instruction does nothing, except take three major cycles to execute.

Let's try a new conditional branch. Enter the value "32" into Program 3.10. What happens? How is this different from the 38=SKP? If you agree that it does not seem to be different, turn on the M/P switch (so that the 32 in location 0008 will not be changed by subsequent entries), then try entering various other pairs of digits. What happens if you enter "00"? Can you find any other pair of digits that is distinctive? Convince yourself that this only works with the 32 opcode, and not with the 38 or 30 opcodes. Why did I tell you to turn on the M/P switch for this test? If you enter 00 with the M/P switch off, what happens to the program? Evidently, after an INP instruction in which the byte that was input is 00 the 32 opcode branches, but for all other bytes, the 32 opcode does not branch. If you go back and review the formal definition of the INP instruction, you will notice that it not only inputs to memory, but the same byte is also placed in the accumulator, D. When memory is protected, memory cannot be altered so only D is changed. The 32 opcode branches if D is exactly equal to zero, and not otherwise.

BZ a Branch on Zero 32 aa
Branch if D is zero; otherwise execute the next instruction in sequence (after the branch address).

If there is a Branch on Zero, is there also a Branch on Not Zero? What would be its opcode? Try it.

BNZ a Branch on Not Zero 3A aa
Branch if D is not exactly 00; otherwise take the next instruction in sequence (after the branch address).

If you think about it for a minute you will realize that there might also be a Long Branch on Zero and a Long Branch on Not Zero. As I said, Program 3.10 is not set up to test long branches, so you cannot use it to observe these instructions in action.

Exercise: Write a program to test LBZ and LBNZ. Convince yourself that these are three-byte instructions that can branch anywhere in memory.

LBZ aa Long Branch if Zero C2 aaaa
If the accumulator D is exactly zero, replace the contents of the Program Counter with the second and third bytes of this instruction; otherwise proceed to the next instruction in sequence.

LBNZ aa Long Branch if Not Zero CA aaaa
If the accumulator D is not exactly zero, replace the contents of the Program Counter with the second and third bytes of this instruction; otherwise proceed to the next instruction in sequence.

There are two more instructions which you can learn about using Program 3.10. This time run it once with M/P off and enter "C", "6". Notice that it behaves like an LSKP instruction. Now turn on M/P so you can feed the new opcode various data bytes. Did you try 00? What happened? Notice that opcode C6 skips when D is not zero; when D is exactly zero the instruction in 0009 is executed. Now try the opcode "CE". We call these "Conditional Skips". Notice that the condition being tested seems to be the reverse from the conditional branches. If you think about it, you will also see that C4=NOP is really a "Skip Never". Do you think the CC opcode would be a "Skip Always" instruction? What about C8=LSKP? Try CC. We will come back to this one.

LSZ Long Skip if Zero CE
Skip two bytes if D is zero; otherwise execute the next byte in sequence after the LSZ opcode.

LSNZ Long Skip if Not Zero C6
Skip two bytes if D is not zero; otherwise execute the next byte in sequence.

Let us look at one more condition before moving on to the register operations. Key in Program 3.11:

        ..  PROGRAM 3.11 -- TEST Q CONDITIONALS
        ..
0000 7A         REQ     .. Q OFF
0001 6C         INP 4   .. GET NEXT OPCODE
0002 7B         (SEQ)   .. MAYBE Q ON AGAIN
0003 C1         LBQ 10  .. **
0004 00
0005 0A
0006 64         OUT 4   .. NOTE NO BRANCH
0007 11         ,11
0008 30         BR  0   .. REPEAT
0009 00
000A 64         OUT 4   .. NOTE BRANCHED
000B 33         ,33
000C 30         BR  0   .. REPEAT
000D 00

First run this program with M/P on. What shows on the hex display? Notice that the program does not wait for or depend on EF4, so it is ignoring the "I" key. Now push the keys "7", "A", and flip the M/P switch off. What happened to the hex display? What is the difference between the program as it is now running and how it was running a few minutes ago? Flip the M/P switch back on and try entering other data: Is there any change? Clearly, the program is different depending on whether it is executing 7A=REQ or 7B=SEQ in location 0002. Obviously the new instruction in 0003-0005 depends on Q. As you probably guessed by now, it is a Long Branch if Q is on. Change location 0003 to hex C9. What do you think this will do to the program? Try it.

LBQ aa Long Branch if Q is on C1 aaaa
Branch to the location whose two byte address follows this opcode if Q is on; otherwise ignore the address and take the next instruction in sequence.

LBNQ aa Long Branch if Q is off C9 aaaa
Branch to the location whose two byte address follows this opcode if Q is off; otherwise ignore the address and take the next instruction in sequence.

As you might have guessed, there is also a Short Branch on Q. To test this, put a NOP=C4 into location 0003, then a hex 31 into location 0004. Leave the "0A" in location 0005; it is the second byte of the branch. Try it. Then change the 31 to hex 39. Notice that after entering 7B to the running program, the "31" opcode branches; after entering any other pair the "39" opcode branches.

BQ a Branch if Q is on 31 aa
Branch to the location whose one-byte address follows this opcode if Q is on; otherwise ignore the address and take the next instruction in sequence.

BNQ a Branch if Q is off 39 aa
Branch to the location whose one-byte address follows this opcode if Q is off; otherwise ignore the address and take the next instruction in sequence.

And of course, there is a "Skip if Q". To test this, replace 0003-0005 with the three bytes CD, 64, FF. Now when you run the program, if Q is on what do you see? When Q is off, what happens? Where is the OUT 4 instruction followed by "AA"? To help you answer this question, try switching the computer into Wait a few times. If your eye sees "FF" and "11" in rapid succession, what will it look like? Now change the CD in location 0003 to C5 and run the program again, alternately pushing 7B and 7A on the keys. Do you think you understand this skip instruction? If not, reset the computer and write down the contents of memory from 0000 to 0009. See if you can think like the computer as it would to execute the bytes in the program. Does that help?

LSQ Long Skip if Q is on CD
If Q is on, skip two bytes; otherwise execute the next byte after this opcode.

LSNQ Long Skip if Q is off C5
If Q is off, skip two bytes; otherwise execute the next byte after this opcode.

Now we have learned all of the 1802 instructions which do input or output; these are INP, OUT, B4, BN4 (also B1, B2, B3, etc.), SEQ and REQ. We have learned most of the conditional skips and branches: BZ, BNZ, LBZ, LBNZ, LSZ, LSNZ, BQ, LBQ, LSQ (and BNQ, etc.), and B4 etc. and all of the unconditional skips and branches: BR, LBR, SKP, and LSKP. And we know how to use NOP and IDL. If you look at the opcodes for these instructions, you will see that they include all the opcodes that begin with 6 except 60 and 68. Opcode 68 is not a defined instruction for the 1802 (though it is for the 1804, 1805, and 1806). We will discuss 60 in the next chapter. You will see that we have covered all the opcodes that begin with 3 except for 33 and 3B, and all those that begin with C except C3, C7, CB, CC, and CF. Opcode CC has to do with the interrupt system, which we will cover in Chapter 6. All the others are conditional skips and branches which test the DF or carry flag. Since I have not yet shown you how to set or clear the carry flag, you have no way to see how these conditionals work. For now, please accept that they look similar enough to the other conditional skips and branches that you do understand, so that when we get to DF, you will have no particular trouble with these instructions.

There is one form of input and output which your computer is capable of that does not use input or output instructions. We call it DMA or Direct Memory Access because it goes directly to memory without affecting the program (except for the time it takes to cycle memory). We will discuss this in some detail in Chapter 7.

[ << Chapter 2 ] [ Index ] [ Chapter 4 >> ]



* (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.)