Part Three:
Beginning to Program

    Register A (called the accumulator) is most versatile of all Z80 registers.  It is used as a sort of general purpose register because of its aptitude towards nearly every kind of situation.  The other registers of immediate importance are H, L, D, E, B and C.  H and L stand for the high and low registers of the HL register pair.  HL is the most versatile of register pairs, in part because of its ability to manipulate indirect addresses.

    The most common of all Z80 instructions are the load instructions, with the syntax: ld register(s), operand where the operand is either a value or another register whose value is loaded into the first register.  The instruction <ld a,$20> loads the accumulator with $20 and <ld b,a> loads B with the value in A.  If A was $20 before execution of <ld b,a>, now both A and B contain $20.  Register pairs are similar, except that you can’t load register pairs with other register pairs, or with any registers period.  <ld hl,$d2fe>, <ld ix,$2434>, <ld iy,$8230>, and <ld bc,0> are perfectly valid instructions.  (Note: instructions for the registers SP, PC, I and R will not be discussed until they are introduced in a later section.)  The HL register pair will function as a pointer for indirect addresses; for instance:  <ld a,(hl)> or <ld h,(hl)> loads the specified register with the value addressed by HL.  You are also allowed to load into (hl) -- <ld (hl),$88>, for example.  So if HL is $c350, then the byte of external memory at $c350 will be $88 after the execution of <ld (hl),$88>.
    IX and IY are called the index registers, and are used primarily for indirect addressing.  The high registers of IX and IY are IXH and IYH; the low registers are IXL and IYL.  You generally don’t want to separate the IX and IY register pairs (and to do so you must use special instructions which are covered in the undocumented instructions section).  Nearly every instruction for HL can be edited to use IX or IY in place of HL.  IX and IY will always take up one extra byte than HL, though, because the opcodes for these instructions are the same as the opcode for HL except that IX has a $dd and IY has a $fd preceding the HL opcode.  <ld hl,$8686> has the opcode 218686, <ld ix,$8686> has the opcode DD218686.  IX’s and IY’s indexing capabilities also take up a second byte if the instructions are used to indirect address.  When you type <ld (ix),a>, you are really saying <ld (ix+0),a> (<ld (ix-0),a> if you're a pessimist); you can offset IX with any value from -128 to +127.  If you want to load A into an address 120 bytes below the address IX points to, then your code would be <ld (ix-120),a>.
    One last thing I need mention concerning the use of indirect addressing: you can not load bytes everywhere to the 64k of memory.  $0000 to $7fff is Read-Only Memory (ROM), meaning that it is immutable (while it can be read from normally, nothing can be written to it).  $8000 to $ffff is Random Access Memory (RAM), meaning that you can use it to store information, such as variables, tables, graphics, sounds and code and is the area of memory on which you can employ indirect addressing instructions.
    Here’s something you can compile and test out on your calculator, even if you don’t understand it (your anxiety is very understandable):

#include “asm86.h”
#include “ti86asm.inc”

.org _asm_exec_ram            ;.org $d748 (in ti86asm.inc)

 call _clrLCD                        ;clear screen
 call _homeup                       ;move cursor to top
 ld hl,string
 call _puts                             ;put the string “Hey, what’s going on?” to cursor position
 ret                                       ;end program

string:
.db “Hey, what’s going on?”,0

;comments are written after semicolons
;comments will be ignored by the compiler

.end
.end

    I’ll first try to explain both the string and the uncanny orgasm up at the top.  Each instruction is separated from the edge of the window by some amount of white space.  Any text that is not preceded by white space and is followed by a colon is called a label.  A label is not compiled, so it takes up no memory; it’s purpose is to help the programmer find an offset in his / her program without having to calculate the address.  When loading a register pair with a label, you are actually loading it with the address of the following byte.  So, <ld hl,string> is actually the same as <ld hl,$d756> -- it’s loading HL with a pointer to the string.
    $d756 is a rather suspicious number; here’s where it came from: when a program is compiled, a compiler will calculate the addresses of all labels according to the initial offset of the program itself in memory (the compiler must know where in memory our program is in order to calculate label offsets correctly when the program references itself).  .org (organize) tells the compiler around what address it needs to arrange the program’s labels.  In this case, the labels need to be offset from _asm_exec_ram.
    Let’s try that again:  the string begins on the 14th byte of this program, so in order that the string is located when this program is on the calculator, we need to know what address it is 14 bytes away from.  Because this program starts at _asm_exec_ram (_asm_exec_ram is an equate defined in ti86asm.inc with a numeric value of $d748 -- the address where all programs are executed on the calc), the compiler must understand that HL wants to point to an address 14 bytes subsequent of $d748 -- the address $d756.

    This program also uses the call instruction.  These instructions are magic, or at least for now they are ;-)