一、先说说堆栈的建立
建立一个堆栈有两项工作要做:
①定义一个名字有堆栈含义的段:
mystack segment stack
dw 40h dup(?)
mystack ends
上述语句为这个段分配了80h个字节的空间。特别需要明确的是,这个段现在除了名字似乎和堆栈有点关系外,本质上仅仅是一个普通的段,还没有被用作堆栈。
②在代码段执行了如下代码后:
mov ax,mystack
mov ss,ax
mov sp,80h
即当ss指向mystack后,该段才被用作堆栈段。
将sp初始化为80h,即让sp指向堆栈段偏移量为80h的单元,即使sp的初值和被用作堆栈的存储器段所申请的字节数相等,是为了完整地使用段定义开辟的80h个字节空间。仔细分析我们会发现,mystack段定义的80h个字节的偏移量是从0到7fh,那么sp初始化时为什么指向堆栈之外呢?之所以这样是因为数据入栈(如push ax)时,首先会将sp的内容减2,这时sp就进入了堆栈段的空间范围之内,然后再把一个字的内容送入堆栈。
二、ss、sp和堆栈结构元素的关系
堆栈似乎有很多和其结构相关的术语,比如堆栈段、堆栈容量、栈底、栈顶等。其实堆栈的这些结构元素都是由ss和sp的初值决定的;
和其他段一样,ss的内容就是堆栈段的段基址,这应该很明确、容易理解的;
而sp的初值使得以这个初值为偏移量的以下所有单元都被用作堆栈。举例来说,假设sp的初值是80h,那么从偏移量为0到7fh的80h个字节就被用作堆栈。由此可见,sp的初值和堆栈的容量就是一回事。
再说说栈底。栈底是这样定义的:堆栈存放第一个字信息的位置就是栈底。显然,存放第一个字信息时就是将sp的初值减2,即栈底的偏移量和sp初值的关系就是:
栈底的偏移量=sp初值-2
至于栈顶,第一是很简单:始终就是sp指向的那个字单元,显然会随数据入栈和出栈不断地变化;第二是要能够理解,当sp初始化时,栈顶在栈底之下;当第一次压栈后,栈顶和栈底齐平;其他情况下才会“恢复顶上底下”的“正常”情况。 |