一.内存中字的存储:一个字型数据(16位)要用两个地址连续的内存单元存放.
1.(大端模式下)低位字节存放在低地址单元中,高位字节存放在高地址单元.将起始地址(存放低位字节的地址)为N的字单元简称为N地址字单元.N地址存放的字型数据存放在N和N+1这两个地址中.
2.在内存和寄存器间传送字型数据时,高地址单元和高8位寄存器,低地址单元和低8位寄存器相对应.
二.段地址寄存器:DS,通常用来存放要访问的【数据】的段地址,如要读取10000H单元的内容,可用如下程序段: mov bx,1000H
mov ds,bx
mov al,[0]
1.[…]表示一个内存单元,括号内的数值表示偏移地址,当前ds的值为段地址
2.所有段地址寄存器(DS,SS等)不支持直接传入数据,需要用一个通用寄存器作为中介.
3.例中mov al,[0]将地址10000H的一个字节的数据传入al,传入数据的大小由前面的寄存器决定(若将al改为ax则传入2个字节的数据),反之亦可.
4.add,sub等指令(算术指令)不可对段地址寄存器ds等进行操作
三.CPU中的栈机制:(可将一段连续的内存想象为由上到下地址逐渐递增的一个井)
1.栈顶的段地址存放在段寄存器SS(Stack segment)中,偏移地址存放在SP中.SS:SP任意时刻指向栈顶.
2.Push ax指令由两步完成:(理解为先往上移动指针,后往下填充数据)(注意栈顶从高地址向低地址移动)
①.SP = SP-2(SS:SP指向当前栈顶前面的单元.执行后以当前栈顶前面的单元为新的栈顶.)
②.将ax中的内容(一个字型数据)传入SS:SP指向的内存单元处,SS:SP此时已指向新栈顶.
3.pop ax指令与Push正好相反(先把数据传出,后往下移动指针)
①.将SS:SP指向的内存单元处的数据送入ax中
②.SP = SP+2(SS:SP指向当前栈顶下面(更高地址)的单元,以当前栈顶下面的单元为新的栈顶)
注:出栈时出栈的元素仍然存在于原来的位置(只是栈顶指针改变了),直到再次压栈有新的元素填充进来
4.8086CPU未设定栈顶超界检查机制(所以需要我们自己注意)
5.Push,pop指令(内存传送指令)也可对寄存器,段寄存器,某个内存的地址进行操作.
6.栈操作都是以字(2Bytes)为单位操作的.
7.在8086中每次只能压入或弹出16位,不能压入/弹出16位,因此push ah是错误的
8.任何一个程序都是有堆栈的,如果程序员未定义则系统会自动分配
补充:
执行mov ss,ax时其后边的指令将立即被执行[这是MOV SS,**指令特点]。这也是为什么强调mov ss,ax 后边必须跟上mov sp,10的原因。
这么规定是便于控制栈段大小,防止特别是在有子程序调用时出错。
至于这两条指令执行后靠近栈顶的10个字节中值立即有了变化,是对定义栈段时部分运行环境变量进行暂存,靠近栈顶的10个字节中的暂存数据分别是SS、IP、 CS 等的值。
练习:
1.若想将10000H~1000FH这段空间当做空栈,则需要
初始化栈顶位置为:1000FH + 1 = 10010H ( 1000H:0010H)
2.若想将10000H~1000FH这段空间当做满栈,则需要
初始化栈顶位置为:10000H ( 1000H:0000H)