[ASM] Compare 16-bit registers?

Got questions? Got answers? Go here for both.

Moderator: MaxCoderz Staff

User avatar
Timendus
Calc King
Posts: 1729
Joined: Sun 23 Jan, 2005 12:37 am
Location: Netherlands
Contact:

[ASM] Compare 16-bit registers?

Post by Timendus »

I want to compare two 16-bit registers, and see which one's value is largest. Something like:

Code: Select all

cp de,bc
jp c,bcIsBigger
Of course cp doesn't work with these registers, but neither does sbc (which, I believe, also properly sets the carry flag), and I'd prefer not to use hl. I could start moving data around with the stack and whatnot, or rewrite my code, but I think I remember seeing some fancy shortcuts for this, and I thought I'd ask the collective brain of the community ;)

If there is no efficient way to do this with these registers, what would be the fastest/smallest way to do it with hl? sbc hl,de?
http://clap.timendus.com/ - The Calculator Link Alternative Protocol
http://api.timendus.com/ - Make your life easier, leave the coding to the API
http://vera.timendus.com/ - The calc lover's OS
King Harold
Calc King
Posts: 1513
Joined: Sat 05 Aug, 2006 7:22 am

Post by King Harold »

maybe a modified version of the regular CpHLDE?

edit: load into HL I'd say.. stack stuff would be slow
edit2:

so something like

Code: Select all

ld h,d
ld l,e
or a
sbc hl,bc
User avatar
Timendus
Calc King
Posts: 1729
Joined: Sun 23 Jan, 2005 12:37 am
Location: Netherlands
Contact:

Post by Timendus »

That's nice and all, but hl is holding a pointer for me, so I'd still have to push it.

Same question for add de,bc... there's got to be much faster ways then

Code: Select all

	push hl
	ld h,0
	ld l,h
	add hl,de
	add hl,bc
	ld d,h
	ld e,l
	pop hl
?
http://clap.timendus.com/ - The Calculator Link Alternative Protocol
http://api.timendus.com/ - Make your life easier, leave the coding to the API
http://vera.timendus.com/ - The calc lover's OS
User avatar
Timendus
Calc King
Posts: 1729
Joined: Sun 23 Jan, 2005 12:37 am
Location: Netherlands
Contact:

Post by Timendus »

Oh, replace
ld d,h \ ld e,l
in my example and
ld h,d \ ld l,e
in your example with
ex de,hl

;)

Either way, the question still stands.
http://clap.timendus.com/ - The Calculator Link Alternative Protocol
http://api.timendus.com/ - Make your life easier, leave the coding to the API
http://vera.timendus.com/ - The calc lover's OS
CoBB
MCF Legend
Posts: 1601
Joined: Mon 20 Dec, 2004 8:45 am
Location: Budapest, Absurdistan
Contact:

Post by CoBB »

What about doing it byte by byte?

Code: Select all

ld a,d
cp b
jp c,bcIsBigger
jp nz,deIsBigger
ld a,e
cp c
jp c,bcIsBigger
jp nz,deIsBigger
<they are equal here>
User avatar
Dwedit
Maxcoderz Staff
Posts: 579
Joined: Wed 15 Dec, 2004 6:06 am
Location: Chicago!
Contact:

Post by Dwedit »

If you're comparing with a constant, you should add a negative number instead of subtracting.
You know your hexadecimal output routine is broken when it displays the character 'G'.
User avatar
qarnos
Maxcoderz Staff
Posts: 227
Joined: Thu 01 Dec, 2005 9:04 am
Location: Melbourne, Australia

Post by qarnos »

CoBB wrote:What about doing it byte by byte?

Code: Select all

ld a,d
cp b
jp c,bcIsBigger
jp nz,deIsBigger
ld a,e
cp c
jp c,bcIsBigger
jp nz,deIsBigger
<they are equal here>
Another way of doing it byte by byte:

Code: Select all

ld a, e
sub c
ld a, d
sbc a, b
Carry flag set if BC > DE.
Zero flag set if BC == DE.
"I don't know why a refrigerator is now involved, but put that aside for now". - Jim e on unitedti.org

avatar courtesy of driesguldolf.
CoBB
MCF Legend
Posts: 1601
Joined: Mon 20 Dec, 2004 8:45 am
Location: Budapest, Absurdistan
Contact:

Post by CoBB »

qarnos wrote:Another way of doing it byte by byte:

Code: Select all

ld a, e
sub c
ld a, d
sbc a, b
Carry flag set if BC > DE.
Zero flag set if BC == DE.
Indeed, I knew I was overlooking something trivial. :lol: That’s what happens when you stop dealing with low-level stuff...
User avatar
Timendus
Calc King
Posts: 1729
Joined: Sun 23 Jan, 2005 12:37 am
Location: Netherlands
Contact:

Post by Timendus »

That looks real nice, thanks qarnos! ;)

And doing a smaller add de,bc, would that be something like this?

Code: Select all

ld a,e
add a,c
ld e,a
ld a,d
adc a,b
ld d,a
Just thinking out loud here, no idea if it'll work :)
http://clap.timendus.com/ - The Calculator Link Alternative Protocol
http://api.timendus.com/ - Make your life easier, leave the coding to the API
http://vera.timendus.com/ - The calc lover's OS
User avatar
qarnos
Maxcoderz Staff
Posts: 227
Joined: Thu 01 Dec, 2005 9:04 am
Location: Melbourne, Australia

Post by qarnos »

Timendus wrote:That looks real nice, thanks qarnos! ;)

And doing a smaller add de,bc, would that be something like this?

Code: Select all

ld a,e
add a,c
ld e,a
ld a,d
adc a,b
ld d,a
Just thinking out loud here, no idea if it'll work :)
Yep, that would work.

You can think of the carry flag from the ADD instruction as being the 9th bit of the result. When you do the ADC, you are carrying-over that bit into the high byte.

Eg: 128 + 129 = 257

257 In binary:

1 0000 0001
^ this bit goes into the carry flag, the rest is the low-byte of the result.

Since bit 9 == 256, we want to add 1 to the high byte of the result if the carry flag is set, and that's what ADC does. :)

Edit: Though a smaller (3 bytes instead of 6) and faster (19 T-states versus 24) way to add DE and BC would be this:

Code: Select all

ex de, hl
add hl, bc
ex de, hl
"I don't know why a refrigerator is now involved, but put that aside for now". - Jim e on unitedti.org

avatar courtesy of driesguldolf.
User avatar
Jim e
Calc King
Posts: 2457
Joined: Sun 26 Dec, 2004 5:27 am
Location: SXIOPO = Infinite lives for both players
Contact:

Post by Jim e »

qarnos wrote:
CoBB wrote:What about doing it byte by byte?

Code: Select all

ld a,d
cp b
jp c,bcIsBigger
jp nz,deIsBigger
ld a,e
cp c
jp c,bcIsBigger
jp nz,deIsBigger
<they are equal here>
Another way of doing it byte by byte:

Code: Select all

ld a, e
sub c
ld a, d
sbc a, b
Carry flag set if BC > DE.
Zero flag set if BC == DE.
Pretty sure that doesn't work.

BC = $00FF
DE = $0100

e - c = 00 - FF = carry set
d - b = 01 - 00 - carry = zero and no carry.

We had a discussion on this at revsoft in the code game thread.

For a non-destructive comparison of de - bc this would work.

Code: Select all

    ex de,hl
    or a
    sbc hl,bc
    add hl,bc
    ex de,hl
Yes all the flags do match CP despite that add hl,bc being there. It doesn't use the stack nor is it very large so you can macro it.
Image
User avatar
qarnos
Maxcoderz Staff
Posts: 227
Joined: Thu 01 Dec, 2005 9:04 am
Location: Melbourne, Australia

Post by qarnos »

Jim e wrote:
qarnos wrote:Carry flag set if BC > DE.
Zero flag set if BC == DE.
Pretty sure that doesn't work.

BC = $00FF
DE = $0100

e - c = 00 - FF = carry set
d - b = 01 - 00 - carry = zero and no carry.
Interesting - I hadn't though of that.

It should still be fine if you just want to know if one is larger, just not if they are equal :)

Perhaps we could check the sign flag. It should be M if BC >= DE and P otherwise, right? I haven't thought that one through at all - it's just a guess, so I may be wrong.
For a non-destructive comparison of de - bc this would work.

Code: Select all

    ex de,hl
    or a
    sbc hl,bc
    add hl,bc
    ex de,hl
Yes all the flags do match CP despite that add hl,bc being there. It doesn't use the stack nor is it very large so you can macro it.
This was my first idea, but I forgot ADD HL doesn't affect the zero flag. That'll learn me. :mrgreen:
"I don't know why a refrigerator is now involved, but put that aside for now". - Jim e on unitedti.org

avatar courtesy of driesguldolf.
CoBB
MCF Legend
Posts: 1601
Joined: Mon 20 Dec, 2004 8:45 am
Location: Budapest, Absurdistan
Contact:

Post by CoBB »

qarnos wrote:Perhaps we could check the sign flag. It should be M if BC >= DE and P otherwise, right? I haven't thought that one through at all - it's just a guess, so I may be wrong.
That wouldn’t be enough, because B can be so much greater than D that the difference goes below -128. You’d have to check the overflow flag too, and it would become rather complicated.
User avatar
qarnos
Maxcoderz Staff
Posts: 227
Joined: Thu 01 Dec, 2005 9:04 am
Location: Melbourne, Australia

Post by qarnos »

CoBB wrote:
qarnos wrote:Perhaps we could check the sign flag. It should be M if BC >= DE and P otherwise, right? I haven't thought that one through at all - it's just a guess, so I may be wrong.
That wouldn’t be enough, because B can be so much greater than D that the difference goes below -128. You’d have to check the overflow flag too, and it would become rather complicated.
I thought there'd be a gotcha in there somewhere. Oh well. :P
"I don't know why a refrigerator is now involved, but put that aside for now". - Jim e on unitedti.org

avatar courtesy of driesguldolf.
User avatar
Timendus
Calc King
Posts: 1729
Joined: Sun 23 Jan, 2005 12:37 am
Location: Netherlands
Contact:

Post by Timendus »

qarnos wrote:You can think of the carry flag from the ADD instruction as being the 9th bit of the result. When you do the ADC, you are carrying-over that bit into the high byte.
Yes, that's what I thought. but I never like to say "this will work" without actually running the code ;)
Edit: Though a smaller (3 bytes instead of 6) and faster (19 T-states versus 24) way to add DE and BC would be this:

Code: Select all

ex de, hl
add hl, bc
ex de, hl
Also, it's much easier for other people to read, because it makes more sense. So I should definately use this one, thanks!
Jim e wrote:

Code: Select all

    ex de,hl
    or a
    sbc hl,bc
    add hl,bc
    ex de,hl
Yes all the flags do match CP despite that add hl,bc being there. It doesn't use the stack nor is it very large so you can macro it.
So, the subtraction sbc hl,bc sets all the flags right and add hl,bc restores de without screwing up the flags? That sounds pretty good. In fact, I can probably just throw one value away after the comparison, and just do

Code: Select all

ex de,hl
or a
sbc hl,bc
ex de,hl
Is that or a really necessary, by the way? Doesn't sbc take care of the carry flag, or does it only set and not reset it?
http://clap.timendus.com/ - The Calculator Link Alternative Protocol
http://api.timendus.com/ - Make your life easier, leave the coding to the API
http://vera.timendus.com/ - The calc lover's OS
Post Reply