栈操作

栈段非常重要,栈操作引入了SP栈顶指针寄存器,但是许多同学对SP寄存器的指向模棱两可,这是不行的,栈都搞不清楚,学习任何编程语言也就都无从谈起了。

栈操作流程

假设栈长度为4B,我们这么定义:

stackseg segment
dw 0,0
stackseg ends

注:dw定义的一个字,即两个字节

栈初始化我们这么定义(注意SP设置的值):

mov ax,stackseg
mov ss,ax
mov sp,4

对于8086处理器,我们要记住四个规则:

  1. 栈是向低地址增长的;
  2. 栈空时,SP指向栈底前一个元素;
  3. 栈满时,SP寄存器的值为0;
  4. 元素入栈,SP先向内存低地址移动一个字长,然后赋值,出栈相反。

也就是说,栈非空时SP永远指向栈顶元素,栈空SP指向栈底的前一个元素。

假设我们要PUSH一个0eeffh,假设此时SP=10,那么首先SP=SP-2=8,栈顶地址为SS:[8],写入一个字长的数据后,低地址SS:[8]为0ffh,高地址SS:[9]为0eeh。为什么写入的两个字节是SS:[8]和SS:[9]呢?因为前面说过栈是向低地址增长的,SP是从高地址“扫向”低地址,那么自然操作的内存偏移地址就是SP和SP+1了,另外,我们也不要搞错写入的顺序,立即数0eeffh中,高地址是0eeh,低地址是0ffh,对应内存中高地址SS:[9]为0eeh,低地址SS:[8]为0ffh

例子代码

assume cs:codeseg,ss:stackseg

stackseg segment
dw 0,0,0,0
stackseg ends

codeseg segment

start:

;设置栈段寄存器SS
mov ax,stackseg
mov ss,ax
mov sp,8

mov ax,0eeffh
push ax
push ax
push ax
push ax
pop bx
pop bx
pop bx
pop bx

mov ax,4c00h
int 21h

codeseg ends

end start

我们可以在DosBox中单步调试,看看SS寄存器、SP寄存器、内存的变化,加深对栈的理解。

作者:Gacfox
版权声明:本网站为非盈利性质,文章如非特殊说明均为原创,版权遵循知识共享协议CC BY-NC-ND 4.0进行授权,转载必须署名,禁止用于商业目的或演绎修改后转载。
Copyright © 2017-2024 Gacfox All Rights Reserved.
Build with NextJS | Sitemap