I am an old computer programmer. I hail from a time before the C language was created. I have always liked assembly languages and enjoy squeezing the most from a computer. I have never warmed up to the syntax of the C language so when I started to look at programming various Microchip PIC processors, I approached them as an assembly language programmer.
Initially, I played with some of the smaller models in the PIC12 and PIC16 groups. In the past few years, I have moved primarily to the PIC18 series.
I cut my programming teeth on early minicomputers such as the DEC PDP-8. Those computers had a single accumulator register. The instruction set was simple and so was the syntax. One of the features of the PIC architecture that appeals to me is that it is a single accumulator machine. The W register is the accumulator of the PIC processor.
The early single accumulator machines almost always stored the results of a computational instruction into the accumulator. There was a single instruction to store the accumulator's contents into memory. The more modern machines have expanded on this model quite a bit. The arithmetic and logic unit (ALU) implement more kinds of operations and the results can be directed to a memory cell about as easily as to the accumulator itself.
One common theme in assembly languages is that one command in the source code results in one command in the machine's binary language. The assembly language is, command-for-command, a direct symbolic representation of every instruction the hardware will execute.
When I started to learn the assembly language for the various PIC models, there were two things that particularly annoyed me. The first is that I find that the commands do not have any kind of common philosophy in their design. Learning a few commands does not give one much clue as to how additional commands might be spelled.
The second issue was that the designers were apparently guided by how the hardware worked more than by what the commands accomplished. For example, the command ADDWF can be used to add the contents of the W register to the contents of a memory cell or it can be used to add the contents of a memory cell to the contents of the W register. Of course, both operations use the same addition circuitry. It is just that the output of that addition circuitry is directed to the memory cell or to the W register. Hence, we have two different instructions that are written exactly the same in assembly language except one is followed by ",F" while the other is followed by ",W" to indicate how the result should be directed.
In other words, these two operations are assigned the same instruction in the language because they use the same hardware:
MemoryCell = MemoryCell + W
W = W + MemoryCell
Given this approach, one would assume that the instruction for move data from W to a memory cell would look like the instruction to move data from a memory cell to W except that one would have ",W" while the other would have ",F" but that is not the case.
For me, there were many more issues but I will not detail them here. Suffice it to say that I grew frustrated with trying to learn and use this assembly language.
I decided to write some macros to define at least some alternate instructions. I first did this while using the PIC16F628A and I was generally happy with that limited approach. I was still struggling with finding a way to describe the wide variety of operations using some consistent approach.
Later, I moved more toward the PIC18F2550. There, things grew even worse in some ways. Some memory cells can be accessed either in the usual way (with the benefit of a setting in a Bank Select Register (BSR)) or more directly using Access Memory addressing mode and avoiding the need to have the BSR set for the operand's bank. The user indicates the desired method by adding or not adding ",A" to an instruction in the assembly language syntax. However, one might ask why a programmer would ever want to use the BSR mode if the Access Memory mode is available. The speed remains the same. The size of the instruction stays the same. The outcome stays the same. It would seem that the assembler should be able to automatically code an instruction using the Access Memory mode if it is available for a given instruction, thus eliminating altogether the task of typing ",A" on instructions where it can be used.
The macro file seemed to be the place to try to take care of this, but I was still frustrated over not having a consistent approach to a set of mnemonics for the PIC instruction set.
As an exercise, I was writing on paper some definitions of what the various instructions did. For example, just like we saw before:
MemoryCell = MemoryCell + W
W = W + MemoryCell
There was no way to include operators like "=" and "+" in an instruction but that seemed like what was needed. Besides, in the PIC18 instruction set, there are two different kinds of adding; the usual kind and then "adding with carry". I remembered back years ago to the instruction set of the DEC PDP-11. It used ADD for simple adding and ADC for "add with carry". I began to think more in terms of:
MemoryCell = MemoryCell ADD W
W = W ADD MemoryCell
Perhaps I should have stuck with "MemoryCell" or "Memory". For some reason, I started using "Var" to mean a memory cell. Therefore, I progressed to this:
Var = Var ADD W
W = W ADD Var
I wrote similar shorthand statements for many of the other PIC18 instructions.
Var = Var SUB W
W = Var SUB W
W = Var SBB W (SBB means Subtract with borrow)
W = W SBB Var
W = 0
W = Lit (Lit means literal number)
Var = 0
W = 0xFF
Var = 0xFF
Var = INC Var
After I had written down these shorthand statements for a pretty good sampling of the PIC18 instruction set, I looked them over to see how I might fit them into mnemonics. There was no way that I was ever going to be able to put an equal sign (=) into the mnemonics. The assembler was just not going to allow that. Eventually, I settled on using underscore (_) in place of the equal sign. Of the characters that are available for use in symbols, the underscore most resembles the equal sign.
Next, I started finding the shortest reasonable abbreviations for the various elements involved. Var became just V. Lit (for literal) became just L. The carry bit was already often called C. The Zero flag is Z. The Negative flag is N. And so on.
Now the shorthand descriptions each turned into a symbol, a symbol that tells what it does.
V_VADDW
W_WADDV
V_VSUBW
W_VSUBW
W_VSBBW
W_WSBBV
W_0
W_L
V_0
W_FF
V_FF
V_INCV
The assembler is not case sensitive. Personally, I tend to like to use mixed case sometimes to improve readability. Therefore, for me, I prefer these command mnemonics like this:
V_VAddW
W_WAddV
V_VSubW
W_VSubW
W_VSbBW
W_WSbBV
W_0
W_L
V_0
W_FF
V_FF
V_IncV
So here is my document to define my New PIC18 Instruction Set
Please send your comments to: