I think your understanding is still wrong.
So can I conclude that when r is HL or DE, INC r actually increases the value in (HL)/(DE), not the value in HL/DE?
No that is actually wrong.
LDIR does the exact same as this piece of code:
Code: Select all
;copy &100 Bytes from &4000 -> &8000
LD BC,&100 ; load BC with number of bytes (BC = byte count)
LD HL,&4000 ; load HL with source
LD DE,&8000 ;load DE with destination (DE = destination)
PUSH AF ;save AF before copying the data. (actually this is not what the LDIR command does - it just does not work with A register).
loop:
LD A,(HL) ;load memory location indicated by HL to A
LD (DE),A ;load A to memory location indicated by DE
inc HL ;increment HL
inc DE ;increment DE
dec BC ;decrement BC
jr nz,loop ;loop if BC>0
pop AF ;restore AF
Now we have copied the &100 bytes from &4000 to &8000.
Shorter way but same result is:
Code: Select all
LD BC,&100
LD HL,&4000
LD DE,&8000
LDIR
LDIR does exactly the following in human readable words:
1. Copy Byte from memory location pointed to by HL into memory location pointed to by DE
2. Increment both HL and DE (the pointers, not the memory locations)
3. Decrement BC
4. loop if BC>0
So the increment commands in the pseudo code of the LDIR description increment the registers and have no impact on the memory itself. The copy in step 1 has the impact to the memory.
LDIR is just a fast way to copy memory regions with a fixed length.
Lets compare the number of memory cycles the CPU will use for both operations (1 memory cycle equals one NOP operation or 4 CPU clock ticks) (actually on individual systems this is different but for CPC it is 4 clocks = 1 memory cycle). Everything is actually counted in NOPs.
So for variant number 1 (the full code) the time in the loop + the push/pop is the following:
Code: Select all
CMD NOPs
PUSH AF 4
loop:
LD A,(HL) 2
LD (DE),A 2
inc HL 2
inc DE 2
dec BC 2
jr nz,loop 2
pop AF 3
TOTAL 19
Time for one LDIR iteration: 6 NOPs.
So LDIR is 3 times faster than the other way.
Now back to the example from the lesson:
Clear Screen CPC:
Code: Select all
LD BC,&4000 ;screen size
LD HL,&C000 ;screen start
LD DE,&C001 ;next cell
LD (HL),&00 ;clear the first memory cell.
LDIR ;copy the first cell to the next cell, increment HL and DE, decrement BC, loop if BC>0
What it does?
It puts in just 00 in the first byte of the screen (source) and then copies this byte to the next cell, then increase both pointers and do this over and over again.
If you use WinAPE, you can run that in the debugger and watch the memory location.
To observe this better, you want to use this:
Fill Memory with &FF
Code: Select all
LD BC,&100 ;Number of cells to fill
LD HL,&5000 ;start address
LD E,L ;copy HL to DE
LD D,H
INC E ;now DE point to one cell above HL
LD (HL),&FF ;setup the first cell with &FF
LDIR ;copy the first cell to the next cell, increment HL and DE, decrement BC, loop if BC>0
So set your debugger to &5000 and step through the code and see what it does.