Although our program doesn’t do very much, it only takes around 1 ^s to implement each instruction. A million unimpressive operations each second can amount to a great deal! Nevertheless, it hardly rates highly in the annals of software, so we will wrap up our introduction to computing by looking at some slightly more sophisticated examples.
Writing a program is somewhat akin to building a house. Given a known range of building materials, the builder simply puts these together in the right order. Of course there are tremendous skills in all this; poor building techniques lead to houses that leak, are drafty and eventually may fall down!
It is possible to design a house at the same time as it is being built. Whilst this may be quite feasible for a log cabin, it is likely that the final result will not remain rain proof very long, nor will it be economical, maintainable, ergonomic or very pretty. It is rather better to employ an architect to design the edifice before building commences. Such a design is at an abstract level, although it is better if the designer is aware of the technical and economic properties of the available building materials.
Unfortunately much programming is of the ‘on the hoof’ variety, with little thought of any higher-level design. In the software arena this means devising strategies and designing data structures in memory. Again, it is better if the design algorithms keep in mind the materials of which the program will be built; in our case the machine instructions.
At the level of our examples in this topic, it will be this coding (building) task we will be mostly concerned with. Later topics will cover more advanced structures which will help this process, and we will get more practice at devising strategies and data structures.
In order to code software we must have a knowledge of the register architecture of the computer/microcontroller and of the individual instructions. Figure 3.5 shows the programming model we will use for our exercises. This shows all registers that can be ‘got at’ by the programmer.
I have added three registers to the previous complement that actually are part of the Data store rather than the CPU but have a special significance for the programmer. File 0 and File 4 are a pair of Address registers working in tandem to point to an object in memory, as described further on in Fig. 3.6. The Status Register6 STATUS comprises two bits in File 3 that are used to tell the software something about the outcome from an instruction. Thus the C flag (bit0 in File 3) primarily holds the Carry out from the last Addition operation. For instance (in decimal) 5 + 2 = 7C0; 5 + 9 = 4C1. It also functions as the complement of the Borrow out from a Subtraction operation. For example 5 – 2 = 3B1; 5 – 9 = 6B0. The Z flag (bit 2 in File 3) is set if the result of the last operation is zero.
Table 3.1 shows all the instructions supported by the BASIC computer. Before looking at these, let us discuss the concept of the address mode. Most instructions act on data, which may be in internal CPU registers or out in the Data store. Thus the location of such operands must be part of the instruction. It isn’t sufficient to simply state clr – Clear what? There are different ways of specifying the operand location. These are known as address modes.
Table 3.1: Our BASIC computer’s instruction set.
Inherent
A few instructions, not shown in Table 3.1, do not explicitly refer to any location. For example return for RETURN from subroutine..
Register Direct
Here the operand is specified to be in the Working register. For example:
Most instructions specify at least one operand should be in W. In many cases W can be both a source and the destination operand. For instance:
where W initially holds one of the two source datum bytes, and ends up holding the outcome datum.
Literal
This address mode is used to specify an operand which is constant data rather than a location. For example:
Only special literal instructions are used with this type of data, such as movlw and sublw. The destination of this type of instruction is always W. The sublw instruction sometimes causes confusion as it actually takes away the contents of W from the literal byte and not vice versa. Thus sublw 1 does not subtract one from the contents of W (i.e. decrement W) but 1 – W. To decrement the contents of W use addlw -1 (i.e. addlw 0FFh). Note the use of the # symbol in the rtl description to denote that the following number is constant data.
A few instructions can test or modify a single bit in a File. For instance:
in which Operand B is the fixed literal 6, specifying the bit position in Operand A’s specified File.
In both kinds of literal instruction the constant is encoded as part of the instruction word. In the former, eight bits of the 14-bit word is used, and in the latter three bits.
File Direct
Here the totally fixed file address of the operand, either source or/and destination is directly specified. For example:
clears the byte out at File 20h.
In many cases the same file can be both source and destination. Thus:
as opposed to the Working register:
which uses File Direct addressing for Operand A and Register Direct for Operand B.
The main characteristic of this address mode is that the location of the operand is fixed as an integral part of the program, and thus cannot be changed as execution progresses. Although directly specifying its address may seem to be the obvious way to locate an object in the Data store, in some situations this technique is rather inflexible.
Suppose we wished to clear all file registers from 0Ch through to 3Fh in the File store, say to hold an array of 52 byte elements. The obvious way to do this is shown in Program 3.1, which uses a clrf instruction for each byte. Although it works, it is rather inefficient, and the mind boggles if you wanted to clear, say, a 1 Kbyte File store. There has got to be a better way!
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |