Beginning Z80 Machine Code, Lesson 3

Author(s): Syd Wyncoop
Pub Details: Time Designs Magazine v2 n5 (Volume 2, Issue 5)
Date: July/August 1986
Pages: 18-19
Drawing of a Timex Sinclair computer
Drawing of a Timex Sinclair computer

Before we get to our first MC instructions, lets take another look inside our CPU. Inside we will find registers that are called A,F,B,C,D,E,H,L,I,R,IX,IY,SP,PC,A’,F’,B’,C’,D’,E’,H’ and L’. These are not the alphabet soup, that the CPU had for lunch. Registers are merely storage places within the CPU as opposed to external memory (ROM and RAM). Think of these registers as storage boxes with names instead of addresses…much the same as you would BASIC variables.

Some of the single registers can be married to form register pairs. You are hereby ordained, by the power invested in me by the Great God Z80, as Justice of the CPU, to form these unions as required. The permissable combinations are AF,BC,DE,HL,AF’,BC’,DE’ and HL’ (and you thought I didn’t know the alphabet!).

Single registers are similar to bytes, in that they can contain any value 0-255. Register pairs can contain any value 0-65535, which makes them very valuable as address pointers. Refer to the discussion on addresses in lesson one for more on this (contact TDM if you need back copies). We will use these similarities to pass parameters (information) to and from our MC routines.

On the subject of addresses and register pairs, you need to remember which is high and low. In memory (addresses), the first byte is low, however, with register pairs, the first register is high. This is easily remembered by knowing that the HL register pair was named with this in mind. H means “high” and L means “low”. An assembler will handle this for you, but we will have to watch it while we are hand assembling our code. Many crashes will occur because you forgot (or confused) the order of the high and low bytes or registers.

Some of these registers have special names and/or jobs. Chart 2 lists some of these names/jobs. However, we will not discuss them further until we get to the instructions using them.

Now for our first set of instructions (and you were wondering if I even knew any). Its mnemonic is “Ld”, which is short for Load. Ld has no relation to the Basic LOAD command. Ld is an assignment instruction and acts very much like the Basic LET command.

The proper “syntax” is: Ld A,15. Which is read as “Load the A register with the value 15”. Ld acts very much like the Basic LET x=15.

Take another look at the sample disassembly that I left you with last lesson. Look at the comments and see if you can follow what is happening. It is a program that will return the sum of 0Ah and 10h to Basic with the command: PRINT USR address. For practice, you can enter that program. Try poking the 2nd and 4th bytes with different values and run it again to see if you get the results you expect. If the sum is greater than 255, you will discover a bug I left (intentionally) for later correction.

Note that we loaded the result into the BC register pair before returning to Basic. This is due to the Basic Operating System’s handling of the USR function. It will always return the value held in the BC register pair. The value returned will not be the result unless you properly load BC before returning.

Ld may not seem to be of much value. However, in its many forms, Ld is the “most used” instruction. We can Ld most registers, register pairs or addresses with either a constant, the contents of another register (pair), or the contents of an address. Chart 3 details some of the many forms Ld can have as well as the proper “syntax”.

You will notice some instructions have parenthesis. The Parenthesis signify “the contents of”. For example: read the instruction Ld A,(4000h) as Load the A register with the contents of the address 4000h. The Basic commands PEEK and POKE can be compared to these instructions. If the parenthesis appear on the left of the comma, you have a POKE operation, and if they appear on the right of the comma, you have a PEEK operation. The Basic equivalent of Ld A, (4000h) is LET x = PEEK 16384, (4000h=16384). Using this knowledge, the instruction Ld (4000h),A is equivalent to POKE 16384,x.

You will also notice a symmetry to the instructions. You can Ld r, (HL) and you can Ld (HL), r. This symmetry will prove to be very useful and holds true throughout most of the instruction set.

Note that some instructions seem to favor the register A or the register pair HL. This is due to their special functions (chart 2). There are simply some instructions that can only be performed with A or HL, and no other register (pair). We will see that Ld is not the only instruction to exhibit this favoritism. This is not as restrictive as it first sounds, although you will on occasion wish for an instruction that does not exist.

There is no need to detail the operation of each instruction as you should be able to determine appoximately what can be expected from them, if you study charts 2 and 3 in conjunction with this lesson. We will discuss them further as we use them. It will be much easier for me to explain, and easier for you to understand their operation.

Chart 2

Register ! Name         ! Job
   A     ! Accumulator  ! accumulate the results of eight bit
         !              ! arithmetic
         !              ! directly access the contents of any
         !              ! memory address
   F     ! Flags        ! holds various flags for CPU which
         !              ! indicate the results of arithmetic
         !              ! and logical instructions
   B     !              ! eight bit counter
   BC    !              ! sixteen bit counter
   DE    ! Destination  ! used for block moves
   HL    ! High/Low     ! sixteen bit arithmetic
         !              ! directly access memory addresses
         !              ! indirect address pointer

Chart 3

Registers              ! Register Pairs
Ld r,r                 ! Ld rr,nn
Ld r,n                 ! Ld IX,nn
                       ! Ld IY,nn
Ld A,(pq)              !
Ld (pq),A              ! Ld (pq),BC
                       ! Ld (pq),DE
Ld r,(HL)              ! Ld (pq),HL
Ld A,(BC)              ! Ld (pq),IX
Ld A,(DE)              ! Ld (pq),IY
Ld (HL),r              !
Ld (BC),A              ! Ld BC,(pq)
Ld (DE),A              ! Ld DE,(pq)
                       ! Ld HL,(pq)
Ld r,(IX+d)            ! Ld IX,(pq)
Ld r,(IY+d)            ! Ld IY,(pq)
Ld (IX+d),r            !
Ld (IY+d),r            !
                       !
Ld (HL),n              !
Ld (IX+d),n            !
Ld (IY+d),n            !

Where: r =any single register
       rr=any register pair
       n =any numeric constant 0-255
       nn=any numeric constant 0-65535
       d =any displacement 0-255
       pq=any address 0-65535

I am not listing the hex codes for all the Z80 instructions that we will use, as this is not intended to be an exhaustive study, but is meant to give you a start. The first rung of the ladder. If you have not yet obtained a good book on the subject, you can find the codes in the appendix of your Sinclair manual.

I cannot hope to give you all you will need in an article such as this. I must advise you to get a good book as a study guide and to fill in where I leave off. Rather than suggest a book that you may not like as well as I do, I would advise you to look at several. If possible, get several opinions…but get a book.

That’s it for now. Next issue we will discover the math instructions. The special significance of A and HL will be very obvious after that.