( 22 )
Review
Let's review the most important programming concepts that were
introduced via the RPN calculator:
- We introduced the concept of a program which is just
a sequence of statements.
- We introduced statements which are textual
representations of computer operations. Statements have syntax rules
and are built upon the machine's instruction set.
- We introduced the instruction set which is the list of
primitives (most basic operations) of a programmable device.
For the RPN calculator "STO" is a member of the instruction set and
"STO 5" is a legal statement built upon the STO primitive.
- We introduced the stack. A stack works the same as the
spring-loaded stack of trays you find in a school cafeteria: students
can only remove the top tray and the kitchen staff can only add newly
washed trays to the top of the stack. The RPN calculator has a 4 deep
operand stack. All operands which are to be used for computations must
first make it into the stack before they can be operated upon. New
numbers can only enter the stack thru the X location. All one-operand
functions use the number in the X stack location for their
operand. All two-operand functions employ the numbers in the X and Y
locations.
- We introduced the distinction between data memory and
program memory. The RPN calculator has exactly 98 program
memory locations and exactly 30 data memory locations. Program memory
holds operation codes which represent the operations the
calculator can perform. Data memory holds (duh) data which are the
operands that operations act upon. You cannot operate upon things
pulled from program memory and you cannot place statements in data memory.
- We introduced one-operand functions and
two-operand functions. An example of a one-operand
function is 10^x and an example of a two-operand function is
y^x.
- We introduced postfix notation via a
reverse Polish notation calculator.
The advantage of postfix notation is that the operation can be performed
as soon as you specify the operation. That is, all necessary operands
will already be available.
- We introduced branching which has the two types
unconditional branching and conditional branching.
The GTO n statement results in an unconditional branch to the label n.
The x>0 statement paired with a GTO n statement forms a
conditional branch. Conditional and unconditional branch
statements can cause a program to loop which means it
repeatedly executes the same section of the program. It is looping that
allows a 10 statement program to produce an unlimited number of results.
Conditional branches are used to exit from the loop when a certain result
has been achieved. When a loop has a defective exit it becomes an
infinite loop which is one of the first program bugs most
programmers discover.
- We introduced subroutines which become function calls in
higher-level languages. A subroutine is used to hold a fragment of code
that is useful at multiple times within a program. Hence by writing
these statements only one time and jumping to them when necessary you
save typing and achieve a bug free program faster.
- We introduced debugging via single stepping
and program tracing. Single stepping is where you command
the computer to execute only the next instruction. Tracing is where
the program creates a record of its activities so the designer can
observe the flow of his program (that is, the path made through all the
branches). Single stepping is obviously very slow while tracing allows
the program to run at close to full speed (a little performance is lost
due to the need to create the log file).
- We introduced indirection. When employing
direct access to data memory you specify the address of a
data memory location that holds the data you want to operate upon. When
employing indirect access to data memory you specify the
address of a data memory location that holds the address of a different
data memory location that holds the data you want to operate upon.
Indirection obviously takes more effort and hence runs slower, but it buys
flexibility. A common situation where indirect addressing is useful
concerns the difference between compile time and
run time. Compile time refers to the time when a program
is created. Run time refers to the time (possibly years later) when
the program is executed. The use of direct addressing requires that
the data memory location be known at compile time, since this address
is hard coded (that is, fixed) in the statements of the
program. But sometimes the location (address) of the needed data does
not become known until run time. For example, the address may depend
upon the results of earlier calculations the program made at run time.
In this case indirect addressing allows the data memory address to be
left unspecified at compile time.
- We introduced addressing modes. The RPN calculator offers
the programmer the choice of only 2 addressing modes: direct and indirect
addressing. The 8051 microprocessor we will study next offers 4 choices
of addressing modes. The Intel Pentium III microprocessor used in many
PCs offers 9 addressing modes. You choose an addressing mode for every
operation when you program in a low level language such as assembly. The
compiler selects an addressing mode to accomplish each of
the operations you request when you program in a high level language such
as C, C++, or Java.