3.3 入栈及出栈命令
push / pop 命令,将元素放入栈顶,或取出栈顶元素。有以下用法:
- push 2 ; 将常数 2 入栈
- push a ; 将变量 a 的值入栈, a 必须已被声明、且已被赋值过
- pop ; 将栈顶向上减少一个单位
- pop a ; 取出栈顶元素,并赋给变量 a , a 必须已被声明
“push 2” 命令运行后,常数 2 被放入栈顶,如下:
- ------------+----------- ------------+-----------
- stack | bind var stack | bind var
- ------------+----------- push 2 ------------+-----------
- ... | -------------> ... |
- ------------+----------- ------------+-----------
- ... |<- ... |
- ------------+----------- ------------+-----------
- 2 |<-
- ------------+-----------
“push a” 命令运行后,变量 a 的值 <5> 被放入栈顶,如下图。
- ------------+----------- ------------+-----------
- stack | bind var stack | bind var
- ------------+----------- ------------+-----------
- 5 | a 5 | a
- ------------+----------- push a ------------+-----------
- ... | -------------> ... |
- ------------+----------- ------------+-----------
- ... |<- ... |
- ------------+----------- ------------+-----------
- 5 |<-
- ------------+-----------
当虚拟机执行 push 命令时,若后面是一个变量名,则虚拟机会在其变量表中查找此变量名,如果查到了,且该变量的值不是空值 “/” ,则将此变量名对应的值放入栈顶,但若此时该变量尚未被赋初值(为空值 “/” ),则虚拟机将出错而终止,如果没有查找到,则虚拟机也会出错终止。
“pop” 命令运行后,栈顶向上减少一个单位,栈顶元素被丢弃,如下:
- ------------+----------- ------------+-----------
- stack | bind var stack | bind var
- ------------+----------- pop ------------+-----------
- ... | -------------> ... |
- ------------+----------- ------------+-----------
- ... | ... |<-
- ------------+----------- ------------+-----------
- ... |<-
- ------------+-----------
“pop a” 命令运行后,栈顶的元素被取出,并将其值赋给了变量 a ,相当于 a = stack.pop() ,此命令是唯一一个能给 直接 给变量赋值的命令。栈的变化如下:
- ------------+----------- ------------+-----------
- stack | bind var stack | bind var
- ------------+----------- ------------+-----------
- ... | a 5 | a
- ------------+----------- pop a ------------+-----------
- ... | -------------> ... |
- ------------+----------- ------------+-----------
- ... | ... |<-
- ------------+----------- ------------+-----------
- 5 |<-
- ------------+-----------
当虚拟机执行 pop 命令后,若后面是一个变量名,虚拟机会在其变量表中查找此变量名,若查到了,则虚拟机会将栈顶元素取出,赋给该变量名对应的栈单元,若没查到,虚拟机会出错终止。
此处同样需要注意的是,若此时 栈顶单元 尚未被赋初值(为空值 “/” ),则虚拟机将出错而终止。总而言之,栈上未被赋初值的单元是不能被使用(读取)的,此约束对后面将要介绍的所有命令都有效,因此后面就不再重复申明此约束了。