通常,堆栈数据是通过stack pointer 相对访问的,stack pointer 是一个 CPU 寄存器,指向存储在堆栈中的最后一个元素。您可以将其视为模拟 CPU 内存的索引。每次将某些内容压入堆栈时,堆栈指针都会减少该内容的大小,并且该内容会存储在减量后地址的模拟内存中。每当您从堆栈中弹出某些内容时,该值都会从存储在堆栈指针中的地址中获取,然后堆栈指针会增加该内容的大小。这就是 CPU 堆栈在许多不同 CPU 中的工作方式。
如果您要实现 CPU 仿真器或 CPU 指令仿真器/解释器,则不太关心变量。您关心的是操作 CPU 寄存器和内存的 CPU 指令,因为您的程序是用 CPU 指令表示的。它们(指令)必须跟踪存储在堆栈中的所有本地变量,即它们相对于堆栈指针当前值的位置。
例如,如果您考虑一个简单的子程序,它将两个传递给它的 16 位整数值添加到堆栈上,它可能看起来像这样,例如16 位 x86 汇编:
myadd:
push bp ; we'll be accessing stack through bp (can't do that through sp because there's no sp-relative memory addressing in 16-bit mode), so, let's save bp first
mov bp, sp ; bp is equal to the stack pointer
mov ax, dword ptr [bp + 4] ; load ax with 1st parameter stored at bp+4 (sp+4)
add ax, dword ptr [bp + 6] ; add to ax 2nd parameter stored at bp+6 (sp+6)
pop bp ; restore bp
ret ; near return to the caller at address stored at sp (address after call myadd), the result/sum is in ax
调用者可能看起来像这样:
push word 2 ; prepare/store 2nd parameter on the stack
push word 1 ; prepare/store 1st parameter on the stack
call myadd ; near call, pushes address of next instruction (add), jumps to myadd
add sp, 4 ; remove myadd's parameters (1 and 2) from the stack
; ax should now contain 3