By now you should have a good idea of how a microcontroller works and how to write a basic program in assembler. In this last lesson we will briefly cover two advanced features that will be useful if you need to develop larger and more complicated programs.
The first feature is called indirect memory addressing. This can be a bit confusing at first, but the way it works is actually quite simple. Among the special function registers are two called INDF and FSR. The INDF register is essentially a virtual memory location. When you issue a read or write from it, you actually access whatever data memory location has its address stored in the FSR register:
// Load address of STATUS register into FSR movlw 08h movwf FSR // Both these instructions will copy the // STATUS register into w. movf 08h, w // direct movf INDF, w // indirect
This feature is essential if you want to implement data structures like queues, or have an algorithm that loops through the elements of an array. Those of you who have done C programming might also recognise this as the way a pointer works, and indeed this is exactly how a compiler would implements a pointer variable on the chip.
The second feature is sub-routine support and is implemented by the call and retlw instructions. The call instruction works like the goto instruction, branching execution to whatever program memory address you specify as an operand. Where it differs is that before the branch is made the address of the instruction immediately following it is loaded into an internal stack. When you issue a corresponding retlw instruction, execution will resume at the address that was previously stored onto the stack:
// ... // ... // (1) Issue a call instruction call my_func // (4) Execution resumes from here // ... // ... :my_func // (2) Do some useful processing // ... // ... // (3) Return to caller retlw 0
Because addresses are stored in a stack, you can nest calls to a level of two deep (on larger microcontrollers it can be many more) and each time a retlw instruction is issued the program will return to the last location where a call was made. This behaviour is the basis for creating functions and allows you to create reusable code blocks in your program.
If you've made it this far then congratulations and hopefully these lessons have been useful. The last section consists of a set of exercises and examples that you can use to test your knowledge and develop your skills further.