汇编(二):寄存器(CPU工作原理)

寄存器(CPU工作原理)

CPU = 运算器 + 控制器 +【寄存器】,器件之间通过总线相连;

8086CPU 有14个寄存器,名称分别为:
AX,BX,CX,DX,SI,DI,SP,BP,IP,CS,SS,DS,ES,PSW

通用寄存器

  1. 8086CPU 所有的寄存器都是16位的,可以存放2个字节;

  2. AX、BX、CX、DX 通常用来存放一般性数据,被称为通用寄存器;

  3. 8086上一代CPU中的寄存器都是8位的,为了保证兼容性
    这四个寄存器都是可以分为2个独立的8位寄存器使用;
    AX=AH+AL
    BX=BH+BL
    CX=CH+CL
    DX=DH+DL

  4. AX的低8位(0-7)构成AL寄存器,高8位(8-15)构成了AH寄存器,AH和AL寄存器是可以独立使用的8位寄存器;

  5. 字在寄存器中的存储,一个字等于两个字节,因此要占用AX整一个寄存器;
     

几条汇编指令

  1. 汇编指令不区分大小写;

  2. CPU 执行下表中的程序段的每条指令后,对寄存器中的数据进行的改变。几条汇编指令:

mov ax,18;    AX = 18
mov ah,78;    AH = 78
add ax,8;     AX = AX+8
mov ax,bx;    AX = BX
add ax,bx;    AX += BX

思考:这个问号的值是多少?

程序段中的最后一条指令 add ax,bx,在执行前 ax 和 bx 中的数据都为 8226H,相加后所得的值为∶ 1044CH,但是 ax 为 16 位寄存器,只能存放 4 位十六进制的数据,所以最高位的1不能在 ax 中保存, ax 中的数据为∶ 044CH。

这里的丢失,指的是进位制不能在 16 位寄存器中保存,但是 CPU 不是并真的不丢弃这个进位值;
 

→ 检测1 ←

  1. 写出每条汇编指令执行相关寄存器的值;
  1. 只能使用目前学过的汇编指令,最多使用4条指令,编程计算2的4次方。
     

物理地址

CPU 访问内存单元时要给出内存单元的地址。所有的内存单元构成的存储空间是一个一维的线性空间,我们将这个唯一的地址称为物理地址。
 

16位结构的CPU

概括的讲,16位结构描述了一个 CPU 具有以下几个方面特征:

  1. 运算器一次最多可以处理16位的数据。
  2. 寄存器的最大宽度为16位。
  3. 寄存器和运算器之间的通路是16位的。
     

8086CPU给出物理地址的方法

8086有20位地址总线,可传送20位地址,寻址能力为1M。

8086内部为16位结构,它只能传送16位的地址,表现出的寻址能力却只有64K。

问题:那么,8086CPU 如何用内部16位的数据转换成20位的地址呢?

8086CPU 采用一种在内部用两个16位地址合成的方法来形成一个20位的物理地址:

8086CPU读写内存时,发生了这么一些事:

CPU 中的相关部件提供两个16位的地址,一个称为段地址,另一个称为偏移地址;段地址和偏移地址通过内部总线送入一个称为地址加法器的部件;地址加法器将两个16位地址合并成一个20位的地址;

地址加法器合成物理地址的方法:物理地址 = 段地址×16 + 偏移地址

由16位二进制变为20位,等价往左移动了四位,也就是乘上了一个24,即16;
 

本质含义

基础地址 + 偏移地址 = 物理地址

比如说,学校、体育馆同在一条笔直的单行路上(学校位于路的起点0米处)。读者在学校,要去图书馆,问我那里的地址,我可以用几种方式描述这个地址?

  1. 从学校走2826m到图书馆。这2826可以认为是图书馆的物理地址。
  2. 从学校走2000m到体育馆,从体育馆再走826m到图书馆。
    • 第一个距离2000m是相对于起点的基础地址;
    • 第二个距离826m是将对于基础地址的偏移地址。
       

段地址×16 + 偏移地址 = 物理地址

比如我们只能通过纸条来通信,读者问我图书馆的地址,我只能将它写在纸上告诉读者。显然我必须有一张可以容纳 4 位数据的纸条才能写下2826这个数据:

不巧的是,没有能容纳4位数据的纸条,仅有两张可以容纳3位数据的纸条。这样我只能以这种方式告诉读者2826这个数据:

在第一张纸上写上 200(段地址),在第二张纸上写上826(偏移地址)。假设我们事前对这种情况又有过相关的约定:你得到这两张纸后,做这样的运算:200(段地址)*10 + 826(偏移地址) = 2826(物理地址)。

8086CPU 就是这样一个只能提供两张3位数据纸条的 CPU。段地址×16可以看做是基础地址
 

段的含义

错误认识:内存被划分成了一个一个的段,每一个段有一个段地址。

事实上,内存并没有分段,段的划分来自于 CPU,由于8086CPU用“(段地址×16)+偏移地址=物理地址”的方式给出内存单元的物理地址,使得我们可以用分段的方式来管理内存。

我们既可以把内存单元看成一个段,也可以看成两个段;

以后,在编程时可以根据需要,将若干地址连续的内存单元看作一个段,用段地址 ×16 定位段的起始地址(基础地址),用偏移地址定位段中的内存单元

注意:
(1)段地址 ×16 必然是16的倍数,所以一个段的起始地址也一定是16的倍数;
(2)偏移地址为16位,16位地址的寻址能力为64K,所以一个段的长度最大为64K。

小结:

  • CPU 访问内存单元时,必须向内存提供内存单元的物理地址。
  • 8086CPU 在内部用段地址和偏移地址移位相加的方法形成最终的物理地址。
     

观察下面的地址,可以得出结论:CPU 可以用不同的段地址和偏移地址形成同一个物理地址。

如果给定一个段地址,仅通过变化偏移地址来进行寻址,最多可以定位多少内存单元?

答:偏移地址16位,变化范围为0~FFFFH,仅用偏移地址来寻址最多可寻64K个内存单元。比如:给定段地址1000H,用偏移地址寻址, CPU 的寻址范围为:10000H~1FFFFH。

→ 检测2 ←

  1. 给定段地址为0001H,仅通过变化偏移地址寻址,CPU 的寻址范围为____到____。

  2. 有一数据存放在内存20000H单元中,现给定段地址为SA,若想用偏移地址寻到此单元,则SA应满足的条件是:最小为____,最大为____。

当段地址给定到多少,CPU 无论怎么变化偏移地址都无法寻到20000H单元。

段寄存器

段寄存器就是提供段地址的。8086CPU有4个段寄存器:CS、DS、SS、ES;

当 8086CPU 要访问内存时,由这4个段寄存器提供内存单元的段地址。
 

CS和IP

CS 和 IP 是 8086CPU 中最关键的寄存器,它们指示了 CPU 当前要读取指令的地址。CS 为代码段寄存器;IP 为指令指针寄存器。

8086PC工作过程的简要描述

(1)从 CS:IP 指向内存单元读取指令,读取的指令进入指令缓冲器;
(2)IP = IP + 所读取指令的长度,从而指向下一条指令;
(3)执行指令。 转到步骤 (1),重复这个过程。

在 8086CPU 加电启动或复位后( 即 CPU 刚开始工作时)CS 和 IP 被设置为 CS=FFFFH,IP=0000H。即在 8086PC 机刚启动时,CPU 从内存 FFFF0H 单元中读取指令执行。FFFF0H 单元中的指令是 8086PC 机开机后执行的第一条指令。

在任何时候,CPU 将 CS、IP 中的内容当作指令的段地址和偏移地址,用它们合成指令的物理地址,到内存中读取指令码,执行。

如果说,内存中的一段信息曾被 CPU 执行过的话,那么,它所在的内存单元必然被 CS:IP 指向过。
 

修改CS、IP的指令

在 CPU 中,程序员能够用指令读写的部件只有寄存器,程序员可以通过改变寄存器中的内容实现对 CPU 的控制。

CPU 从何处执行指令是由 CS、IP 中的内容决定的,程序员可以通过改变 CS、IP 中的内容来控制 CPU 执行目标指令。
 

如何修改 AX 中的值?

mov 指令,如:mov ax,123;

mov 指令可以改变 8086CPU 大部分寄存器的值,被称为传送指令。
 

如何同时修改CS、IP的内容?

jmp指令:用指令中给出的段地址修改 CS,偏移地址修改 IP。

jmp 段地址:偏移地址
jmp 2AE3:3
jmp 3:0B16

仅修改IP的内容:

jmp 某一合法寄存器
jmp ax   (类似于 mov IP,ax)
jmp bx

CPU运行的流程

内存中存放的机器码和对应汇编指令情况: (初始:CS=2000H,IP=0000H)

(1)mov ax,6622
(2)jmp 1000:3
(3)mov ax,0000
(4)mov bx,ax
(5)jmp bx (bx 是0,因此 ip 为0,所以就到转到了地址10000H处)
(6)mov ax,0123H
(7)转到第(3)步执行

不难发现这是个死循环蛤;
 

代码段

对于8086PC机,在编程时,可以根据需要,将一组内存单元定义为一个段。

可以将长度为 N( N≤64KB )的一组代码,存在一组地址连续、起始地址为16的倍数的内存单元中,这段内存是用来存放代码的,从而定义了一个代码段。

这段长度为 10 字节的字节的指令,存在从123B0H123B9H的一组内存单元中,我们就可以认为,123B0H123B9H这段内存单元是用来存放代码的 ,是一个代码段 ,它的段地址为123BH,长度为10字节。

如何使得代码段中的指令被执行呢?

将一段内存当作代码段,仅仅是我们在编程时的一种安排,CPU 并不会由于这种安排,就自动地将我们定义得代码段中的指令当作指令来执行。CPU 只认被 CS:IP 指向的内存单元中的内容为指令。所以要将CS:IP指向所定义的代码段中的第一条指令的首地址。
 

小结

1、段地址在8086 CPU 的寄存器中存放。当8086 CPU 要访问内存时,由段寄存器提供内存单元的段地址。8086 CPU 有4个段寄存器,其中 CS 用来存放指令的段地址。

2、CS 存放指令的段地址,IP 存放指令的偏移地址。8086机中,任意时刻,CPU 将 CS:IP 指向的内容当作指令执行。

3、8086CPU 的工作过程:
(1)从 CS:IP 指向内存单元读取指令,读取的指令进入指令缓冲器;
(2)IP 指向下一条指令;
(3)执行指令。(转到步骤(1),重复这个过程。)

4、8086CPU 提供转移指令修改 CS、IP 的内容。
 

→ 检测3 ←

下面的3条指令执行后,cpu几次修改IP?都是在什么时候?最后IP中的值是多少?

mov ax,bx
sub ax,ax
jmp ax

答案

检测1

mov ax,62627   AX=F4A3H

mov ah,31H     AX=31A3H

mov al,23H     AX=3123H

add ax,ax      AX=6246H

mov bx,826CH   BX=826CH

mov cx,ax      CX=6246H

mov ax,bx      AX=826CH

add ax,bx      AX=04D8H

mov al,bh      AX=0482H

mov ah,bl      AX=6C82H

add ah,ah      AX=D882H

add al,6       AX=D888H

add al,al      AX=D810H

mov ax,cx      AX=6246H
mov  ax,2         AX=2
add  ax,ax        AX=4
add  ax,ax        AX=8
add  ax,ax        AX=16

检测2

解题过程:

物理地址 = SA*16+EA

EA的变化范围为 0h~ffffh

物理地址范围为 (SA*16+0h)~(SA*16+ffffh)

现在 SA = 0001h,那么寻址范围为

(0001h*16+0h)~(0001h*16+ffffh)

= 0010h~1000fh

解题过程:

物理地址 = SA*16+EA

20000h = SA*16+EA

SA = (20000h-EA)/16 = 2000h-EA/16

EA取最大值时,SA = 2000h-ffffh/16 = 1001h,SA为最小值

EA取最小值时,SA = 2000h-0h/16 = 2000h,SA为最大值

当段地址给定为 1001H 以下和 2000H 以上,CPU无论怎么变化偏移地址都无法寻到20000H单元。
 

检测3

最后 IP 的值为0000H,因为最后 ax 中的值为0000H,所以 IP 中的值也为0000H;

sub 指令是相减的意思,sub ax,ax 就是 ax=0;

猜你喜欢

转载自blog.csdn.net/weixin_46263782/article/details/120260740
今日推荐