热门问题
时间线
聊天
视角

堆叠暂存器

来自维基百科,自由的百科全书

Remove ads

堆叠暂存器微处理器中,处理呼叫堆叠暂存器。在以累加器为基础的处理器中,堆叠暂存器可能是某个特定的暂存器。若是有多个通用暂存器的处理器架构,堆叠暂存器可能是某个依惯例保留的暂存器,像是IBM System/360z/Architecture英语z/Architecture架构以及RISC架构,也有可能是用副程式呼叫或程式返回指令,硬编码的暂存器,例如PDP-11VAXIntel x86架构。有些处理器(像Data General Eclipse英语Data General Eclipse)没有专用的堆叠暂存器,而是用保留的硬体记忆体位置来处理此功能。

在1960年末期以前的处理器(例如PDP-8HP 2100英语HP 2100)没有可以支援递归呼叫的编译器。其程序呼叫指令会将目前程式指标位置储存在跳跃地址,接著将程式指标设定为下一个位置[1]。此作法比维护堆叠简单,因为每一个副程式只会有一个返回位址,但除非程式作大幅相关更动,此作法无法支援递归呼叫。

堆叠结构机器(Stack machine)可能会有二个或多个堆叠暂存器,其中有一个处理呼叫堆叠,其他暂存器则处理其他堆栈

Remove ads

x86的堆叠暂存器

x86架构16位元的处理器里,主堆叠暂存器是16位元的堆叠指标(Stack Pointer,SP), 32位元的IA-32里,扩展为32位元的扩展堆叠指标(Extended Stack Pointer, ESP),64位元的X86-64里,扩展为64位元的暂存器堆叠指标(Register Stack Pointer,RSP)。堆叠区段暂存器(stack segment register,SS)会储存目前执行程式呼叫堆叠记忆体分段相关资讯。SP会指向目前堆叠的最顶端。预设情形,堆叠会以记忆体减少的方式成长,因此比较新的资料会放在较低的记忆体位置。PUSH指令可以将值存在堆叠里,因此堆叠会增加一个资料,POP指令可以提取堆叠中的资讯,并且堆叠会减少一笔资料。

假设SS = 1000h,SP = 0xF820,这表示目前的堆叠顶是在实体地址0x1F820(这是因为Intel 8086的记忆体分区机制),接下来的二个机器码是

PUSH AX
PUSH BX
  • 第一个指令会将AX(16位元暂存器)的值放在堆叠内,SP数值会减2。
  • 新的SP值是0xF81E。CPU会将AX的值复制到0x1F81E.
  • 执行PUSH BX时,会设定SP为0xF81C,将BX的值复制到0x1F81C[2]

上述就是PUSH运作的原理。一般来说,程式将暂存器的资料PUSH到堆叠是有其目的,例如呼叫会更改暂存器值的副程式。若要提取堆叠中的程式,可以用以下的机器码

POP BX
POP AX
  • POP BX将0x1F81C位置的字元(是BX原来的值)复制到BX,接著将SP加2,SP值是0xF81E。
  • POP AX将0x1F81E位置的字元复制到AX,接著将SP加2,SP值是0xF820[nb 1][nb 2]
Remove ads

堆叠机

较简单的处理器会将堆叠指标储存在一般的硬体暂存器,用算术逻辑单元(ALU)来处理其数值。一般来说push和pop会翻译为多个微指令,去增加或减少堆叠指标,处理记忆体的读取和写入[3]

较新的处理器会有专用的堆叠机(stack engine)以最佳化堆叠操作。Intel的Pentium M是第一个有堆叠机的x86处理器,其实现方式是将堆叠指标分为两个暂存器:ESPO是32位元的暂存器,ESPd是8位元的偏移值,会依堆叠操作而更新其数值。PUSH、POP、CALL和RET微指令直接对ESPd运作。若If ESPd接近溢位,或是ESP暂存器被其他指令更新(而ESPd ≠ 0),此时会插入同步的微指令,用ALU更新ESPO,并且让ESPd为0。在后续的Intel处理器中,此机制大致保留,不过将ESPO扩充到64位元[4]

AMD K8微处理器使用一种类似于Intel堆叠机的作法。在其推土机微架构中,不需要加入同步的微指令,但不清楚其堆叠机的内部设计[4]

Remove ads

注解

参考资料

Loading related searches...

Wikiwand - on

Seamless Wikipedia browsing. On steroids.

Remove ads