A question about conditional jumps in ASM

The place for codemasters or beginners to talk about programming any language for the Spectrum.
Post Reply
User avatar
Alessandro
Dynamite Dan
Posts: 1910
Joined: Wed Nov 15, 2017 11:10 am
Location: Messina, Italy
Contact:

A question about conditional jumps in ASM

Post by Alessandro »

I have got a question about conditional jumps in Z80 Assembly.

Sinclair BASIC allows jumps towards a part of a program if one of multiple conditions is met, like in this example:

Code: Select all

  10 IF a = 5 OR a = 10 OR a = 11 OR a = 12 OR a = 20 THEN GO TO 100
In order to do the same in Z80 Assembly, the first option I could think of would be:

Code: Select all

  LD A,(ADDRESS)
  CP 5
  JP Z, DESTINATION
  CP 10
  JP Z, DESTINATION
  CP 11
  JP Z, DESTINATION
  CP 12
  JP Z, DESTINATION
  CP 20
  JP Z, DESTINATION
(JR Z if DESTINATION is close enough, just to save some bytes; speed is not important here)

This would do the job but looks rather cumbersome and excessively long to me.

Does anyone know whether there is a more efficient way to do it?
User avatar
Morkin
Bugaboo
Posts: 3277
Joined: Mon Nov 13, 2017 8:50 am
Location: Bristol, UK

Re: A question about conditional jumps in ASM

Post by Morkin »

...I'd probably do it exactly like that, which probably means it probably IS cumbersome :lol:

I'd say it's essentially the same as the BASIC version, just written vertically written rather than horizontally. Also it's easy to read and understand if you come back to the code at a later date. Assuming you put comments in of course for the CP lines.
My Speccy site: thirdharmoniser.com
AndyC
Dynamite Dan
Posts: 1409
Joined: Mon Nov 13, 2017 5:12 am

Re: A question about conditional jumps in ASM

Post by AndyC »

That's not a bad way if you have only a handful of options. If it gets longer/more complex it may be better to have a jump table of addresses and look it up in there. Or rearrange things so you're dealing with ranges rather than comparing every individual values etc.
catmeows
Manic Miner
Posts: 718
Joined: Tue May 28, 2019 12:02 pm
Location: Prague

Re: A question about conditional jumps in ASM

Post by catmeows »

What AndyC saíd. This particular case could be shorter if you test range 10..12.
Proud owner of Didaktik M
User avatar
Joefish
Rick Dangerous
Posts: 2059
Joined: Tue Nov 14, 2017 10:26 am

Re: A question about conditional jumps in ASM

Post by Joefish »

The direct translation of the BASIC would be way longer. It would test each case in turn, get a TRUE/FALSE result, OR it to a cumulative result, then test that and decide whether or not to jump at the end. Since it's all ORs, it should be smart enough to skip over any remaining tests once one comes up true, but that logic means twice as many tests to code. Yours is by far the more efficient version.
User avatar
MustardTiger
Microbot
Posts: 122
Joined: Tue May 02, 2023 8:05 pm

Re: A question about conditional jumps in ASM

Post by MustardTiger »

If you know the value is more often going to be greater than 20 you can compare that first and skip the other compares.

cp 21
jr nc,SkipAllCompares
highrise
Manic Miner
Posts: 305
Joined: Fri Mar 20, 2020 11:29 pm

Re: A question about conditional jumps in ASM

Post by highrise »

you could try this:
ld a,(address)
ld b,5
ld hl,testlist
testloop:
cp (hl)
jr z,destination
inc hl
djnz testloop

...no match code here


and then:

testlist: 5,10,11,12,15
Ralf
Rick Dangerous
Posts: 2289
Joined: Mon Nov 13, 2017 11:59 am
Location: Poland

Re: A question about conditional jumps in ASM

Post by Ralf »

What do you mean by "efficient" Alessandro if speed is not important?

You know, people usually optimize their code just by speed of execution.
Another way is to optimize by size of the code.

Or do you want the code just to look "pretty"? Whatever that means ;)
User avatar
Joefish
Rick Dangerous
Posts: 2059
Joined: Tue Nov 14, 2017 10:26 am

Re: A question about conditional jumps in ASM

Post by Joefish »

As @MustardTiger says, you can do one initial test to skip the lot, which will often be quicker.
You could also change the order of the tests so more common results are tested for first. That could make your code run faster on average.

But if it's just the way it's written, then an assembly listing will often look longer or more complicated or even more repetitive than BASIC, but it's pretty much always going to be asking the CPU to do less work overall.
AndyC
Dynamite Dan
Posts: 1409
Joined: Mon Nov 13, 2017 5:12 am

Re: A question about conditional jumps in ASM

Post by AndyC »

Indeed. Even in the worst case scenario (no jump at all) that code is probably many times faster than BASIC even parsing that single line of code, let alone running it.
User avatar
Pobulous
Dynamite Dan
Posts: 1366
Joined: Wed Nov 15, 2017 12:51 pm

Re: A question about conditional jumps in ASM

Post by Pobulous »

If there are a lot of valid values close together, you could do this:

LD A,(Address)
LD H, jumptable%256
LD L,A
ADD HL,HL
LD A,(HL)
INC L
LD H,(HL)
LD L,A
JP (HL)

jumptable: ;aligned on 256 byte boundary
DW Address0
DW Address1
DW Address2

etc
User avatar
Morkin
Bugaboo
Posts: 3277
Joined: Mon Nov 13, 2017 8:50 am
Location: Bristol, UK

Re: A question about conditional jumps in ASM

Post by Morkin »

I think in Alessandro's example all matches jump to the same address, so probably wouldn't need an address lookup.

Got me thinking though, I wonder how early this method (the Pobulous HL address lookup) started being used for Speccy games?
My Speccy site: thirdharmoniser.com
User avatar
Alessandro
Dynamite Dan
Posts: 1910
Joined: Wed Nov 15, 2017 11:10 am
Location: Messina, Italy
Contact:

Re: A question about conditional jumps in ASM

Post by Alessandro »

Thank you all for your feedback and suggestions.

Actually, in my case there are no values that can be recurring more often than others; they all depend from the user's choices. @highrise 's suggestion is interesting, and I had thought about a sort of value table, but the values which drive the program's flow towards the same directions are in my case no more than about ten, it's the code itself that is programmed in order to "decide" at start what to do according to that value. After considering your indications, I think the repetition of CP ... JP Z, ... instructions is, for my purposes, the faster and more compact solution; I shall keep it, then :)
Timmy
Manic Miner
Posts: 230
Joined: Sat Apr 23, 2022 7:13 pm
Location: The Netherlands

Re: A question about conditional jumps in ASM

Post by Timmy »

My advice is that, if you have 5 conditions to test, then just test all 5 conditions. It's not worth the time to rewrite it, and it's easier to change later when the conditions change.

If you have, for example, 200 conditions to check, then there could be other more efficient ways.
User avatar
deanysoft
Dizzy
Posts: 75
Joined: Sat Jun 18, 2022 10:35 pm

Re: A question about conditional jumps in ASM

Post by deanysoft »

here's one more way that I use that is useful if the number of choices is limited, contiguous and zero or 1 based (so not useful for the original question but for anyone who's interested...)

ld a,(valueToTest)
and a ; 0?
jr z,destination ; yes...
dec a ; 1?
jr z,destination ; yes...
dec a ; 2?
jr z,destination ; yes...
etc...

obviously the more entries you need, the slower it'll be further down the list and yes, not elegant but in assembly it's all horses for courses
highrise
Manic Miner
Posts: 305
Joined: Fri Mar 20, 2020 11:29 pm

Re: A question about conditional jumps in ASM

Post by highrise »

as with all things assembly, there are many different ways to achieve the same thing which may be better depending on the context, but here is another alternative, if you don't mind using the registers:

ld a,(address)
ld bc,$050A
ld de,$0b0c
ld hl,$0f14

cp b
jr z,dest
cp c
jr z,dest
cp d
jr z,dest

...etc
User avatar
Pobulous
Dynamite Dan
Posts: 1366
Joined: Wed Nov 15, 2017 12:51 pm

Re: A question about conditional jumps in ASM

Post by Pobulous »

With 0-15 as possibles you could use rra to do a binary search, which would be more similar in slowest to fastest path, than AND and DEC (off the telly?).
Anything bigger and the lookup table is definitely quicker and shorter

rra
jr c, xxx1
rra
jr c, xx10
rra
jr c, x100
rra
jr c, addr1000
jr addr0000

xxx1:
rra
jr c, xx11
rra
jr c, x101
rra
jr c, addr1001
jr addr0001

xx10:
rra
jr c, x110
rra
jr c, addr1010
jr addr0010

xx11:
rra
jr c, x111
rra
jr c, addr1011
jr addr0011

x100:
rra
jr c, addr1100
jr addr0100

x101:
rra
jr c, addr1101
jr addr0101

x110:
rra
jr c, addr1110
jr addr0110

x111:
rra
jr c, addr1111
jr addr0111
User avatar
Einar Saukas
Bugaboo
Posts: 3147
Joined: Wed Nov 15, 2017 2:48 pm

Re: A question about conditional jumps in ASM

Post by Einar Saukas »

highrise wrote: Mon May 15, 2023 11:09 am you could try this:
ld a,(address)
ld b,5
ld hl,testlist
testloop:
cp (hl)
jr z,destination
inc hl
djnz testloop

...no match code here


and then:

testlist: 5,10,11,12,15
Same as:

ld a,(address)
ld bc,5
ld hl,testlist
cpir
jr z,destination

...no match code here

testlist: db 5,10,11,12,20
Post Reply