如何检查8086上的堆栈是否为空

How to check if the stack is empty on 8086

我正在使用 8086 汇编器进行一项研究,检查数学表达式中括号的平衡。算法如下:

除了需要检查栈是否为空的部分,我已经想通了。如何检查堆栈是否为空或如何在代码中创建一个空堆栈?当堆栈中没有任何东西可以弹出时,我尝试将其弹出并输出一些值。这个值是什么意思?

所以你想用call-stack来实现你的栈数据结构。这很正常,在 asm 中通常是个好主意。

您不想 "empty" 调用堆栈,您只是想设置一种方法来告诉您何时弹出了您在此函数中推送的所有数据。即您的堆栈数据结构为空。

要么推送一个您的代码不会以其他方式生成的标记值,要么使用寄存器(或内存位置)来保存 SP 的当前值。尤其是在 16 位代码中,使用 mov bp,sp 来制作堆栈帧是很常见的,因此您已经将一个寄存器专门用于记住 SP 的旧值。你可以在后面的代码中使用 cmp sp,bp 来查看你是否清空了你的堆栈数据结构。

如果您需要任何 space 用于堆栈上的局部变量,您可以为 BP 以上的局部变量设置 space 的堆栈帧,以及低于 BP 的可变大小堆栈数据。

 my_func:
    ; push  si   ; save whatever other register you want
    sub   sp, 28      ; reserve 28 bytes for locals
    push  bp
    mov   bp, sp

  .my_loop:
    ...                ; use locals from [bp+2] to [bp+26]
    cmp  bp, sp
    jne   .my_loop
    ; else fall through: stack empty

    leave
    add   sp, 28
    ret

如果你根本不需要将任何局部变量溢出到内存中,那么你就不需要制作堆栈框架并且可以使用 bp 作为一个额外的暂存器。但如果你这样做,那么你可以免费使用 bp 作为你的堆栈数据结构的顶部。

请注意,它不是一个传统的堆栈帧:通常 [bp+2] 是 return 地址,因此调试器堆栈回溯可能会显示虚假结果。但是 [bp+0] 仍然指向调用者保存的 bp 值,所以只有那个条目是错误的,它不会中断通过 这个函数的回溯


调用栈为空是什么意思?

除非 sp = 0xFFFE(2 字节在段的顶部对齐),否则 ss:sp 上方总是有内存。如果 sp0xFFFE 循环到 0x0000pop 甚至不会出错。 pop [mem] 可以 #GP 如果弹出内存超出 CS、DS、ES、FS 或 GS​​ 的段限制,根据手册,但我认为这只有在虚幻模式下才有可能。

push in real-mode does fault with #SS 如果 spesp 的新值超出堆栈段限制(在纯 x86-16 中不可能不使用在保护模式下加载的虚幻模式缓存段描述符).实际上,我认为您可能会在纯 real-mode 和 SP=1 / push ax 中获得 #SS。存储地址将为 ss:0xFFFF,因此 2 字节存储将包括从 ss<<4

开始的 64k 段之外的内存 1 字节