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 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 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.