目录
第2章 访问寄存器和内存
2.1、CS、IP和代码段
1、CS和IP寄存器
CS:代码段寄存器
IP:指针指令寄存器
CPU将CS:IP指向的内存单元中的内容当作指令执行
8086CPU工作原理
1.从CS :IP指向的内存单元读取指令,将读取的指令送入指令缓存器。
2.IP=IP+所读指令的长度,从而指向下一条指令。
3.转到步骤1,执行全过程。
2、演示
在2000:0000处执行下列代码
mov ax,0123H
mov bx,0003H
mov ax,bx
add ax,bx
2.2、Jmp指令
1.应用背景
指向何处的指令,取决于CS:IP,可以通过改变CS:IP的内容,来控制CPU要执行的目标命令。
问题:如何修改CS、IP的值?
1.Debug中使用R命令修改
Debug是调试手段,非程序方式。
2.用指令修改(非法)
8086CPU不提供对CS和IP修改的指令
3.转移指令jmp
(1)同时修改CS、IP的内容
jmp 段地址:偏移地址
(2)仅修改IP的内容
jmp 某一合法寄存器(通常为通用寄存器)
例:jmp ax(类似于mov IP,ax)
跳转到IP寄存器值为ax值处执行
2、问题分析
从2000:0000处开始执行,则执行序列是?
解:
mov ax,6622H //cs=2000,ip=0
jmp 1000:3 //cs=1000,ip=3
mov ax,0
mov bx,ax
jmp bx //cs=1000,ip=0
mov ax,0123H
3、debug演示
2.3、内存中字的存储
1、存储规则
对于8086CPU,16位作为1个字
16位的字存储在1个16位的存储器中,高8位放高字节(AH)、低8位放低字节(AL)
例如:20000D(4E20H)存放0、1两个单元,18D(0012H)存放在2、3两个单元。
AH | AL |
4E(H) | 20(H) |
0 | 20H |
1 | 4EH |
2 | 12H |
3 | 00H |
4 |
4 | |
3 | 00H |
2 | 12H |
1 | 4EH |
0 | 20H |
0号是低地址,1号是高地址
2、字单元
字单元是由2个地址连续的内存单元组成,存放1个字型数据(16位)。
原理:在1个字单元中,低地址单元存放低位字节,高地址单元存放高位字节
在起始地址为0的单元中,存放的是4E20H;
在起始地址为2的单元中,存放的是0012H。
0 | 20H |
1 | 4EH |
2 | 12H |
3 | 00H |
4 |
问题:
(1)0地址单元中存放的字节型数据是(20H)
(2)0地址字单元中存放的字型数据是(4E20H)
(3)2地址单元中存放的字节型数据是(12H)
(4)2地址字单元中存放的字型数据是(0012H)
2.4、用DS和[address]实现字的传送
1、原理
CPU从内存单元中读取数据时,必须给出这个内存单元的地址。
内存地址由段地址和偏移地址组成(段地址:偏移地址)
使用DS寄存器和[address]配合
1.用DS寄存器存放要访问的数据的段地址
2.偏移地址用[...]形式直接给出
使用通用寄存器将段地址送入DS寄存器
8086CPU不支持将数据直接送入寄存器(硬件设计的问题),故必须通过通用寄存器才能将数据送入段寄存器。
mov bx,1000H
mov ds,bx
例如:将10000H(1000:0)中的数据读到al中
mov bx,1000H
mov ds,bx
mov al.[0]
2、字的传送
8086CPU可以一次性传送1个字(16位)数据。
例1:已知内存和指令如下
10000H | 23 |
10001H | 11 |
10002H | 22 |
10003H | 66 |
mov ax,1000H
mov ds,ax
mov ax,[0]
mov bx,[2]
mov cx,[1]
add bx,[1]
add cx,[2]
Debug实现如下
例2:已知内存和指令如下
10000H | 23 |
10001H | 11 |
10002H | 22 |
10003H | 11 |
mov ax,1000H
mov ds,ax
mov ax,2C31
mov [0],ax
mov bx,[0]
sub bx,[2]
mov [2],bx
Debug执行如下
2.5、 DS和数据段
1、对内存单元中数据的访问
对于8086CPU,可以根据需要将一组内存单元定义为一个段。
物理地址=段地址X16+偏移地址
将一组长度为N(N<64K)、地址连续、起始地址为16的倍数的内存单元当作专门存储数据的内存空间,从而定义了一个数据段。
DS:[address]
用DS存放数据段的段地址
用相关指令访问数据段中的具体单元,单元地址由[address]指出
已知将123B0H~123BAH的内存单元定义为数据段
例1:累加数据段中的前3个单元中的数据
mov ax,123BH
mov ds,ax
mov al,0
add al,[0]
add al,[1]
add al,[2]
例2:累加数据段中的前3个字型数据
mov ax,123BH
mov ds,ax
mov ax,0
add ax,[0]
add ax,[2]
add ax,[4]
2、用mov指令操作数据
已知:mov 段寄存器,寄存器。推测1—>mov 寄存器,段寄存器
已知:mov 内存单元,寄存器。推测2—>mov 内存单元,段寄存器;推测3—>mov 段寄存器,内存单元
已知:mov 段寄存器,数据。推测4—>mov 段寄存器,数据
3、加法add和减法sub
4、小结
2.6、 栈及栈操作的实现
1、栈结构
栈结构是一种能能够在一端进行插入或删除的数据结构
两个基本操作:入栈和出战
入栈:将一个新元素放到栈顶;
出栈:从栈顶取出一个元素
操作规则:后进先出
2、指令
push(入栈)和pop(出栈)
push ax:将ax中的数据送入栈中
pop ax:从栈顶取出数据送入ax中
(以字为单位对栈进行操作)
例如:设将10000H~1000FH内存当作栈来使用
mov ax,1000H
mov ss,ax
mov sp,0010H //栈顶地址为1000:0010
mov ax,0123H
push ax
mov bx,2266H
push bx
mov cx,1122H
pop ax
pop bx
pop cx
10000H | |
... | |
10009H | |
1000AH | 22 |
1000BH | 11 |
1000CH | 66 |
1000DH | 22 |
1000EH | 23 |
1000FH | 01 |
结果ax=1122H;bx=2266H;cx=0123H
3、相关的寄存器
栈段寄存器SS——存放栈顶的段地址
栈顶指针寄存器SP——存放栈顶的偏移地址
任意时刻,SS:SP指向栈顶元素。
push ax
(1)sp=sp-2
(2)将ax中的内容送入SS:SP指向的内存单元处,
SS:SP此时指向新栈顶
pop ax
(1)将SS:SP指向的内存单元处的数据送入ax中
(2)sp=sp+2,SS:SP指向当前栈顶下面的单元,
以当前栈顶下面的单元为新的栈顶
栈顶超界问题
8086CPU不保证对栈的操作不会越界
4、小结
(1)push、pop实质上是一种内存传送指令,可以在寄存器和内存之间传送数据,于mov指令不同的是,push和pop指令访问的内存单元的地址不是在指令中给出的,而是由SS:SP指出的。
(2)执行push和pop指令时,SP中的内容自动改变
(3)8086CPU提供的栈操作机制
push指令执行步骤
1)SP=SP-2
2)向SS:SP指向的字单元中送入数据
pop指令执行步骤
1)从SS:SP指向的字单元中读取数据
2)SP=SP+2
2.7、关于段的总结
1、各种段
物理地址=段地址X16+偏移地址
段地址指使段,用偏移地址访问段内的单元
数据段
将段地址放在DS中
CPU将定义的数据段中的内容当作数据段访问
代码段
将段地址放在CS中,将段中第一条指令的
偏移地址放在IP中。
CPU执行定义的代码段的指令
栈段
将段地址放在SS中,将栈顶元素
的偏移地址放在SP中。
CPU执行栈操作(push、pop)时,
将定义的栈段当作地址空间使用。
2、综合示例
按要求设置段并执行程序
设10000H~1000FH为数据段,10010H~1001FH为栈段,20000H~2FFFF为代码段。
(10000H)=23、(10001H)=11、(10002H)=22、(10003H)=66
mov bx,1000H
mov ds,bx
mov ss,bx
mov sp,10H
mov ax,[0]
mov bx,[2]
push ax
push bx
pop ax
pop bx
mov [0],ax
mov [2],bx