They say the best way to learn is to learn by example so in this section we'l take a look at a simple program that counts from 0 to 10 over and over again:
# # This is a program that increases the contents of the # variable "counter" from 0 to 10. When it has reached 10 it # is reset to 0 again. # start: move 0,counter # initialize counter loop: add 1,counter # add 1 to counter move counter,tmp # copy counter to tmp sub 10,tmp # subtract 10 from tmp jne tmp,%loop # if tmp is not 0, jump to loop jmp %start # jump to the first instruction
I will now go though each instruction in this program, explaining what happens and hopefully even why it happens.
First of all, it's important to understand the concept of "symbol values". Every symbol has a value. Whenever a symbol appears in an instruction the value of this symbol is stored in the extension word of this instruction. This value is then usually used to refer to a data memory location but it can also be used to specify a location in program memory.
When I talk about "memory locations" I always talk about locations in data memory. As was said earlier, there are no commands dealing directly with program memory, so its hardly ever mentioned.
The first 5 lines are comments. Comments start with a # and extend to the end of the line. The first non-commented line is the line:
start:
This is a label definition. What it does is that it sets the
value of the symbol to the PC of the next
instruction. Since the next instruction is the first line
of the program the value for the symbol start
will
be 0.
The next instruction is:
move 0,counter
This instruction stores the value 0 in the variable
counter
. Or, to be more precise, it stores the
value 0 into the memory location pointed to by the value of
the symbol counter
.
Now, all of this sounds nice, but what really is the value of
the symbol counter
? The answer is that during
assembly, the assembler finds all symbols that have not
receieved a value in some other way (i.e. through a label
definition like the one we saw on the previous line), allocates
one word of memory for each symbol and assigns the address to a
memory location to each symbol. We do not set the symbol value
of counter
in our program so counter
's
symbol value will indeed be that of the address to an unused
memory location. Because of this we can simply take an unused
name whenever we need a storage location and the assembler will
automatically allocate it for us.
The next instruction is just another label definition. Since it preceedes the second instruction in the program it will get the symbol value 1.
The next instruction:
add 1,counter
adds the value 1 to the storage location pointed to by
counter
. The next instruction:
move counter,tmp
Here, we move the contents in the memory location pointed to
by the symbol value of counter
to the
contents of the memory location pointed to by the value of
tmp
. tmp
is a symbol just like
counter
so its symbol value is assigned by the
assembler just like counter
's was.
The instruction:
sub 10,tmp
subtracts 10 from the storage location pointed to by
tmp
. The next instruction:
jne tmp,%loop
This means that the CPU should jump to the program memory
location that is the symbol value of loop
if the
memory location pointed to by tmp
is not 0.
The %-sign deserves some explanation. If we had written
jne tmp,loop
it wouldn't work, because the CPU would make a lookup in the
memory location pointed to by loop
and then jump to
that location in program memory. The %-sign prevents
the memory lookup and uses the symbol value instead.
The last instruction:
jmp %start
This instruction jumps to the first line in the program so that it starts counting again.