Hi Al,
I hereby send you the final outcomings of the program calling issue. It presents a stack mechanism for the Basic Stamp BS2SX, BS2E and BS2P. Maybe you are willing to put it on the faq list so others can benefit from it.
Multilevel stack design and usage for Basic Stamp BS2SX, BS2E and BS2P using the scratchpad.
Many thanks to Tracy Allen for all his input and positive suggestions.
This design uses the available scratchpad to hold a multilevel stack that can be used to call functions (with parameters if required) in other programs and to create named local variables for use within gosubs. It shows a general program setup that can be used as a template.
Features: up to 32 entry/return points per program nested program calls parameter passing via stack named local variables for subroutines
Limitations: program calls can only execute at main level code outside for-next loops. names for local variables must be unique as they are seen as aliases no stackpointer check
'scratchpad usage (TOS stands for Top Of Stack)
'TOS-0 = entryID/runID 1
'TOS-1 = entryID/runID 2
'TOS-2 = entryID/runID 3
'etc.
'program 0
TopOfStack1 con 62 'top of stack for BS2SX, BS2E
TopOfStack2 con 126 'top of stack for BS2P
TOS con TopOfStack2 'pick the right top of stack
STACKSIZE con 30 'define stacksize
BOS con TOS-STACKSIZE 'bottom of stack
EN1P0 con (1<<3)+0 'entry01 in program 0
EN2P0 con (2<<3)+0 'entry02 in program 0
EN3P0 con (3<<3)+0 'entry03 in program 0
EN4P0 con (4<<3)+0 'entry04 in program 0
EN5P0 con (5<<3)+0 'entry05 in program 0
EN4P3 con (4<<3)+4 'entry 4 in program 3
EN14P4 con (14<<3)+4 'entry 14 in program 4
EN6P7 con (6<<3)+7 'entry 6 in program 7
'system variables
TargetID var byte 'entry index and program to run
runID var TargetID.lownib 'entry index b0, program to run
entryID var TargetID.highnib 'entry index b4-b1
StackPointer var byte 'stackpointer
'application variables
x var byte
y var byte
z var byte
ProgramID con 0
begin0: branch (TargetID>>3),[main0,entry01,netry02,...,entry1F]'first entry for direct run
main0: StackPointer=TOS 'insert init code here
main0loop: 'insert mainloop code here
z=0
call_loop_example: '1st program call example, stackpointer check could be placed here
put StackPointer,EN1P0
StackPointer=StackPointer-1
TargetID=EN14P4
run TargetID 'execute entry 14 in program 4, then return to entry01
entry01: 'return point for call
z=z+1
if z<10 then call_loop_example
'insert mainloop code here
'2nd call example, stackpointer check could be placed here
put StackPointer,x 'first put parameters onto stack
put StackPointer-1,y
put StackPointer-2,EN2P0 'then put return point
StackPointer=StackPointer-3
TargetID=EN6P7
run TargetID 'execute entry 6 in program 7, then return to entry02
entry02: 'return point for call
get StackPointer+2,x 'retrieve results
get StackPointer+1,y
StackPointer=StackPointer+2 'remove results from stack
'insert mainloop code here
'direct run example
TargetID=$03
run TargetID 'run program 3 directly (no call but jump)
'insert mainloop code here
main0end: goto main0loop
'function entries for program calls
entry03: gosub function_03
put StackPointer,EN4P3
StackPointer=StackPointer-1
TargetID=EN4P0
run TargetID 'execute entry 14 in program 4, then return to entry04
entry04: 'return point for call
goto ReturnFromProgramCall_0
entry05: get StackPointer+3,x 'get parameters from stack
get StackPointer+2,y
gosub function_04 'perform some math on x and y, results in x and y
put StackPointer+3,x 'place results on stack
put StackPointer+2,y
goto ReturnFromProgramCall_0
ReturnFromProgramCall_0:
StackPointer=StackPointer+1 'adjust stack here
get StackPointer,TargetID 'get TargetID
run TargetID 'return to parent program
'subroutines
function_03:
gosub alloc4 'allocate 4 bytes for local variables
x1 var W12 'local word variable
y1 var B23 'local byte variable
'code here
goto free4 'free local variables and return from gosub
function_04:
'code here
return
alloc8: put StackPointer,B18
'space is allocated from B25 upwards
put StackPointer-1,B19
put StackPointer-2,B20
put StackPointer-3,B21
StackPointer=StackPointer-4
alloc4: put StackPointer,B22
put StackPointer-1,B23
put StackPointer-2,B24
put StackPointer-3,B25
StackPointer=StackPointer-4
return
free8: get StackPointer+8,B18
get StackPointer+7,B19
get StackPointer+6,B20
get StackPointer+5,B21
get StackPointer+4,B22
get StackPointer+3,B23
get StackPointer+2,B24
get StackPointer+1,B25
StackPointer=StackPointer+8
return
free4: get StackPointer+4,B22
get StackPointer+3,B23
get StackPointer+2,B24
get StackPointer+1,B25
StackPointer=StackPointer+4
return
end