Z80 Assembly - Instructions: Moving Data


Syntax: ld op1,op2

The ld instruction copies the value of the second operand into the first operand. It does not alter any of the flags, except for the special cases of reading the I or R registers. The two operands must fit in size; they can be either 8 or 16 bits long. The two tables below show all the possibilities. The first operand is on the left column, the second on the top row. imm denotes an immediate (either 8 or 16-bit constant), n is a signed 8-bit integer (ranging from -128 to 127). ofs is a 16-bit memory address.

8-bit combinations

IXHXXXXXX  ***X          
IXLXXXXXX  X***          
IYHXXXXXX    ***X        
IYLXXXXXX    X***        
(BC) X                  
(DE) X                  
(HL)XXXXXXXX      **     
(IX+n)XXXXXXXX       **    
(IY+n)XXXXXXXX        **   
(ofs) X                  
I X                  
R X                  

16-bit combinations

BCX      X
DEX      X
HLX      X
IXX      X
IYX      X
(ofs) XXXXXX 

Stack operations

There are two things to note about the stack: a) before using push you have to be sure that SP points to a safe place (pop is normally less critical, as it does not write to the memory); b) you must be aware that the callret instructions also use the very same stack to preserve the return address.


Syntax: push reg16 (reg16: AF, BC, DE, HL, IX, IY)

When the instruction is executed, SP is decreased by two and the value of reg16 is copied to the memory location pointed by the new value of SP. It does not affect the flags.


Syntax: pop reg16 (reg16: AF, BC, DE, HL, IX, IY)

When the instruction is executed, the value of the word found at the memory location pointed by SP is copied into reg16, then SP is increased by 2. No flags are affected (except for the case of popping into AF).

Block operations

Although the following instructions are basically simple loads, they do affect the flags. S, Z and C are not altered, but H and N are set to zero. The P/V flag is interpreted as overflow. None of them have any operands. It is worth noting that a bunch of ldi’s/ldd’s is always faster than the corresponding ldir/lddr, so if you are optimising for speed, do not use the repeated load instructions.


The instruction copies a byte from (HL) to (DE) (i. e. it does an ld (de),(hl)), then increases both HL and DE to advance to the next byte. Besides, it decreases BC, and sets the P/V flag in the case of overflowing.


Almost the same as ldi. The only difference is that HL and DE are decreased on every execution.


This is an ldi repeated until BC reaches zero. Naturally, the P/V flag holds zero after leaving the instruction, since BC does not overflow. After all, this single instruction copies BC bytes from (HL) to (DE), increases both HL and DE by BC, and sets BC to zero.


Similarly to the previous one, but with ldd repeated (copying backwards).

Exchange operations

These instructions do not alter the flags. However, they are the only ones that access the shadow registers. You can use them for backing up data in a reasonably fast way, but you have to pay attention, since this action alters the contents of the registers you “save”, unlike the stack instructions. If you are smart enough, you can effectively extend the registers you use by taking advantage of the shadow registers. When interrupts are enabled, you must not use these instructions, because shadow registers are used to back up all the 8-bit registers in the system interrupt routine!


Syntax: ex op1,op2

The values of the two operands are exchanged. There is a total number of five combinations possible: ex (sp),hl, ex (sp),ix, ex (sp),iy, ex de,hl, ex af,af’. The last one naturally alters the flags (exchanges them with the shadow flags). You cannot exchange the order given, e. g. there is no ex hl,de!


There are no operands. This instruction exchanges BC with BC’, DE with DE’ and HL with HL’ at the same time. What’s very important to note that it is very fast.

Back to the index