5.7.2.2 Software Stack Operation
A software stack is a dynamic allocation of memory that is used for automatic storage duration objects and which is indirectly accessed via a stack pointer. Although access of objects on a software stack can be slower, functions which use a software stack are reentrant. This form of stack is available only for Enhanced Mid-range and PIC18 devices.
As functions are called, they allocate a chunk of memory for their stack-based objects and the stack grows in memory. When the function exits, the memory it claimed is released and made available to other functions. Thus, a software stack has a size that is dynamic and varies as the program is executed. The stack grows up in memory, toward larger addresses, when objects are allocated to the stack; it decreases in size when a function returns and its stack-based objects are no longer required.
A register, known as the stack pointer, is permanently assigned to hold the address of the “top” of the stack. MPLAB XC8 uses the FSR1 register as the stack pointer, and it holds the address of the next free location in the software stack. The register contents are increased when variables are allocated (pushed) to the stack and decreased when a function returns and variables are removed (popped) from the stack. There is no register assigned to hold a frame pointer. All access to the stack must use an offset to the stack pointer.
Note that if there are any functions in the program that use the software stack, the FSR1 register is reserved as the stack pointer for the duration of the entire program, even when executing functions that do not use the software stack. With this register unavailable for general use, the code generated may be less efficient or “Can’t generate code” errors may result.
The maximum size of the stack is not exactly known at compile time and the
compiler typically reserves as much space as possible for the stack to grow during program
execution. The stack is always allocated a single memory range, which may cross bank
boundaries, but within this range it may be segregated into one area for main-line code and
an area for each interrupt routine, if required. The maximum size of each area can be
specified using the -mstack
option (see 4.6.1.23 Stack Option). The stack pointer is
reloaded when an interrupt occurs so it will access the separate stack area used by
interrupt code. It is restored by the interrupt context switch code when the interrupt
routine is complete.
The stack will be assigned a location that makes the best use of the available free memory,
but it can be repositioned if required. The stack
psect is used as a
placeholder for the stack and this is typically linked into the STACK
linker class, whose memory range is dictated by the values specified for the maximum stack
size in the -mstack
option. The linker's -A
option
defining the STACK
class can be overridden, if desired, provided the new
memory range does not interfere with any other linking requirement of the program. See
4.6.11.8 Wl: Pass Option To The Linker,
Option to see how
default linker options can be overridden. Typically you might change the stack location
when the reserved stack is small and you need to force it to a fixed location, or to
locations that are within a confined memory range.
The compiler cannot detect for overflow of the memory reserved for the stack as a whole, nor are any runtime checks made for stack overflow. If the software stack overflows, data corruption and code failure can result.