3.1 内存中字的存储
在0地址处存放20000(4e20H)
0地址单元中存放的字节型数据是多少?
是20H
0地址字单元存放的字节型数据是多少?
是4e20H
任何两个地址连续的内存单元,N和N+1单元,可以将其看成两个内存单元,也可以看成一个地址为N的字单元中的高位字节单元和低位字节单元。
3.2 DS和[address]
DS存放储存数据的段地址
执行指令时,8086CPU自动获取DS中的数据为内存单元的段地址。
如何用mov指令从10000H中读取数据呢?
- 10000H表示1000:0(段地址:偏移地址)
- 将段地址1000H放入DS
- 用mov al, [0]完成传送(mov指令中的[]说明操作对象是一个内存单元,[]中德0说明这个内存单元的偏移地址是0,他的段地址默认放在ds中)
能不能直接用mov ds,1000H?
不行,8086CPU不支持将数据直接放入段寄存器,只能通过通用寄存器来中继一下。
数据->通用寄存器->段寄存器
3.3 字型数据的传送
8086CPU是16位结构,有16根数据线,所以可以一次性传16位数据,就是一个字
比如:
mov bx,1000H
mov ds,bx
mov ax,[0]
mov [0],cx
1,2行表示确定了段地址
第三行表示,将1000:0处的字型数据送入ax。
第四行表示将cx中的16位数据送到1000:0处。
3.4 mov add sub指令
mov 寄存器,数据 mov ax ,6//通用寄存器
mov 寄存器,寄存器 mov ax,bx
mov 寄存器,内存单元 mov ax,[0]
mov 内存单元,寄存器 mov [0],ax
mov 段寄存器,寄存器 mox ds,ax
3.5 数据段
我们可以将一组长度为N(N<=64K)地址连续起始地址为16倍数的内存单元当作专门存储数据的内存空间,从而定义了一个数据段。
mov ax, 123BH
mov ds, ax //将123BH送入ds中作为数据段的段地址
mov ax, 0 //用ax存放累加结果
add ax,[0] //将数据段的第一个字(偏移地址为0)加到ax中
add ax,[2] //将数据段的第二个字(偏移地址为2)加到ax中
add ax,[4] //将数据段的第三个字(偏移地址为4)加到ax中
注意:一个字型数据占两个单元,所以偏移地址是0,2,4。
3.6 栈
栈是一种特殊访问方式的存储空间,先进先出。
入栈:将一个新元素插入栈顶
出栈:从栈顶取出一个元素
- CPU如何知道一段内存空间被当做栈使用?
寄存器CS和IP中存放着当前指令的段地址和偏移地址
8086有两个寄存器:
段寄存器SS 存放栈顶的段地址
寄存器SP 存放栈顶的偏移地址
任意时刻,SS:SP指向栈顶元素
- 执行push和pop时,CPU如何知道哪个单元是栈顶?
push ax这一步执行时会由以下两步完成
- SP = SP-2 SS:SP指向当前栈顶前面的单元,以当前栈顶前面的单元为新的栈顶。
- 将ax中的内容送入SS:SP指向的内存单元处,SS:SP此时指向新栈顶
如果将10000H~1000FH这段空间当作栈,初始栈是空的,此时SS=1000H,那么SP=?
将如下图所示 SP=0010H
当栈只有一个元素时,SS=1000H,SP=000EH,当栈为空时,SP=SP+2应该是可以理解的。
所以SP=0010H。
下图描述了pop命令的执行过程:
其中画红圈的部分,只是把这个数据复制进ax,这个数据本身还是存在在内存里面的。
3.8 栈顶超界的问题
当栈满了之后再用push指令将数据推入栈中,会出问题。
栈空了之后再用pop也会出问题
向下溢出了
在编程时,要注意栈顶超界的问题,要根据可能用到的最大栈空间来安排栈的大小,防止入栈的数据太多而导致的超界问题。出栈也一样哈。
push是先sp=sp-2 然后把数据压进去
pop是先把数据拿出来再sp=sp+2
push和pop操作,修改的只是SP,也就是说栈顶的变化范围最大时0~FFFFH。
3.10 栈段
比如我们将10010H~1001FH这段长度为16字节的内存空间当作栈来用,以栈的方式进行访问
这段空间酒可以成为栈段,段地址为1000H,大小为16字节。