The special registers all reside below location 0x20. However, you have to keep in mind which bank you should select (using the RP bits in STATUS) since most registers only appear in one bank (with exceptions, like STATUS).
Here are some of the more common registers:
There are more that you can read about in the Microchip documentation, but these will get us started.
You've already read how PCLATH supplies the upper bits to the program counter when you execute a jump or subroutine call. There are two other important quirks you should know about.
First, the I/O pins are tied to the PORT registers, as you'd probably guess. However, on reset, all port pins are set to inputs. If you want to use a port pin as an output, you'll need to change the corresponding direction bit from a 1 (the default) to a 0. So to prepare PORTB pin 0 for output you might write:
bsf status,rp0 ; rp0=1 - select bank 1 bcf trisb,0 ; port b direction bit 0 = 0 bcf status,rp0 ; rp0=0 - select bank 0
It is good practice to reset the bank to 0 as soon as you are done accessing another bank. So then if you wanted to set the output to 1 you might write:
The other quirky behavior is the interaction between INDF and FSR. INDF isn't like an ordinary register. Instead, it mirrors another register indicated by the address in FSR. For example, location 0x6 is the PORTB register. Suppose you write:
movlw 6 ; W=6 movwf fsr ; FSR=W
Now the INDF register is really an alias for PORTB. So you might write:
bsf indf,0 ; set bit 0
This instruction doesn't really set bit 0 of INDF, it sets bit 0 of PORTB. Since FSR is an 8-bit register, it can contain a complete address from bank 0 or bank 1 (just treat bank 1 addresses as ranging from 0x80-0xFF). To access bank 3 and and bank 4 using FSR/INDF, you have to set the IRP bit in the STATUS register. RP0 and RP1 don't apply to INDF access!
That's a lot to digest about data memory for now. Take a break and come back to see the next frame where we'll look at instruction details.