RLCA/RRCA a range of values in memory

Posts about Z80 programming that do not relate to a particular computer
Post Reply
puppydrum64
Posts: 32
Joined: Thu Apr 22, 2021 9:30 pm

RLCA/RRCA a range of values in memory

Post by puppydrum64 » Tue Oct 05, 2021 12:35 am

I was playing around with RRD and RLD, and came up with something that I thought was quite clever. I haven't tested this on any Z80 hardware, this was all done by writing out what should happen on paper. (Do people still do that?)

EDIT: I have tested this on WinAPE and so far it seems to work. :Cheers:

EDIT 2: I can get it to work for rotating right, but not left... :AtWork:

Imagine memory address &1000 - &1003 contain the following, in order: &23, &45, &67, &89.

Code: Select all

LD HL,&1000
LD A,(HL)   		;A = &23
PUSH HL
Now, here's where the magic happens.

Code: Select all

	RRD		;A = &23, &1000 = &32 &45 &67 &89
	INC HL 			
	
	RRD		;A = &25, &1000 = &32 &34 &67 &89
	INC HL		
	
	RRD		;A = &27, &1000 = &32 &34 &56 &89
	INC HL
	
	RRD		;A = &29, &1000 = &32 &34 &56 &78
POP HL
PUSH HL
	RRD		;A = &22, &1000 = &93 &34 &56 &89
	INC HL
	
	RRD		;A = &24, &1000 = &93 &23 &56 &78
	INC HL
	
	RRD		;A = &26, &1000 = &93 &23 &45 &78
	INC HL
	
	RRD		;A = &28, &1000 = &93 &23 &45 &67
POP HL
RRD			;A = &23, &1000 = &89 &23 &45 &67
After all this is said and done, A equals what it did before any of the RRD commands took place, and the memory range has effectively been RRCA'd once. That is, the last byte is now the first, and the rest were shifted one byte over. We began with &23, &45, &67, &89, and ended with &89, &23, &45, &67.

This test worked for a 4 byte long range, but it seems like it can be generalized with the following (untested) code:

Code: Select all

RRCA_Range:
;input: 
;B = total size of memory range to rotate (measured in bytes)
;HL = address of zeroth element of the range.

LD A,(HL) ;ACCUMULATOR NEEDS TO EQUAL THE FIRST BYTE OF THE RANGE FOR THIS TO WORK
PUSH HL
PUSH BC
loop_RRCA_Range_firstloop:
	RRD
	INC HL
	DJNZ loop_RRCA_Range_firstloop
POP BC
POP HL
PUSH HL
PUSH BC
loop_RRCA_Range_secondloop:
	RRD
	INC HL
	DJNZ loop_RRCA_Range_secondloop
POP BC
POP HL
RRD
RET
And to properly call this routine you can use this macro:

Code: Select all

macro rrca_MemoryRange,addr,count
         LD HL,\addr
         LD b,count
         call RRCA_Range  ;the above subroutine
         endm
As I said before, I haven't fully tested this technique, but I believe this should work. If anyone wants to try it, feel free and please let me know if it works for you.

Post Reply

Return to “General Z80 Programming”