什么是用于微处理器的堆栈指针?

时间:2009-09-23 04:56:09

标签: stack microprocessors

我正准备进行微处理器考试。如果使用程序计数器来保存下一条指令的地址,那么堆栈指针的用途是什么?

9 个答案:

答案 0 :(得分:89)

堆栈是一个LIFO(最后输入,第一个输出 - 你输入堆栈的最后一个条目是你弹出时得到的第一个条目)数据结构,通常用于保存堆栈帧(堆栈的位)属于当前的功能)。

这包括但不限于:

  • 返回地址。
  • 返回值的地方。
  • 传递参​​数。
  • 局部变量。

将物品推入堆叠并将其弹出。在微处理器中,堆栈可用于用户数据(例如局部变量和传递的参数) CPU数据(例如调用子例程时的返回地址)。

堆栈的实际实现取决于微处理器架构。它可以在内存中增长或减少,并且可以在推/弹操作之前或之后移动。

通常影响堆栈的操作是:

  • 子程序调用并返回。
  • 中断呼叫并返回。
  • 代码明确地推送和弹出条目。
  • 直接操纵SP寄存器。

以我的(虚构的)汇编语言考虑以下程序:

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

现在让我们按照执行情况,描述上面评论中显示的步骤:

  1. 这是程序计数器为零且堆栈指针为8000(所有这些数字都是十六进制)的起始条件。
  2. 这只是将寄存器r0加载到立即值7并移动到下一步(我假设您理解默认行为将转移到下一步,除非另有说明)。
  3. 通过将堆栈指针减少2,然后将寄存器的值存储到该位置,将r0推入堆栈。
  4. 这会调用子程序。 作为程序计数器的内容以与上一步骤中的r0类似的方式被推入堆栈,然后程序计数器被设置为其新值。这与用户级推送没有什么不同,除了它更多地作为系统级别的事情。
  5. 从堆栈指针计算的内存位置加载r1 - 它显示了将参数传递给函数的方法。
  6. return语句从堆栈指针指向的位置提取值并将其加载到程序计数器中,同时调整堆栈指针。这就像系统级弹出(见下一步)。
  7. 从堆栈弹出r0涉及从堆栈指针指向的位置提取值,然后调整堆栈指针。
  8. 暂停指令只会让程序计数器保持原样,无限循环。
  9. 希望从这个描述中,它会变得清晰。底线是:堆栈对于以LIFO方式存储状态很有用,这通常是大多数微处理器进行子程序调用的理想选择。

    除非你当然是SPARC,否则你在堆栈中使用循环缓冲区: - )

    更新:为了澄清在上面的示例中推送和弹出值所采取的步骤(无论是显式还是通过调用/返回),请参阅以下示例:

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

答案 1 :(得分:11)

堆栈指针存储推入堆栈的最新条目的地址。

要将值压入堆栈,堆栈指针会递增以指向下一个物理内存地址,新值将复制到内存中的该地址。

要从堆栈中弹出一个值,将从堆栈指针的地址复制该值,并递减堆栈指针,将其指向堆栈中的下一个可用项目。

硬件堆栈最典型的用途是存储子程序调用的返回地址。当子程序执行完毕后,返回地址从堆栈顶部弹出并放入程序计数器寄存器,使处理器在调用子程序后的下一条指令处继续执行。

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

答案 2 :(得分:6)

你准备[考试]准备了更多; - )

堆栈指针是一个寄存器,用于保存堆栈中下一个可用点的地址。

堆栈是内存中的一个区域,用于存储堆栈,即LIFO(后进先出)类型的容器,我们存储局部变量和返回地址,允许简单管理堆栈函数调用典型程序。

有关堆栈管理的基本说明,请参阅此Wikipedia article

答案 3 :(得分:3)

对于8085:堆栈指针是微处理器中的一个专用16位寄存器,它保存堆栈顶部的地址。

计算机中的堆栈指针寄存器可供在中断处理程序以较低权限级别执行的程序使用。除了堆栈操作之外,这些程序中的一组指令将堆栈指针以外的数据(例如操作数等)存储在堆栈指针寄存器中。当在中断上将执行切换到中断处理程序时,当前正在执行的程序的返回地址数据将在中断处理程序的特权级别被压入堆栈。因此,将其他数据存储在堆栈指针寄存器中不会导致堆栈损坏。此外,这些指令可以将数据存储在超出当前堆栈指针的堆栈段的暂存部分中。

阅读本文以获取更多信息。

<强> General purpose use of a stack pointer register

答案 4 :(得分:2)

堆栈是用于保存临时数据的内存区域。 CALL指令使用堆栈来保留过程的返回地址返回RET指令从堆栈中获取该值并返回到该偏移量。当INT指令调用中断时,会发生同样的事情。它在堆栈中存储标志寄存器,代码段和偏移量。 IRET指令用于从中断调用返回。

堆栈是后进先出(LIFO)内存。使用PUSH指令将数据放入堆栈,并使用POP指令删除。堆栈存储器由两个寄存器维护:堆栈指针(SP)和堆栈段(SS)寄存器。当数据字被推入堆栈时,高阶8位字节被放置在位置SP-1中,低8位字节被放置在位置SP-2中。然后SP递减2. SP加到(SS x 10H)寄存器,形成物理堆栈存储器地址。当数据从堆栈POPPED时发生相反的顺序。当从堆栈中对数据字进行POPPED时,在位置SP-1中获得高阶8位字节,在位置SP-2中获得低8位字节。然后SP增加2。

答案 5 :(得分:1)

堆栈指针将地址保存到堆栈顶部。堆栈允许函数将存储在堆栈中的参数相互传递,并创建作用域变量。此上下文中的范围意味着当堆栈帧消失时和/或函数返回时,变量将从堆栈中弹出。没有堆栈,您需要为所有内容使用显式内存地址。这将使得为架构设计高级编程语言变得不可能(或至少非常困难)。 此外,每个CPU模式通常都有自己的存储堆栈指针。因此,当异常发生时(例如中断),异常处理程序例程可以使用自己的堆栈而不会破坏用户进程。

答案 6 :(得分:1)

如果您渴望更深入的理解,我衷心建议Patterson and Hennessy作为介绍,Hennessy and Patterson作为高级文本的中间人。它们价格昂贵,但真正的非pareil;我希望当我获得硕士学位并进入为他们设计芯片,系统和系统软件部分的劳动力时,其中一个或两个都可用(但是,唉!,那是很久以前的方式;-)。堆栈指针是如此重要(并且微处理器和任何其他类型的CPU之间的区别在这种情况下非常有意义......或者,就此而言,在任何其他情况下,在过去几十年......! - )我怀疑什么,但是一些彻底的从头开始的复习可以帮助! - )

答案 7 :(得分:0)

在某些CPU上,堆栈有一组专用寄存器。当执行调用指令时,一个寄存器加载程序计数器,同时第二个寄存器加载第一个,第三个寄存器加载第二个,第四个加载第三个,等等。当执行返回指令时,程序计数器与第一个堆栈寄存器的内容锁存,同时该寄存器从第二个寄存器锁存;第二个寄存器是从第三个加载的,等等。请注意,这样的硬件堆栈往往相当小(例如,许多较小的PIC系列微处理器具有两级堆栈)。

虽然硬件堆栈确实具有一些优势(例如,推送和弹出不会为调用/返回添加任何时间),但是具有可以加载两个源的寄存器会增加成本。如果堆栈变得非常大,用可寻址存储器替换推挽寄存器会更便宜。即使使用一个小的专用存储器,使用32个可寻址寄存器和一个带递增/递减逻辑的5位指针寄存器比使用32个寄存器(每个寄存器有两个输入)更便宜。如果一个应用程序可能需要更多堆栈而不是容易适合CPU,那么就可以使用堆栈指针和逻辑来存储/从主RAM中获取堆栈数据。

答案 8 :(得分:0)

堆栈指针是一个小寄存器,用于存储堆栈顶部的地址。它用于指向堆栈顶部的地址。

相关问题