Difference between revisions of "Introducing the Instruction Set Part 3"

From Intellivision Wiki
Jump to: navigation, search
(Overview)
Line 1: Line 1:
This segment of the tutorial introduces branches, particularly conditional branches and function calls.  This is Part 3 of a series.  If you haven't yes, you may wish to review at least [[Introducing the Instruction Set Part 1|Part 1]] and [[Introducing the Instruction Set Part 2|Part 2]].
 
  
= Overview =
 
 
Branches and jumps provide a way to guide the CPU through a sequence of code.  (Jump is pretty much a synonym for branch.)  Ordinarily, the CPU just keeps executing instructions in the order you wrote them.  It's like going down a to-do list.  For a simple example, suppose we wanted to add two numbers&mdash;call them A and B&mdash;together, and write the result to a third place&mdash;call it C.  The steps might look like this:<BR/><BR/>
 
<OL>
 
<LI>Read A into a R0
 
<LI>Add B to R0
 
<LI>Write R0 to C
 
</OL>
 
<BR />
 
These steps translate to the following instruction sequence:<BR/>
 
<CODE><pre>
 
    MVI  A,  R0    ; Read A into R0
 
    ADD  B,  R0    ; Add B to R0
 
    MVO  R0, C    ; Write R0 out to C
 
</pre></CODE>   
 
The CPU, when it encounters this sequence of instructions, will always execute them in this order.  That's useful by itself, but not useful enough to write interesting programs. <BR/> <BR/>
 
 
For example, suppose you wanted to fill the entire screen with blank characters.  The screen occupies 240 locations of memory starting at location $200.  You need to write a blank character (which happens to be the value $0000) to all 240 locations.  One way to do that would be to do this:<BR/><BR/>
 
<OL>
 
<LI>Set R0 to 0
 
<LI>Write R0 to $200
 
<LI>Write R0 to $201
 
<LI>Write R0 to $202
 
</OL>... 234 lines omitted ...<OL START=239>
 
<LI>Write R0 to $2FD
 
<LI>Write R0 to $2FE
 
<LI>Write R0 to $2FF
 
</OL>
 
<BR/>
 
That works, but it leads to very large and tedious code.  The simple way to write this in assembly code would be:<BR/><BR/>
 
<CODE><pre>
 
    CLRR R0
 
    MVO  R0,  $200
 
    MVO  R0,  $201
 
    MVO  R0,  $202
 
    ; ... 234 lines omitted ...
 
    MVO  R0,  $200
 
    MVO  R0,  $201
 
    MVO  R0,  $202
 
</pre></CODE>
 
That runs very fast, but it takes up a ton of ROM.  Also, it clears the screen only once.  What if you want to clear the screen many times?  You really don't want to copy this same code everywhere you need to clear the screen.  That's where branches come in.<BR/><BR/>
 
 
Branches tell the CPU to start executing at a different location, rather than barreling forward.  Unconditional branches and jumps tell the CPU to always jump to that location.  Conditional branches tell the CPU to jump to a new location <I>if some condition is true.</I>  These let you skip pieces of code, or repeat them a number of times.  Jumps to subroutine tell the CPU "go do this and come back when you're done."  The following sections explore these concepts a little more closely.<BR/><BR/>
 
 
= Unconditional Branches and Jumps =
 
 
Jump and Unconditional Branch instructions are like "goto" instructions found in higher-level languages.  They tell the CPU to immediately start executing code from somewhere else as opposed to executing the next instruction in sequence.  They're useful to tell the CPU to skip a section of code, or to repeat a section of code.  Be careful when repeating a block of code with an unconditional branch:  If there isn't a conditional branch somewhere in that block, it could end up running forever.
 
 
The following table lists the instructions:<br/><br/>
 
 
<TABLE BORDER>
 
<TR><TH>Mnemonic</TH><TH>Description                              </TH><TH>    Cycles    </TH><TH>        Size        </TH></TR>
 
<TR><TH> [[B]]  </TH><TD>Branch to label                          </TD><TD align=center> 9</TD><TD align=center>2 words</TD></TR>
 
<TR><TH> [[J]]  </TH><TD>Jump to label                            </TD><TD align=center>12</TD><TD align=center>3 words</TD></TR>
 
<TR><TH> [[JD]] </TH><TD>Jump to label while disabling interrupts </TD><TD align=center>12</TD><TD align=center>3 words</TD></TR>
 
<TR><TH> [[JE]] </TH><TD>Jump to label while enabling interrupts  </TD><TD align=center>12</TD><TD align=center>3 words</TD></TR>
 
</TABLE>
 
<br/>
 
As you can see, the primary difference between branches and jumps is that branches are smaller and faster.  Branches encode their "target address," the address being jumped to, as a [[relative displacement]] to the current address.  Jumps, on the other hand, store the actual address of the target.  In most cases, especially in a 16-bit ROM, there are few reasons to use a [[J]] instruction, although the combination instructions, [[JD]] and [[JE]] can be useful.
 
<br/><br/>
 
There is also a pseudo-instruction, [[JR]], that allows "jumping to a location held in a register."  It is really a pseudonym for "[[MOVR]] Rx, R7".  Because it is a MOVR instruction, it will modify the [[Sign Flag]] and [[Zero Flag]], which may be confusing if you're not expecting it.  Otherwise, it is an efficient method for jumping to an address held in an register, such as when returning from a CALL.
 
<br/><br/>
 
 
= Conditional Branches =
 
 
Conditional branches are similar to "<CODE>if ... goto</CODE>" type constructs found in other languages.  They tell the CPU to start executing at another location if a particular condition is true.  This allows us to build "<CODE>if-then-else</CODE>" types of statements, as well as "<CODE>for</CODE>" and "<CODE>while</CODE>" loops.<br/><br/>
 
 
The [[CP1610]] has a rich set of conditional [[Branch|branch]] instructions.  They work by looking at the CPU's flag bits to decide when to branch.  Instructions like [[CMP]] and [[DECR]] set these flags, making it easy to write those if/else statements and for/while loops.  Even fancier uses are possible with some creativity.<br/><br/>
 
 
The following table summarizes the conditional branches.<br/><br/>
 
 
<TABLE BORDER=1 CELLPADDING=3>
 
<TR><TH>Mnemonic</TH><TH>Name</TH><TH>Branch taken when...</TH><TH>Mnemonic</TH><TH>Name</TH><TH>Branch taken when...</TH></TR>
 
<TR><TH>&nbsp;&nbsp;[[BC]]&nbsp;&nbsp;</TH><TD>Branch on Carry</TD><TD><CODE> C = 1            </CODE></TD><TH>&nbsp;&nbsp;[[BNC]]&nbsp;&nbsp;</TH><TD>Branch on No Carry</TD><TD><CODE> C = 0          </CODE></TD></TR>
 
<TR><TH>&nbsp;&nbsp;[[BOV]]&nbsp;&nbsp;</TH><TD>Branch on OVerflow</TD><TD><CODE> OV = 1      </CODE></TD><TH>&nbsp;&nbsp;[[BNOV]]&nbsp;&nbsp;</TH><TD>Branch on No OVerflow</TD><TD><CODE> OV = 0          </CODE></TD></TR>
 
<TR><TH>&nbsp;&nbsp;[[BPL]]&nbsp;&nbsp;</TH><TD>Branch if PLus</TD><TD><CODE> S = 0            </CODE></TD><TH>&nbsp;&nbsp;[[BMI]]&nbsp;&nbsp;</TH><TD>Branch on MInus</TD><TD><CODE> S = 1          </CODE></TD></TR>
 
<TR><TH>&nbsp;&nbsp;[[BEQ]]&nbsp;&nbsp;</TH><TD>Branch if EQual</TD><TD ROWSPAN=2><CODE> Z = 1 </CODE></TD><TH>&nbsp;&nbsp;[[BNEQ]]&nbsp;&nbsp;</TH><TD>Branch on Not Equal</TD><TD ROWSPAN=2><CODE> Z = 0          </CODE></TD></TR>
 
<TR><TH>&nbsp;&nbsp;[[BZE]]&nbsp;&nbsp;</TH><TD>Branch on ZEro</TD><TH>&nbsp;&nbsp;[[BNZE]]&nbsp;&nbsp;</TH><TD>Branch on Not ZEro</tD></TR>
 
<TR><TH>&nbsp;&nbsp;[[BLT]]&nbsp;&nbsp;</TH><TD>Branch if Less Than</TD><TD ROWSPAN=2><CODE> S <> OV          </CODE></TD><TH>&nbsp;&nbsp;[[BGE]]&nbsp;&nbsp;</TH><TD>Branch if Greater than or Equal</TD><TD ROWSPAN=2><CODE> S = OV          </CODE></TD></TR>
 
<TR><TH>&nbsp;&nbsp;[[BNGE]]&nbsp;&nbsp;</TH><TD>Branch if Not Greater than or Equal</TD><TH>&nbsp;&nbsp;[[BNLT]]&nbsp;&nbsp;</TH><TD>Branch if Not Less Than</TD></TR>
 
<TR><TH>&nbsp;&nbsp;[[BLE]]&nbsp;&nbsp;</TH><TD>Branch if Less than or Equal</TD><TD ROWSPAN=2><CODE> Z = 1 OR S <> OV  </CODE></TD><TH>&nbsp;&nbsp;[[BGT]]&nbsp;&nbsp;</TH><TD>Branch if Greater Than</TD><TD ROWSPAN=2><CODE> Z = 0 AND S = OV </CODE></TD></TR>
 
<TR><TH>&nbsp;&nbsp;[[BNGT]]&nbsp;&nbsp;</TH><TD>Branch if Not Greather Than</TD><TH>&nbsp;&nbsp;[[BNLE]]&nbsp;&nbsp;</TH><TD>Branch if Not Less than or Equal</TD></TR>
 
<TR><TH>&nbsp;&nbsp;[[BUSC]]&nbsp;&nbsp;</TH><TD>Branch on Unequal Sign and Carry</TD><TD><CODE> S <> C          </CODE></TD><TH>&nbsp;&nbsp;[[BESC]]&nbsp;&nbsp;</TH><TD>Branch on Equal Sign and Carry</TD><TD><CODE> S = C          </CODE></TD></TR>
 
</TABLE>
 
<br/>
 
Conditional branches are most often used with numeric comparisons, or as the branch at the end of a loop.  The following sections illustrate how numeric comparisons, increment and decrement work in concert with branches.
 
<br/><br/>
 
Conditional branches can also be paired with other instructions that manipulate the flags.  For instance, shift instructions, as described in [[Introducing the Instruction Set Part 4|Part 4]] update sign, zero, carry and overflow flags depending the operation performed.  This can lead to interesting and creative combinations of shifts and branches.
 
<br/><br/>
 
Another use of flags and branches is to pass status information in CPU flags (such as the [[Carry Flag]]) and then act on that information later.  The [[SETC]] and [[CLRC]] instructions make it easy to manipulate the Carry Flag to pass this status information around.
 
<br/><br/>
 
== Signed Comparisons ==
 
 
The following branches are particularly useful when comparing signed numbers.  These are the conditional branches you will use most when writing "<CODE>if-then-else</CODE>" statements, since most numbers are signed, or can be treated as signed.
 
<BR/><BR/>
 
<TABLE BORDER=1 CELLPADDING=3>
 
<TR><TH COLSPAN=2>Mnemonic</TH><TH>Branch taken when...</TH><TH COLSPAN=2>Mnemonic</TH><TH>Branch taken when...</TH></TR>
 
<TR><TH>&nbsp;&nbsp;[[BEQ]]&nbsp;&nbsp;</TH><TH>&nbsp;&nbsp;[[BZE]]&nbsp;&nbsp;</TH><TD><CODE> Z = 1            </CODE></TD><TH>&nbsp;&nbsp;[[BNEQ]]&nbsp;&nbsp;</TH><TH>&nbsp;&nbsp;[[BNZE]]&nbsp;&nbsp;</TH><TD><CODE> Z = 0          </CODE></TD></TR>
 
<TR><TH>&nbsp;&nbsp;[[BLT]]&nbsp;&nbsp;</TH><TH>&nbsp;&nbsp;[[BNGE]]&nbsp;&nbsp;</TH><TD><CODE> S <> OV          </CODE></TD><TH>&nbsp;&nbsp;[[BGE]]&nbsp;&nbsp;</TH><TH>&nbsp;&nbsp;[[BNLT]]&nbsp;&nbsp;</TH><TD><CODE> S = OV          </CODE></TD></TR>
 
<TR><TH>&nbsp;&nbsp;[[BLE]]&nbsp;&nbsp;</TH><TH>&nbsp;&nbsp;[[BNGT]]&nbsp;&nbsp;</TH><TD><CODE> Z = 1 OR S <> OV  </CODE></TD><TH>&nbsp;&nbsp;[[BGT]]&nbsp;&nbsp;</TH><TH>&nbsp;&nbsp;[[BNLE]]&nbsp;&nbsp;</TH><TD><CODE> Z = 0 AND S = OV </CODE></TD></TR>
 
<TR><TH COLSPAN=2>&nbsp;&nbsp;[[BOV]]&nbsp;&nbsp;</TH><TD><CODE> OV = 1            </CODE></TD><TH COLSPAN=2>&nbsp;&nbsp;[[BNOV]]&nbsp;&nbsp;</TH><TD><CODE> OV = 0          </CODE></TD></TR>
 
</TABLE>
 
<BR/>
 
Note:  One pair of branches shown above&mdash;[[BOV]] and [[BNOV]]&mdash;are useful in this context only for detecting overflow and little else.  I included them here for completeness.  These actually find more use paired up with shift instructions.  Those are described [[Introducing the Instruction Set Part 4|Part 4]] of this tutorial.
 
 
=== How Signed Arithmetic Works With Conditional Branches ===
 
The next couple of paragraphs describe how these branches work with compares.  Most of the time, you do not need to think about these details when writing programs, so feel free to skim it for now and come back to it later.<BR/><BR/>
 
The compare instruction compares two numbers by subtracting them, and then setting the flags based on the result.  This provides a lot of information about the relative values of the two numbers, as this table shows (ignoring overflow):
 
<BR/><BR/>
 
<TABLE BORDER=1 CELLPADDING=10>
 
<TR><TH>If this is true...</TH><TH>...then this also must be true...</TH><TH COLSPAN=2>...which implies the flags get set as follows<BR/>(if you ignore overflow).</TH></TR>
 
<TR><TD ALIGN=center><CODE>x = y</CODE></TD><TD ALIGN=center><CODE>x - y = 0</cODE></TD><TD ALIGN=center>S = 0</TD><TD ALIGN=center>Z = 1</TD></TR>
 
<TR><TD ALIGN=center><CODE>x &lt; y</CODE></TD><TD ALIGN=center><CODE>x - y &lt; 0</cODE></TD><TD ALIGN=center>S = 1</TD><TD ALIGN=center>Z = 0</TD></TR>
 
<TR><TD ALIGN=center><CODE>x &gt; y</CODE></TD><TD ALIGN=center><CODE>x - y &gt; 0</cODE></TD><TD ALIGN=center>S = 0</TD><TD ALIGN=center>Z = 0</TD></TR>
 
</TABLE>
 
<BR/>
 
That is, we can determine whether two numbers are equal or not by looking at the [[Zero Flag]].  We can determine if one's less than the other by looking at the [[Sign Flag]].  At least, that would be true if there was no such thing as overflow. 
 
<BR/><BR/>
 
The CP1610 can only work with 16 bits at a time.  If you try to subtract two numbers whose values are very far apart, such as, in the worst case 32767 - (-32768), you will trigger an overflow, because the results don't fit in 16 bits.  Overflow causes the sign of the result to be the opposite of what you would get if no overflow had occurred.  The branches take this into account and look at the overflow bit in addition to the sign bit to decide whether one number is greater than or less than another.  The following table illustrates the relationships both with and without overflow.
 
<BR/><BR/>
 
<TABLE BORDER=1 CELLPADDING=10>
 
<TR><TH>If this is true...</TH><TH COLSPAN=3>...then the flags get set as follows...</TH><TH>...which matches these branches.</TH></TR>
 
<TR><TD ALIGN=center><CODE>x = y</CODE></TD><TD ALIGN=center>S = 0</TD><TD ALIGN=center>Z = 1</TD><TD ALIGN=center>OV = 0</TD><TD ALIGN=center>BEQ, BGE, BLE</TD></TR>
 
<TR><TD ALIGN=center ROWSPAN=2><CODE>x &lt; y</CODE></TD><TD ALIGN=center>S = 1</TD><TD ALIGN=center>Z = 0</TD><TD ALIGN=center>OV = 0</TD><TD ALIGN=center ROWSPAN=2>BNEQ, BLT, BLE</TD></TR>
 
<TR><TD ALIGN=center>S = 0</TD><TD ALIGN=center>Z = 0</TD><TD ALIGN=center>OV = 1</TD></TR>
 
<TR><TD ALIGN=center ROWSPAN=2><CODE>x &gt; y</CODE></TD><TD ALIGN=center>S = 0</TD><TD ALIGN=center>Z = 0</TD><TD ALIGN=center>OV = 0</TD><TD ALIGN=center ROWSPAN=2>BNEQ, BGT, BGE</TD></TR>
 
<TR><TD ALIGN=center>S = 1</TD><TD ALIGN=center>Z = 0</TD><TD ALIGN=center>OV = 1</TD></TR>
 
</TABLE>
 
<BR/>
 
As you can see, the flags and the branches cooperate quite nicely.
 
=== Gotchas With the CP1610 Compare Instruction ===
 
The syntax for the CP1610's [[CMP|compare]] instruction can confuse things slightly, since it does a "subtract from".  Consider the following example: 
 
<CODE>
 
    [[MVII]]    #1, R0  ; R0 = 1
 
    [[MVII]]    #2, R1  ; R1 = 2
 
    [[CMPR]]    R0, R1  ; Subtract R0 from R1 to set flags
 
    [[BLT]]    label  ; Is this taken?
 
</CODE>
 
This computes "R1 - R0", not "R0 - R1".  It compares R0 to R1 by subtracting R0 from R1.  In this example, that leaves S=0 and OV=0.  R1 is <I>not</I> less than R0, so the branch is <I>not</I> taken.  In other words, to determine if a given branch is taken, you have to read right-to-left.  "Is R1 less than R0?"  In this case, the answer is no, so the branch is not taken.
 
<BR/><BR/>
 
 
== Unsigned Comparisons ==
 
 
These branches are useful when comparing unsigned numbers.  Most often, these get used with pointers into your game ROM, or with [[fixed point]] values such as screen coordinates.<br/><br/>
 
 
<TABLE BORDER=1 CELLPADDING=3>
 
<TR><TH COLSPAN=2>Mnemonic</TH><TH>Branch taken when...</TH><TH COLSPAN=2>Mnemonic</TH><TH>Branch taken when...</TH></TR>
 
<TR><TH COLSPAN=2>&nbsp;&nbsp;[[BC]]&nbsp;&nbsp;</TH><TD Align=center><CODE> C = 1            </CODE></TD><TH COLSPAN=2>&nbsp;&nbsp;[[BNC]]&nbsp;&nbsp;</TH><TD align=center><CODE> C = 0          </CODE></TD></TR>
 
<TR><TH>&nbsp;&nbsp;[[BEQ]]&nbsp;&nbsp;</TH><TH>&nbsp;&nbsp;[[BZE]]&nbsp;&nbsp;</TH><TD align=center><CODE> Z = 1            </CODE></TD><TH>&nbsp;&nbsp;[[BNEQ]]&nbsp;&nbsp;</TH><TH>&nbsp;&nbsp;[[BNZE]]&nbsp;&nbsp;</TH><TD align=center><CODE> Z = 0          </CODE></TD></TR>
 
</TABLE>
 
<BR/>
 
The unsigned comparisons require some additional explanation to be useful.  After comparing two unsigned numbers, the [[BC]] instruction will branch if the second number is greater than or equal to the first.  The [[BC]] instruction will branch if the second number is smaller than the first.  The CP1610 does not offer unsigned equivalents for "branch if greater than" or "branch if less than or equal."  You can get similar effects, though, by combining [[BC]] and [[BNC]] with [[BEQ]] or [[BNEQ]] to separate out the "equals", "greater-than" and "less-than" cases.
 
 
=== How Unsigned Arithmetic Works With Conditional Branches ===
 
The following couple of paragraphs explain how [[BC]] and [[BNC]] work in concert with other instructions to provide unsigned comparisons.  Feel free to skim this for now and come back to it later.<BR/><BR/>
 
 
Unsigned arithmetic is actually pretty similar to signed arithmetic, except that there isn't a sign bit.  Rather, all the interesting information ends up in the carry bit.  Read "How Signed Arithmetic Works With Conditional Branches" above to get the basics. 
 
 
As mentioned before, the compare instruction compares two numbers by subtracting them and setting the flags.  When subtracting two unsigned numbers, the Carry flag doubles as a "do not borrow" flag.  With that in mind (and handwaving just <I>how</I> carry functions that way for now), we have:<BR/><BR/>
 
<TABLE BORDER=1 CELLPADDING=10>
 
<TR><TH>If this is true...</TH><TH>...then this also must be true...</TH><TH COLSPAN=2>...which implies the flags get set as follows</TH></TR>
 
<TR><TD ALIGN=center><CODE>x = y</CODE></TD><TD ALIGN=center><CODE>x - y = 0</cODE></TD><TD ALIGN=center>C = 1 (no borrow)</TD><TD ALIGN=center>Z = 1</TD></TR>
 
<TR><TD ALIGN=center><CODE>x &gt; y</CODE></TD><TD ALIGN=center><CODE>x - y &gt; 0</cODE></TD><TD ALIGN=center>C = 1 (no borrow)</TD><TD ALIGN=center>Z = 0</TD></TR>
 
<TR><TD ALIGN=center><CODE>x &lt; y</CODE></TD><TD ALIGN=center><CODE>x - y &lt; 0</cODE></TD><TD ALIGN=center>C = 0 (borrow needed)</TD><TD ALIGN=center>Z = 0</TD></TR>
 
</TABLE>
 
<BR/>
 
As you can see, the carry flag gets set whenever 'x' is greater than or equal to 'y'.  The carry flag is clear whenever 'x' is less than 'y'.  This is why [[BC]] works as the equivalent of an unsigned "branch if greater than or equal," and [[BNC]] works as an unsigned version of "branch if less than."<BR/><BR/>
 
 
== Sign/Zero Comparisons ==
 
 
Common looping instructions, such as [[DECR]] and [[INCR]] only modify the [[Sign Flag|sign]] and [[Zero Flag|zero]] flags without updating the [[Carry Flag|carry]] or [[Overflow Flag|overflow]] flags.  These are best used with the following branches:<BR/><BR/>
 
 
<TABLE BORDER=1 CELLPADDING=3>
 
<TR><TH COLSPAN=2>Mnemonic</TH><TH>Branch taken when...</TH><TH COLSPAN=2>Mnemonic</TH><TH>Branch taken when...</TH></TR>
 
<TR><TH COLSPAN=2>&nbsp;&nbsp;[[BPL]]&nbsp;&nbsp;</TH><TD align=center><CODE> S = 0            </CODE></TD><TH COLSPAN=2>&nbsp;&nbsp;[[BMI]]&nbsp;&nbsp;</TH><TD align=center><CODE> S = 1          </CODE></TD></TR>
 
<TR><TH>&nbsp;&nbsp;[[BEQ]]&nbsp;&nbsp;</TH><TH>&nbsp;&nbsp;[[BZE]]&nbsp;&nbsp;</TH><TD align=center><CODE> Z = 1            </CODE></TD><TH>&nbsp;&nbsp;[[BNEQ]]&nbsp;&nbsp;</TH><TH>&nbsp;&nbsp;[[BNZE]]&nbsp;&nbsp;</TH><TD align=center><CODE> Z = 0          </CODE></TD></TR>
 
</TABLE>
 
<BR/>
 
These will be explored in more detail in the "looping" section below.
 
 
== If-Then and If-Then-Else ==
 
 
== Looping ==
 
 
= Function Calls =
 
 
<!-- JSR/CALL instruction table -->
 
 
== Simple Call/Return ==
 
 
== Nested Call/Return ==
 
 
== Passing Arguments via Return Address ==
 
 
 
= Indirect Branches and Jump Tables =
 
 
<BLOCKQUOTE>"It was a 'Jump to Conclusions' mat. You see, it would be this mat that you would put on the floor... and would have different <B>conclusions</B> written on it that you could <B>jump to.</B>" -- Tom Smykowski, Office Space</BLOCKQUOTE>
 
 
== Indirect Branching:  "Jump Vectors" ==
 
 
<!-- storing an address to jump to in memory, such as an ISR vector -->
 
 
== Simple Jump Tables ==
 
<!-- Using MVI@ to read one of several branch targets -->
 
 
== Adding to the Program Counter ==
 
 
 
= Moving On =
 
 
At this point, you may wish to move along to the last part, or review earlier parts of this tutorial:
 
 
* [[Introducing the Instruction Set Part 1]]:  The CPU, Memory and Registers; Primary Instructions and Addressing Modes
 
* [[Introducing the Instruction Set Part 2]]:  Single Register and Implied Operand Instructions
 
<!--* [[Introducing the Instruction Set Part 3]]:  Branches, Conditional Branches and Calls-->
 
* [[Introducing the Instruction Set Part 4]]:  Shift and Rotate Instructions
 
 
Or, you can return to the [[Programming Tutorials]] index.
 

Revision as of 19:19, 3 November 2007