GoTo from a Subroutine - how to decrease the return address stack?

Started by trastikata, Jul 20, 2021, 10:13 PM

Previous topic - Next topic

trastikata

Hello all,

Due to lack of memory space in my program I am calling a lot of Sub-routines (GoSub) however to simplify the code I would like to use GoTo commands from within the Sub-routine which I assume would require manually decreasing the return address stack before executing the GoTo command from within the Sub? Thus my question - if you can advise the simplest way of doing this?

P.s. I was wondering too how the compiler deals with GoTo command from inside a Procedure?

Thank you.

Stephen Moss

Quote from: trastikata on Jul 20, 2021, 10:13 PMI assume would require manually decreasing the return address stack before executing the GoTo command from within the Sub? Thus my question - if you can advise the simplest way of doing this?
That suggest to me that you are intending to use the GoTo to jump out of the Subroutine which is generally not a good idea.
Is there not a compatible device that has more memory? If so changing to such a device now is probably the best option as you may want to make changes to the program at a later time which would result in the modified code being to large to fit in the currently selected device.

If using another device is not an option then if you can be certain that the data currently at the top of the stack is the return address of the current subroutine/procedure then issuing the Pop command immediately before the GoTo should remove the return address from stack.

TimB

In the past when really pushed on an 8 stack device I did the following


bReturnLoc = cMyroutineR1
Goto mySub1
MyroutineR1:


mySub1:
....
....
...

If bReturnLoc = cMyroutineR1 then goto MyroutineR1

If bReturnLoc = cxxxx then goto xxxxR2






top204

The GoTo command within a procedure operates as a standard GoTo, but uses a local label name if there is one that matches within the procedure, otherwise, looks outside the procedure for a matching label.

The current 18F devices have a 31 level call stack, which is fine for every program I have created, even programs that have filled a microcontroller's code memory with their complexity.

I understand in detail how it works because I had to alter the call stack for the On GoSub command, and create a software stack for the old 12-bit core devices, but it is something I will not explain or give examples of because it is too dangerous to do unless the user has a detailed knowledge of the microcontroller's architecture, and experience has shown that "it is always the compilers at fault" when something goes wrong because a user made mistakes or altered low-level aspects. :-)

Manipulating the call stack is a very dangerous thing to do because if you get it slightly incorrect, the program will not work at all, but the fault will not appear straight away! The compiler's optimiser helps, in that if it sees a Call/Return, it will use a GoTo instead of the Call/Return so that the routine that was being called will perform the Return.

The newer 18F devices that I am currently working on adding to the compiler have a 128 level call stack, which makes things a lot better. The devices are the 18F05Q4x, 18F15Q4x types and the 18F06Q4x, 18F16Q4x types. They are difficult to add because they use a new asm mechanism, but I had my first running program on one of them the other night, after a few months of getting all the things in place.

trastikata

Quote from: top204 on Jul 21, 2021, 02:07 PMThe GoTo command within a procedure operates as a standard GoTo, but uses local label names if there is one that matches, otherwise, looks outside the procedure for a matching label.

Thanks Les, then I will convert the Sub's to Proc's in order to avoid troubles.

Quote from: top204 on Jul 21, 2021, 02:07 PMThe compiler's optimiser helps, in that if it sees a Call followed by Call/Return, it will use a GoTo instead of the Call/Return so that the routine that was being called will perform the Return.

If I understood well, as long as it is one level "deep" Subroutine with respect the GoTo address, the Optimizer will correct the stack for GoTo from within the Sub?

top204

It will not use the stack because the optimiser changes the assembler code before it is assembled.

For example:

MySub0:
GoSub MySub1
Return


The optimiser will change the underlying assembler code to the high-level equivalent of:

MySub0:
GoTo MySub1


Because MySub1 has a Return at the end of it, so 'it' will return from the call to MySub0.

This also applies to procedures, which are, essentially, self contained subroutines.

Picprogrammer

Quote from: trastikata on Jul 20, 2021, 10:13 PMHello all,

Due to lack of memory space in my program I am calling a lot of Sub-routines (GoSub) however to simplify the code I would like to use GoTo commands from within the Sub-routine which I assume would require manually decreasing the return address stack before executing the GoTo command from within the Sub? Thus my question - if you can advise the simplest way of doing this?

P.s. I was wondering too how the compiler deals with GoTo command from inside a Procedure?

Thank you.

You can remove the previous stack pointer by using the POP assembly command, essentially returning back 1 level of your nested gosubs. You could arguably do this X amount of times to ensure root level and eg. goto straight in to main loop.