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?


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:

  • This is the starting condition where the program counter is zero and the stack pointer is 8000 (all these numbers are hexadecimal).
  • 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).
  • This pushes r0 onto the stack by reducing the stack pointer by two then storing the value of the register to that location.
  • 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.
  • This loads r1 from a memory location calculated from the stack pointer - it shows a way to pass parameters to functions.
  • 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).
  • Popping r0 off the stack involves extracting the value from where the stack pointer points then adjusting that stack pointer up.
  • 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  |
         |        |      |        |      |        |
         |        |      |        |      |        |
         |        |      |        |      |        |
         +--------+      +--------+      +--------+
    

    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


    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.

    链接地址: http://www.djcxy.com/p/80364.html

    上一篇: ASM函数调用返回地址

    下一篇: 什么是微处理器中使用的堆栈指针?