What is a stack pointer used for in microprocessors?

I am preparing for a microprocessor exam. If the use of a program counter is to hold the address of the next instruction, what is use of stack pointer?


Solution 1:

A stack is a LIFO (last in, first out - the last entry you push on to the stack is the first one you get back when you pop) data structure that is typically used to hold stack frames (bits of the stack that belong to the current function).

This includes, but is not limited to:

  • the return address.
  • a place for a return value.
  • passed parameters.
  • local variables.

You push items onto the stack and pop them off. In a microprocessor, the stack can be used for both user data (such as local variables and passed parameters) and CPU data (such as return addresses when calling subroutines).

The actual implementation of a stack depends on the microprocessor architecture. It can grow up or down in memory and can move either before or after the push/pop operations.

Operation which typically affect the stack are:

  • subroutine calls and returns.
  • interrupt calls and returns.
  • code explicitly pushing and popping entries.
  • direct manipulation of the SP register.

Consider the following program in my (fictional) assembly language:

Addr  Opcodes   Instructions    ; Comments
----  --------  --------------  ----------
                                ; 1: pc<-0000, sp<-8000
0000  01 00 07  load r0,7       ; 2: pc<-0003, r0<-7
0003  02 00     push r0         ; 3: pc<-0005, sp<-7ffe, (sp:7ffe)<-0007
0005  03 00 00  call 000b       ; 4: pc<-000b, sp<-7ffc, (sp:7ffc)<-0008
0008  04 00     pop r0          ; 7: pc<-000a, r0<-(sp:7ffe[0007]), sp<-8000
000a  05        halt            ; 8: pc<-000a
000b  06 01 02  load r1,[sp+2]  ; 5: pc<-000e, r1<-(sp+2:7ffe[0007])
000e  07        ret             ; 6: pc<-(sp:7ffc[0008]), sp<-7ffe

Now let's follow the execution, describing the steps shown in the comments above:

  1. This is the starting condition where the program counter is zero and the stack pointer is 8000 (all these numbers are hexadecimal).
  2. This simply loads register r0 with the immediate value 7 and moves to the next step (I'll assume that you understand the default behavior will be to move to the next step unless otherwise specified).
  3. This pushes r0 onto the stack by reducing the stack pointer by two then storing the value of the register to that location.
  4. This calls a subroutine. What would have been the program counter is pushed on to the stack in a similar fashion to r0 in the previous step and then the program counter is set to its new value. This is no different to a user-level push other than the fact it's done more as a system-level thing.
  5. This loads r1 from a memory location calculated from the stack pointer - it shows a way to pass parameters to functions.
  6. The return statement extracts the value from where the stack pointer points and loads it into the program counter, adjusting the stack pointer up at the same time. This is like a system-level pop (see next step).
  7. Popping r0 off the stack involves extracting the value from where the stack pointer points then adjusting that stack pointer up.
  8. Halt instruction simply leaves program counter where it is, an infinite loop of sorts.

Hopefully from that description, it will become clear. Bottom line is: a stack is useful for storing state in a LIFO way and this is generally ideal for the way most microprocessors do subroutine calls.

Unless you're a SPARC of course, in which case you use a circular buffer for your stack :-)

Update: Just to clarify the steps taken when pushing and popping values in the above example (whether explicitly or by call/return), see the following examples:

LOAD R0,7
PUSH R0
                     Adjust sp       Store val
sp-> +--------+      +--------+      +--------+
     |  xxxx  |  sp->|  xxxx  |  sp->|  0007  |
     |        |      |        |      |        |
     |        |      |        |      |        |
     |        |      |        |      |        |
     +--------+      +--------+      +--------+

POP R0
                     Get value       Adjust sp
     +--------+      +--------+  sp->+--------+
sp-> |  0007  |  sp->|  0007  |      |  0007  |
     |        |      |        |      |        |
     |        |      |        |      |        |
     |        |      |        |      |        |
     +--------+      +--------+      +--------+

Solution 2:

The stack pointer stores the address of the most recent entry that was pushed onto the stack.

To push a value onto the stack, the stack pointer is incremented to point to the next physical memory address, and the new value is copied to that address in memory.

To pop a value from the stack, the value is copied from the address of the stack pointer, and the stack pointer is decremented, pointing it to the next available item in the stack.

The most typical use of a hardware stack is to store the return address of a subroutine call. When the subroutine is finished executing, the return address is popped off the top of the stack and placed in the Program Counter register, causing the processor to resume execution at the next instruction following the call to the subroutine.

http://en.wikipedia.org/wiki/Stack_%28data_structure%29#Hardware_stacks

Solution 3:

You got more preparing [for the exam] to do ;-)

The Stack Pointer is a register which holds the address of the next available spot on the stack.

The stack is a area in memory which is reserved to store a stack, that is a LIFO (Last In First Out) type of container, where we store the local variables and return address, allowing a simple management of the nesting of function calls in a typical program.

See this Wikipedia article for a basic explanation of the stack management.

Solution 4:

For 8085: Stack pointer is a special purpose 16-bit register in the Microprocessor, which holds the address of the top of the stack.

The stack pointer register in a computer is made available for general purpose use by programs executing at lower privilege levels than interrupt handlers. A set of instructions in such programs, excluding stack operations, stores data other than the stack pointer, such as operands, and the like, in the stack pointer register. When switching execution to an interrupt handler on an interrupt, return address data for the currently executing program is pushed onto a stack at the interrupt handler's privilege level. Thus, storing other data in the stack pointer register does not result in stack corruption. Also, these instructions can store data in a scratch portion of a stack segment beyond the current stack pointer.

Read this one for more info.

General purpose use of a stack pointer register

Solution 5:

The Stack is an area of memory for keeping temporary data. Stack is used by the CALL instruction to keep the return address for procedures The return RET instruction gets this value from the stack and returns to that offset. The same thing happens when an INT instruction calls an interrupt. It stores in the Stack the flag register, code segment and offset. The IRET instruction is used to return from interrupt call.

The Stack is a Last In First Out (LIFO) memory. Data is placed onto the Stack with a PUSH instruction and removed with a POP instruction. The Stack memory is maintained by two registers: the Stack Pointer (SP) and the Stack Segment (SS) register. When a word of data is PUSHED onto the stack the the High order 8-bit Byte is placed in location SP-1 and the Low 8-bit Byte is placed in location SP-2. The SP is then decremented by 2. The SP addds to the (SS x 10H) register, to form the physical stack memory address. The reverse sequence occurs when data is POPPED from the Stack. When a word of data is POPPED from the stack the the High order 8-bit Byte is obtained in location SP-1 and the Low 8-bit Byte is obtained in location SP-2. The SP is then incremented by 2.