simple Icall question

Go To Last Post
3 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello:

I am trying to make a jump (to subroutines) using ICALL. I am assuming the corresponding return instruction is simply ret. is this true?
My code seems to lock up--if I kill the Icall all is well!! any thoughts?

ldi ZH, high(actions*2) ;get address of command check string
ldi ZL, low (actions*2)
mov temp, routine_to_do ;specify which subroutine to run
lsl temp ;mult by 2 to for word address
add ZL,temp ;point to table address (base +2*cmdnum)
clr temp
adc ZH,temp ;propogate carry
icall ;execute valid cmd subroutine
more code--seems to never come back here/locks up

routine0: ret ;right now routines do nothing but return
routine1: ret
actions: dw routine0, routine1

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You are calculating the pointer to your table, of function addresses... but you are never loading the address in the table back into Z for ICALL to use. So instead you are jumping to an unexpected location in flash.

ICALL will interpret the address in Z as a word address, though when you execute ICALL, it holds the byte address of the entry in the function table you should be loading, so you are really jumping to (base + 2 * cmdnum)*2.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I usually create a rjmp table holding the actions addresses so ican use a byte pointer:

ldi ZH, high(actions*2) ;get address of command check string
ldi ZL, low (actions*2)
mov temp, routine_to_do ;specify which subroutine to run
add ZL,temp ;point to table address
clr temp
adc ZH,temp ;propogate carry
icall ;execute valid cmd subroutine
more code

actions:
rjmp routine0
rjmp routine1
rjmp routine2

routine0: ret
routine1: ret
routine2: ret