字的存储
在上一篇中说到一个16位寄存器可以存放一个字(16位)或者一个字节(8位),当存放一个字节的时候只需要一个内存单元(内存单元是以字节为单位的,8位),而存放一个字需要两个内存单元,这样存放一个字就需要两个连续的内存单元,这个16位的字,高位存放在高地址,低位存放在低地址。
内存地址 | 内存数据 |
---|---|
0 | 20H |
1 | 4EH |
2 | 12H |
3 | 00H |
对于字来说0就是低地址单元,1是高地址单元,则字型数据4E20H的低地址位20存放在0号单元,高地址位4E存放在高地址单元,因为它的起始地址为0,又可以称作0地址字单元。
段地址寄存器
通过前面学过的知识我们可以知道当CPU想要对一个内存单元进行操作时,必须知道它的地址,要知道内存单元的地址就要知道它的段地址和偏移地址,在8086 CPU中,DS寄存器就是用来存放段地址的,执行指令的时候,CPU会自动读取DS中的数据为内存单元的段地址,使用[偏移地址]
来表示偏移地址,假设DS寄存器中此时存放的是1000H,那么mov al,[0]
就表示将10000H(物理地址=段地址x16+偏移地址)地址上存放的数据存到al中。
如果想要修改DS寄存器中的值,那么直接使用mov指令将数字存到DS寄存器中是不行的,只能先将值存到一个寄存器中,再使用mov指令将这个寄存器中的值存到DS中,例:
mov bx,1000H mov ds,bx mov ax,[0]
这样就将地址为10000H处的值存放到ax寄存器中了,也就是将下表中的4E20H存放到ax中。(ax是十六位,一个字,两个字节)
内存地址 | 内存数据 |
---|---|
0 | 20H |
1 | 4EH |
2 | 12H |
3 | 00H |
所以一个内存单元地址的确定可以通过段地址DS+[偏移地址]
进行确定。
add和sub指令
顾名思义,add指令就是用来做加法操作的,sub指令就是用来做减法操作的,例如add ax,8
这条指令相当于C语言中的ax = ax + 8
,sub ax,8
相当于C语言中的ax = ax - 8
。
add和sub指令可以操作的对象有以下几种形式,以add指令为例:
add 寄存器,数据 例如:add ax,8 add 寄存器,寄存器 例如:add ax,bx add 寄存器,内存单元 例如:add ax,[0] add 内存单元,寄存器 例如:add [0],ax
栈
栈,是一段具有特殊访问方式的存储空间,它的存取规则是先进后出,后进先出,就像是一个上面没有盖的桶,最后放进去的东西只能最先取出来。
那么我们怎么知道在连续的存储空间中,哪一段是栈,哪一段不是栈,回想一下,CPU是根据CS、IP两个寄存器中存放的值判断当前指令存放的位置,根据DS、偏移地址判断数据存放在哪个内存单元,显然,也会有相应的寄存器用来判断哪一段是栈,在8086 CPU中,通过段寄存器SS和寄存器SP就可以确定栈的位置,栈有栈顶和栈底,栈顶的段地址存放在SS中,SP用于存放偏移地址,在任意时刻SS:SP指向栈顶元素,它指向的第一个元素可以理解为栈底,以后每存放一个数据SS:SP就向上提升,而它所指向的就是栈顶。
PUSH和POP指令
有了栈,那么就可以对栈进行存取数据的操作,使用的指令时push和pop指令,push指令用于入栈操作,也就是存数据,pop指令用于出栈,也就是取数据。8086 CPU的入栈、出栈操作都是以字为单位。
假设有如下一段连续的内存单元,此时SS为1000H,SP为000EH,AX为1234H,栈顶为1000EH。
内存地址 | 数据 |
---|---|
1000AH | |
1000BH | |
1000CH | |
1000DH | |
1000EH | |
1000FH |
首先,因为SS为1000H,SP为000EH,所以栈顶是指向1000EH位置的:
SS为1000H,SP为000EH,AX为1234H
内存地址 | 数据 |
---|---|
1000AH | |
1000BH | |
1000CH | |
1000DH | |
1000EH | [SS:SP] |
1000FH |
接着我们执行入栈操作,将AX(1234H)入栈,使用push ax
操作进行压栈。
SS为1000H,SP为000CH,AX为1234H
内存地址 | 数据 |
---|---|
1000AH | |
1000BH | |
1000CH | 34[SS:SP] |
1000DH | 12 |
1000EH | |
1000FH |
此时,新的栈顶就变成了1000CH,接着,我们再将一个立即数5678H压入栈中,使用push 5678
:
SS为1000H,SP为000AH,AX为1234H。
内存地址 | 数据 |
---|---|
1000AH | 78[SS:SP] |
1000BH | 56 |
1000CH | 34 |
1000DH | 12 |
1000EH | |
1000FH |
这是,栈顶就是1000AH,SS为1000H,SP为000AH。
演示完了入栈,我们再进行出栈,使用pop ax
操作,将出栈的数据放入到ax寄存器中:
SS为1000H,SP为000CH,AX为5678H。
内存地址 | 数据 |
---|---|
1000AH | 78 |
1000BH | 56 |
1000CH | 34[SS:SP] |
1000DH | 12 |
1000EH | |
1000FH |
注意,出栈并不意味着之前写入内存单元的数据被删除了,之前写入的数据还是存在的,只不过它不在栈中了。
来源:https://www.cnblogs.com/Timesi/p/12198752.html