Omnimaga

Calculator Community => TI Calculators => ASM => Topic started by: Runer112 on August 14, 2010, 01:00:53 pm

Title: Jumping to a variable entry in a jump table
Post by: Runer112 on August 14, 2010, 01:00:53 pm
I'm a little confused. Is there any good or "right" way to access a variable entry of a jump table (or a vector table, I don't really care which I use)? The only thing I can think of so far is cheating by calculating the address you want to jump to, pushing it onto the stack, and then using a return.
Title: Re: Jumping to a variable entry in a jump table
Post by: thepenguin77 on August 17, 2010, 11:35:12 am
This post got passed by by every one.  :( sad

Anyways, there are a few ways to access jump tables. I assume you don't know about the instuction jp (hl). It jumps to HL. It's not mentioned in asm in 28 days but it's really useful.

Here's an example that's all about speed.
Code: [Select]
;before hand
ld hl, tableStart
ld de, $8000
ld bc, tableEnd-tableStart
ldir

;super fast access
ld a, (toJump)
add a, a
add a, a
ld l, a
ld h, $80
jp (hl)

;the nops are there to make them 4 bytes
;but you could remove them and multiply by 3

tableStart:
jp lbl0
nop
jp lbl1
nop
jp lbl2
nop
jp lbl3
nop
jp lbl4
nop
tableEnd:

This kind of table is typically used in super fast sections, like drawing and such. You could simplify yours a lot by making it a .dw table and not aligning it to a $100 boundary. But I think all the magic you are looking for is in jp (hl). It's only 4 t-states to boot. There are also jp (ix) and jp (iy), but unless you use undocumented instructions, those are rather hard to use.
Title: Re: Jumping to a variable entry in a jump table
Post by: Runer112 on August 17, 2010, 04:17:01 pm
Thanks, I didn't know about jp (hl). My question is, why copy the jump table to $8000? Shouldn't I copy it to a location like $8700 (saveSScreen+16)?
Title: Re: Jumping to a variable entry in a jump table
Post by: Iambian on August 17, 2010, 05:07:41 pm
You could do that if you wanted to. It's just that $8000 is conveniently open for such a thing. And it's way easy to remember since it's the start of RAM.

If you avoid doing things like archiving or other things that might need $8000, it's safe to use for whatever you want. It's a nice 256 byte stretch of memory.
Title: Re: Jumping to a variable entry in a jump table
Post by: Runer112 on August 17, 2010, 06:21:45 pm
Wait, what exactly is at $8000?
Title: Re: Jumping to a variable entry in a jump table
Post by: calcdude84se on August 17, 2010, 06:32:31 pm
By the include file it's the start of ram and some field called "appdata"
I'm not really sure, though.
Title: Re: Jumping to a variable entry in a jump table
Post by: thepenguin77 on August 17, 2010, 07:17:08 pm
There's nothing permanent at $8000, it's used as scratch space by the OS for archiving. $8100 is also open up to $8180 as OS scratch space.
Title: Re: Jumping to a variable entry in a jump table
Post by: calc84maniac on August 17, 2010, 11:08:00 pm
And here's a demonstration of the .dw method (uses much less space and only slightly slower):

Code: [Select]
;A holds number of routine to jump to
ld hl,jumpTable
add a,a
add a,l
ld l,a
jr nc,$+3
inc h

ld a,(hl)
inc hl
ld h,(hl)
ld l,a
jp (hl)

jumpTable:
.dw Routine0
.dw Routine1
.dw Routine2
;...
;...
Title: Re: Jumping to a variable entry in a jump table
Post by: Quigibo on August 18, 2010, 02:34:02 am
Yet another alternative would be to create a value jump table which doesn't have to rely on ordered values, rather, on specific values.  Like let's say you need to jump to one place when a is 20, another place when its 60 and another place when it's 250.  You don't want to make a 250 valued jump table with lots of empty slots for only 3 labels.  This is an optimization I use a lot in Axe Parser for deciding what to do with each token.

Code: [Select]
;I use these series of macros to make the code more readable and easier to type
#define JTABLE call JumpTable
#define JT(xx,xxxx) .db xx \ .dw xxxx
#define JTEND .db 0


;'a' holds a value and you want to jump to the label associated with the value.
JTABLE
JT(value1,label1)
JT(value2,label2)
JT(value3,label3)
;...
;...
JTEND


;This is the jump table routine
JumpTable:
ex (sp),hl
push bc
ld b,a
JumpTableLoop:
ld a,(hl)
inc hl
or a
jr z,hJumpTableEnd
cp b
jr z,JumpTableEnd
inc hl
inc hl
jr JumpTableLoop
JumpTableEnd:
ld a,(hl)
inc hl
ld h,(hl)
ld l,a
hJumpTableEnd:
ld a,b
pop bc
ex (sp),hl
ret

I know the routine is much larger, but that's because it comes with a lot of other features and if you use it as often as I do, it really saves space in the program.  The advantages are that it preserves all registers in all cases and if the value did not match any of the jump values in your table, then the routine comes back and continues executing after JTEND.  By the way, you can't use 0 as a value for 'a' since that signifies the end of the table.  It probably could use some optimization too.