Finding LSB in a register

The place for codemasters or beginners to talk about programming any language for the Spectrum.
Post Reply
User avatar
arkannoyed
Manic Miner
Posts: 435
Joined: Mon Feb 05, 2018 9:56 am
Location: Northamptonshire

Finding LSB in a register

Post by arkannoyed »

Hey folks, I'm back!

I'm currently shaving more bytes off the Chess display engine (it got down to 589 bytes last year!). A few fresh ideas to explore after a break from it. I've speeded it up a little so far, which is nice, but I've an idea that requires to find the LSB within HL. Is there a quick method anyone knows of?

Ta.
User avatar
arkannoyed
Manic Miner
Posts: 435
Joined: Mon Feb 05, 2018 9:56 am
Location: Northamptonshire

Re: Finding LSB in a register

Post by arkannoyed »

I should've also added that I want to isolate that BIT and set all the bits to the Right of it ideally.

I know that you could just DEC HL which will set all to the right, but clearing the rest, is there an easy way? 8 bit maths is easy, 16 bit less so.
User avatar
Ast A. Moore
Rick Dangerous
Posts: 2640
Joined: Mon Nov 13, 2017 3:16 pm

Re: Finding LSB in a register

Post by Ast A. Moore »

Not sure if this is fast enough for you, but I came up with this:

Code: Select all

;HL holds the value for testing

	ld de,0
	push hl
	ld b,16
l1	rrc h		;mind the C in RRC here.
	rr l
	jr c,p1
	ccf
	rl e
	rl d
	djnz l1

p1
	pop hl
	add hl,de
The DJNZ loop can be replaced with a simple jump, if you’re positive that at least one bit in HL is set. As a bonus, though, B will hold the position of the first set bit counting from the left (if you need it).
Every man should plant a tree, build a house, and write a ZX Spectrum game.

Author of A Yankee in Iraq, a 50 fps shoot-’em-up—the first game to utilize the floating bus on the +2A/+3,
and zasm Z80 Assembler syntax highlighter.
User avatar
arkannoyed
Manic Miner
Posts: 435
Joined: Mon Feb 05, 2018 9:56 am
Location: Northamptonshire

Re: Finding LSB in a register

Post by arkannoyed »

Interesting. Whichever way I've tried so far, its coming out a lot more complicated than I'd originally imagined.

Basically this is an auto masking excercise, where I want to create a mask by using the LSB as the marker for where to create the mask, so for instance;

if HL were;

00000101 11000000 then bit 6 of L is the marker and would make a mask say in BC of 00000000 00111111

does that make sense?

It does need to be small, and speed isn't massively important, more the smallness!
User avatar
Ast A. Moore
Rick Dangerous
Posts: 2640
Joined: Mon Nov 13, 2017 3:16 pm

Re: Finding LSB in a register

Post by Ast A. Moore »

arkannoyed wrote: Thu Jan 17, 2019 1:26 pm It does need to be small, and speed isn't massively important, more the smallness!
In that case, my routine can be modified to save one byte: replace LD B,16 with LD B,D or LD B,E. You’ll end up with having to LD A,B/NEG/INC A to get the first set bit position (now counting from the right) in A.
Every man should plant a tree, build a house, and write a ZX Spectrum game.

Author of A Yankee in Iraq, a 50 fps shoot-’em-up—the first game to utilize the floating bus on the +2A/+3,
and zasm Z80 Assembler syntax highlighter.
User avatar
Metalbrain
Microbot
Posts: 107
Joined: Thu Feb 15, 2018 2:14 pm

Re: Finding LSB in a register

Post by Metalbrain »

What about this?

Code: Select all

;Input:  DE = original value
;Output: HL = mask

		ld	hl,0
		and	a
nextbit:	adc	hl,hl
		ret	c
		rr	d
		rr	e
		ccf
		jr	c,nextbit
		ret
User avatar
arkannoyed
Manic Miner
Posts: 435
Joined: Mon Feb 05, 2018 9:56 am
Location: Northamptonshire

Re: Finding LSB in a register

Post by arkannoyed »

Oooh, yes. Now the RET C won't be needed, as theres no need for error protection (I think thats what its there for?), though I will need to push and pop DE, but that just might work. Off to test thanks!
User avatar
Metalbrain
Microbot
Posts: 107
Joined: Thu Feb 15, 2018 2:14 pm

Re: Finding LSB in a register

Post by Metalbrain »

arkannoyed wrote: Thu Jan 17, 2019 3:02 pm Oooh, yes. Now the RET C won't be needed, as theres no need for error protection (I think thats what its there for?), though I will need to push and pop DE, but that just might work. Off to test thanks!
I was about to post that the RET C could be removed, but it's not for error protection, just to exit earlier in the case of initial value being 0
User avatar
Ast A. Moore
Rick Dangerous
Posts: 2640
Joined: Mon Nov 13, 2017 3:16 pm

Re: Finding LSB in a register

Post by Ast A. Moore »

Oh, I see. You only want the mask, not the already masked value. Sorry, I didn’t get that from your initial posts. Disregard my code then.
Every man should plant a tree, build a house, and write a ZX Spectrum game.

Author of A Yankee in Iraq, a 50 fps shoot-’em-up—the first game to utilize the floating bus on the +2A/+3,
and zasm Z80 Assembler syntax highlighter.
User avatar
Kweepa
Manic Miner
Posts: 311
Joined: Sat Feb 03, 2018 6:14 pm
Location: Albuquerque, New Mexico

Re: Finding LSB in a register

Post by Kweepa »

No loops:
ld bc,hl
dec bc
ld a,h
xor 255
and b
ld b,a
ld a,l
xor 255
and c
ld c,a
Just uses HL & BC
User avatar
Kweepa
Manic Miner
Posts: 311
Joined: Sat Feb 03, 2018 6:14 pm
Location: Albuquerque, New Mexico

Re: Finding LSB in a register

Post by Kweepa »

Mine is 13 bytes (checked with www.asm80.com, which is awesome!).
Metalbrain's is 12 bytes, if you remove the ret c and replace ld hl,0 with xor h/xor l.
User avatar
djnzx48
Manic Miner
Posts: 729
Joined: Wed Dec 06, 2017 2:13 am
Location: New Zealand

Re: Finding LSB in a register

Post by djnzx48 »

Could you replace XOR 255 with CPL and get it down to 11 bytes?
User avatar
Kweepa
Manic Miner
Posts: 311
Joined: Sat Feb 03, 2018 6:14 pm
Location: Albuquerque, New Mexico

Re: Finding LSB in a register

Post by Kweepa »

Yep, that works :)
Didn't know about that instruction!
User avatar
djnzx48
Manic Miner
Posts: 729
Joined: Wed Dec 06, 2017 2:13 am
Location: New Zealand

Re: Finding LSB in a register

Post by djnzx48 »

If you're doing regular AND-then-OR masking, you can just use OR B instead of CPL: AND B (and the same for C) as it doesn't matter what the mask is when the pixel value is set. That would get it down to 9 bytes.

(EDIT: Actually in that case all you need to create the mask is a single DEC instruction. So this method only requires one byte.)

Maybe other types of masking would work, for instance OR for the mask and then XOR for the sprite. Are you doing the same thing to create a mask on the left using the MSB?
User avatar
Metalbrain
Microbot
Posts: 107
Joined: Thu Feb 15, 2018 2:14 pm

Re: Finding LSB in a register

Post by Metalbrain »

Kweepa wrote: Thu Jan 17, 2019 9:47 pm and replace ld hl,0 with xor h/xor l.
xor h/xor l wouldn't set hl to 0, they would just make A = A xor H xor L
User avatar
arkannoyed
Manic Miner
Posts: 435
Joined: Mon Feb 05, 2018 9:56 am
Location: Northamptonshire

Re: Finding LSB in a register

Post by arkannoyed »

Wow, some great ideas, and it certainly looks as if the 8 bit logic methods will win. I'll have a go with some ideas later and see what works best.

Lots of re-designing to do to make the printing byte-wise work as opposed to bit-wise, which is how the Chess pieces are done currently. The speed improvement will be huge though, and hopefully might lose a few bytes as well as a bonus!
User avatar
lister_of_smeg
Microbot
Posts: 145
Joined: Thu Nov 16, 2017 1:44 pm

Re: Finding LSB in a register

Post by lister_of_smeg »

Kweepa wrote: Thu Jan 17, 2019 3:49 pm No loops:
ld bc,hl
dec bc
ld a,h
xor 255
and b
ld b,a
ld a,l
xor 255
and c
ld c,a
Just uses HL & BC
ld bc,hl isn't a valid z80 instruction
Last edited by lister_of_smeg on Fri Jan 18, 2019 9:48 am, edited 2 times in total.
User avatar
arkannoyed
Manic Miner
Posts: 435
Joined: Mon Feb 05, 2018 9:56 am
Location: Northamptonshire

Re: Finding LSB in a register

Post by arkannoyed »

yes, but ld B,H and ld C,L are, which does the same thing.
User avatar
arkannoyed
Manic Miner
Posts: 435
Joined: Mon Feb 05, 2018 9:56 am
Location: Northamptonshire

Re: Finding LSB in a register

Post by arkannoyed »

Seems to almost do what it needs to. The only thing left that I should've mentioned before is that it needs to RESet the LSB in HL (the data register).
So whereas maybe HL=05c0h, after creating the mask, bit 6 of L needs to be cleared, giving the result HL=0580h.

Does that make sense?
User avatar
Kweepa
Manic Miner
Posts: 311
Joined: Sat Feb 03, 2018 6:14 pm
Location: Albuquerque, New Mexico

Re: Finding LSB in a register

Post by Kweepa »

arkannoyed wrote: Fri Jan 18, 2019 9:46 am yes, but ld B,H and ld C,L are, which does the same thing.
Wow, apparently asm80.com is too clever for its own good - it automatically converted ld bc,hl to ld b,h/ld c,l!
User avatar
lister_of_smeg
Microbot
Posts: 145
Joined: Thu Nov 16, 2017 1:44 pm

Re: Finding LSB in a register

Post by lister_of_smeg »

arkannoyed wrote: Fri Jan 18, 2019 2:01 pm Seems to almost do what it needs to. The only thing left that I should've mentioned before is that it needs to RESet the LSB in HL (the data register).
So whereas maybe HL=05c0h, after creating the mask, bit 6 of L needs to be cleared, giving the result HL=0580h.

Does that make sense?
This any good?

Code: Select all

ld	d, h
ld	e, l
dec	de
ld	a, d
xor	h
ld	d, a
cpl
and	h
ld	h, a
ld	a, e
xor	l
ld	e, a
cpl
and	l
ld	l, a
rr	d
rr	e
Post Reply