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

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

一个堆栈是一个LIFO(后进先出 – 你推入堆栈的最后一个条目是你popup时返回的第一个)数据结构,通常用于存放堆栈帧(属于当前的function)。

这包括但不限于:

  • 返回地址。
  • 一个返回值的地方。
  • 传递参数。
  • 局部variables。

你把物品推到堆叠上,然后popup。 在微处理器中,堆栈既可以用于用户数据(例如本地variables和传递的参数) 也可以用于CPU数据(例如调用子程序时的返回地址)。

堆栈的实际实现取决于微处理器架构。 它可以在内存中长大,也可以在push / pop操作之前或之后移动。

通常影响堆栈的操作是:

  • 子程序调用和返回。
  • 中断调用并返回。
  • 代码显式推送和popup条目。
  • 直接操纵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(所有这些数字均为hex)的起始条件。
  2. 这只是加载寄存器r0立即值7,并转移到下一步(我假设你明白默认行为将移动到下一步,除非另有规定)。
  3. 这通过将堆栈指针减less2来将r0推入堆栈,然后将该寄存器的值存储到该位置。
  4. 这就调用一个子程序。 程序计数器的内容按照与上一步中的r0类似的方式推入堆栈,然后将程序计数器设置为新值。 这与用户级别的推动没有什么不同,除了它作为一个系统级别的东西更多的事实。
  5. 这从从堆栈指针计算的内存位置加载r1 – 它显示了一种将parameter passing给函数的方法。
  6. return语句从堆栈指针指向的位置提取值并将其加载到程序计数器中,同时调整堆栈指针。 这就像系统级别的popup窗口(参见下一步)。
  7. 从堆栈中popupr0包括从堆栈指针指向的位置提取值,然后调整堆栈指针。
  8. 暂停指令简单地把程序计数器留在原来的地方,这是一个无限循环。

从这个描述中,希望会变得清楚。 底线是:堆栈对于以LIFO方式存储状态非常有用,这对于大多数微处理器执行子程序调用的方式来说通常是理想的。

除非你是SPARC ,否则在这种情况下,你使用循环缓冲区来处理你的堆栈:-)

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

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

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

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

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

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

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

你有更多的准备[考试]做;-)

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

堆栈是内存中的一个区域,用于存储堆栈,即LIFO(后进先出)types的容器,在这里我们存储局部variables和返回地址,允许简单地pipe理函数调用的嵌套一个典型的程序。

请参阅本维基百科文章 ,了解堆栈pipe理的基本说明。

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

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

阅读这一个更多的信息。

通用的使用堆栈指针寄存器

堆栈指针将地址保存到堆栈顶部。 堆栈允许函数将堆栈中存储的parameter passing给对方,并创build范围variables。 在这种情况下的范围意味着当堆栈帧消失时和/或函数返回时,variables被popup堆栈。 没有堆栈,你将需要使用显式内存地址的一切。 这将使得为该体系结构devise高级编程语言变得不可能(或者至less是非常困难)。 另外,每个CPU模式通常都有自己的堆栈指针。 所以当发生exception(例如中断)时,exception处理程序可以使用自己的堆栈,而不会破坏用户进程。

如果你想要更深入的了解,我衷心推荐帕特森和轩尼诗作为介绍, 轩尼诗和帕特森作为中级到高级文本。 他们是昂贵的,但真正的非pareil; 我只是希望在获得硕士学位之后,或者两者都可用,并进入为他们devise芯片,系统和系统软件部分的工作人员(但是,唉,这太早了!)。 堆栈指针非常重要(在这种情况下,微处理器与其他任何types的CPU之间的区别,或者在这种情况下,在任何其他环境下,在过去的几十年里……)我怀疑什么,但有一些彻底的从头开始复习可以帮助! – )

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

堆栈是一个后进先出(LIFO)内存。 通过PUSH指令将数据放入堆栈,并用POP指令删除。 堆栈存储器由两个寄存器维持:堆栈指针(SP)和堆栈段(SS)寄存器。 当一个数据字被压入堆栈时,高位8位字节被放置在位置SP-1中,而低位8位字节被放置在位置SP-2中。 然后,SP减2。SP增加到(SS×10H)寄存器,形成物理堆栈存储器地址。 数据从堆栈中popup时会发生相反的情况。 当一个数据字从堆栈popup时,在位置SP-1中获得高位8位字节,在位置SP-2中获得低位8位字节。 SP然后增加2。

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

虽然硬件堆栈确实有​​一些优点(例如,push和pop不会给call / return添加任何时间),但是具有可以加载两个源的寄存器会增加成本。 如果堆栈变得非常大,用可寻址的存储器replace推挽式寄存器会更便宜。 即使使用一个小的专用存储器,有32个可寻址寄存器和一个带有增量/减量逻辑的5位指针寄存器也比每个寄存器有两个input要便宜。 如果一个应用程序可能需要更多的堆栈而不是容易放在CPU上的堆栈,那么可以使用一个堆栈指针和逻辑来存储/读取主RAM中的堆栈数据。

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