## Forums

Sega Master System / Mark III / Game Gear
SG-1000 / SC-3000 / SF-7000 / OMV
Home - Forums - Games - Scans - Maps - Cheats - Credits
Music - Videos - Development - Hacks - Translations - Homebrew

## View topic - copy bits in a byte

Author Message
• Joined: 05 Sep 2013
• Posts: 2908
copy bits in a byte
Posted: Tue Apr 13, 2021 8:17 pm
after swap two bits in a byte, today I'm wondering if there's a (fast) way to copy a bit into a few (but not all) other locations into the same byte, for instance as in:

%abcdefgh -> %abCCefCh

bonus point if it's possible to do that with more than one bit at the same time, as in:

%abcdefgh -> %BBCCefCB

any hints? :)

• Joined: 05 Dec 2019
• Posts: 32
How to replace select bits with contents of CF
Posted: Tue Apr 13, 2021 10:04 pm
Assume bit C is in CF, and byte %abcdefgh is in B.

sbc a          ; A=C C C C C C C C
xor b          ; A=CaCbCcCdCeCfCgCh
and %00110010  ; A=0 0 CcCd0 0 Cg0  clear bits to keep from B
xor b          ; A=a b C C e f C h

I'll attempt the bonus point if it is explained where bits B and C come from, so that I can get them into CF and apply the above.

For more inspiration, see ASM Snippets and Optimizing assembly code. (These pertain to SM83, a CPU by Sharp that is similar in many ways to Z80.)

• Joined: 05 Sep 2013
• Posts: 2908
Posted: Wed Apr 14, 2021 9:34 am
thanks for the reply and the links!

sorry for not stating the question correctly. I mean the bits come from the same byte as in

%76543210 -> %76553250

or in

%76543210 -> %66553256

(also, is last operation an XOR? Shouldn't it be OR?)

• Joined: 14 Aug 2000
• Posts: 598
• Location: Adelaide, Australia
copy bits in a byte
Posted: Wed Apr 14, 2021 11:41 am
The fastest and most space-efficient way I found was to test one bit being copied at a time using the BIT instruction and then using an OR or AND with immediate data to set or clear the target bits in one go:

CopyBit6:
BIT A,6
JR NZ, SetBits7and0
AND %01111110
JR CopyBit5
SetBits7and0:
OR %10000001
CopyBit5:
BIT A,5
JR NZ, SetBits4and1
AND %11101101
JR exit
SetBits4and1:
OR %00010010

Usually, using the direct register logical instructions is the fastest way to do something like this because the instructions involved (LD, OR, AND, RRCA, RLCA) are all single bytes and all fast instructions. But the single Accumulator kills it because you end up copying back and forth from temp values in another register or two multiple times.

The bit test, set and reset instructions (BIT, SET, RES) are purpose built for this, but as they all have a 0xCB prefix byte, they take the most time, and the most space, all due to the prefix byte.

There may be faster and better ways though.

• Joined: 14 Apr 2013
• Posts: 528
Posted: Wed Apr 14, 2021 12:00 pm
sverx wrote
(also, is last operation an XOR? Shouldn't it be OR?)

The XOR is correct here.

His suggestion makes use of the fact that using XOR you can combine 2 values in a non-destructive way:
If C = A XOR B then A = C XOR B and B = C XOR A.

In the row
xor b          ; A=CaCbCcCdCeCfCgCh

Each bit in register A stores the original bit (a..h) and the value of C. That's what he illustrated in the comment.

Using the AND he then clears the information in the bits that should not keep the value of C.

The final XOR then writes the original bits to the bits that got masked out to 0 and removes the original bit from this bits that still contain the XOR-combined value, leaving C in there.

It's basically the same idea as with swapping the values of two variables using XOR.

• Joined: 05 Dec 2019
• Posts: 32
Posted: Wed Apr 14, 2021 12:28 pm
Given that the objective is to copy bit 5 to the other bits, the first step is to copy bit 5 into CF.

ld a, %11011111
and b  ; A = B if bit 5 were 0
cp b   ; CF = 1 if A < B, 0 if A == B

Then proceed as above to overwrite selected bits with CF. In total, it takes 9 bytes and 34 cycles.

• Joined: 05 Sep 2013
• Posts: 2908
Posted: Wed Apr 14, 2021 12:53 pm
instead of copying the single bit to CF and then from there to all the bits in the accumulator (that wouldn't work in a single pass if we were going to copy more than one bit to any other location) how could we combine that to less instructions?

say we want to go from %76543210 to %76673223 - sure we don't want to do the whole copy process 4 times, one for each bit, right?

also, thanks @Calindro for the clarification, much appreciated! :)

• Joined: 14 Aug 2000
• Posts: 598
• Location: Adelaide, Australia
copy bits in a byte
Posted: Wed Apr 14, 2021 2:55 pm
For all out speed, my boring solution is 10 bytes and 27 to 29 cycles per bit copied.

What's the optimisation for out of interest?

• Joined: 05 Dec 2019
• Posts: 32
Posted: Thu Apr 15, 2021 3:30 am
This snippet takes advantage of moving two of the bits by the same distance (1 place value) and two other bits by the same distance (3 place values).

; have %hgfedcba, want %hgghdccd

ld a, b        ; A=h g f e d c b a
rra            ; A=? h g f e d c b
xor b          ; A=?hhggffeeddccbba
and %00100010  ; A=0 0 gf0 0 0 cb0
xor b          ; A=h g g e d c c a
ld b, a
rrca           ; A=b h g g e d c c
rrca           ; A=c b h g g e d c
rrca           ; A=c c b h g g e d
xor b          ; A=chcgbghegdgcecda
and %00010001  ; A=0 0 0 he0 0 0 da
xor b          ; A=h g g h d c c d

Back to the top of this page

Back to SMS Power!