首先,我使用的是Mac 系统下 DOSBox 的debug 环境。
不同的系统运行结果是不是一样呢?有可能吧~ 主要考虑他的原理。
逐步分析: 首先,前两行代码将ds指向了FFFF段内存,也就是数据段是ffffH:00开始的内存单元了。 然后,建立一个栈结构,ss指向2200H段的内存,初始化栈顶指针是100H,ss:sp指向栈底后面第一个单元(目前栈结构是空);也就是说这个栈结构栈底后面第一个单元地址是2200:100H(物理地址:22100H)
mov ax,[0] //ax=C0EA; add ax,[2] //ax=ax+[2]=C0EA+0012=C0FC mov bx,[4] //bx=30F0; add bx,[6] //bx=bx+[6]=31F0+2F30=6120 push ax //将ax=C0FC压入栈中;sp=sp-2=0100-2=00FE; 修改的内存单元的地址是220FE,内容是C0FC push bx //将bx=6120压入栈中;sp=sp-2=00FE-2=00FC 修改的内存单元的地址是220FC,内容是6021 pop ax //将ax=C0FC推出栈;sp=sp+2=00FE;ax=6021 pop bx //将ax=C0FC推出栈;sp=sp+2=0100;bx=C0FC push [4] //将DS:0004压入栈中;sp=sp-2=00FE; 修改的内存单元的地址是220FE,内容是30F0 push [6] //将DS:0006压入栈中;sp=sp-2=00FC; 修改的内存单元的地址是220FC,内容是2F31可以看出尽管修改了数据,但是基本的原理都还相同。
程序理解: 【1】创建了一个栈的结构,它的实质就是一段连续的内存空间,只不过访问内存的方式不像我们原来的CPU寻址方式,使用push和pop访问。 【2】栈使用的实际空间是随着sp指针的指向而发生改变的,它和最大使用空间是有区别的。栈空,sp=100H,栈满,sp=0。 【3】栈操作的对象基本单位是字单元(2个字节),对应的内存就是2个内存单元。
前三行指令的功能为:
将2000进入ax寄存器中
将ax中的值赋值给ss
将sp的值改为0010。
变化的原因为: 在用t指令进行调试时,会产生中断。cpu将先把标志寄存器进栈,再把当前的cs的值进栈,IP的值最后进栈。初始没有执行这段代码时,使用d命令观察2000:00内存,都是00,怎么创建栈结构指向这段内存时,我们发现有些数据了。这些数据是什么?
发现呢这里面有cs值、ip值、ax值(这个容易看出来),还有bp值(00 00),还有那个一排英文字符。
了解一下之后呢,发现:t命令实际是引发了单步中断,执行中断例程时,CPU会将一些中断例程使用的的寄存器变量自动压栈到栈中,此例中就包括了上述的寄存器变量的值。
注意:由于t命令必须保存寄存器变量的值(这个是中断程序定义的。)它也占用一定的空间。可能我们定义的栈空间比较小;频繁的使用push指令,为了避免栈顶超界,我们尽量使栈空间大些,就像此程序,设定栈空间是100H。
