这一章主要介绍了CPU中的重要器件——寄存器,整个系列通篇是以8086CPU作为探讨对象,其它更高级的CPU都是在此基础之上进行的升级。
1、一个典型的CPU是由运算器、控制器、寄存器等器件组成,这些器件靠内部总线相连。
区别:内部总线实现CPU内部各个器件之间的联系。
外部总线实现CPU和主板上其它器件的联系。
2、8086CPU有14个寄存器,有8个通用寄存器
AX、BX、 CX、 DX、 SI、 DI、 SP、 BP、 IP、 CS 、SS、 DS、 ES、 PSW
8086CPU所有的寄存器都是16位的,可以存放两个字节。
AX、BX、CX、DX通常用来存放一般性数据,被称为通用寄存器。
3、16位寄存器的逻辑结构
如下图所示:
所以16位数据在寄存器中的存放情况如下图所示:
4、一个16位寄存器可以存储一个16位的数据,那么这个16位寄存器所能存储的数据的最大值为2^16-1。
5、8086上一代CPU(8088等)中的寄存器都是8位的,为保证兼容性,这四个寄存器都可以分为两个独立的8位寄存器使用。
因此,AX可以分为AH和AL,高8位和低8位(这样做是为了兼容低版本的CPU);
BX分为BH和BL,CX分为CH和CL,DX分为DH和DL
以AX为例,8086CPU16位寄存器分为两个8位寄存器的情况:
AX的低8位(0-7位)构成了AL寄存器,高8位(8-15位)构成了AH寄存器。AH和AL寄存器是可以独立使用的8位寄存器。
8086CPU的8位寄存器数据存储情况:
高八位和低八位分别可以代表不一样的数字,但是二者结合在一起又会是另一个数字。
6、字在寄存器中的存储
一个字可以存储在一个16位寄存器中,这个字的高位字节和低位字节自然就存储在这个寄存器的高8位和低8位寄存器中。
7、几条汇编指令
8、物理地址
CPU访问内存单元时要给出内存单元的地址。所有的内存单元构成的存储空间是一个一维的线性空间。
我们将这个唯一的地址称为物理地址。
9、16位结构的CPU
概括的讲,16位结构描述了一个CPU具有以下几个方面的特征:
(1)运算器一次可以处理16位的数据。
(2)寄存器的最大宽度为16位。
(3)寄存器和运算器之间的通路是16位的。
10、8086CPU给出的物理地址的方法
8086有20位地址总线,可传送20位地址,寻址能力为1M。(外部)
8086内部为16位结构,只能传送16位的地址,表现出的寻址能力却只有64K。(内部)
这样内外部就会产生冲突,那么工程师是如何解决这样的冲突的呢?
如图所示:
8086CPU读写内存时:(1)CPU中的相关部件提供两个16位的地址,一个为段地址,一个为偏移地址;
(2)段地址和偏移地址通过内部总线送入一个称为地址加法器的部件;
(3)地址加法器将两个16位地址合并成一个20位的地址;
地址加法器合成物理地址的方法:
物理地址=段地址*16+偏移地址(很重要,这个公式!)
首先CPU会将地址(段地址和偏移地址)通过内部总线传送到地址加法器中,然后将段地址左移1位(16进制的数乘以16),再加上偏移地址,最后就得出了最终想要的物理地址。
打个比方,我要从学校去图书馆,之间有一个体育馆,学校到图书馆的距离是2286m,学校到体育馆的距离是2000m,体育馆到图书馆的距离是286m,那么学校到体育馆之间的距离就可以看做是段地址,体育馆到图书馆的距离就是偏移地址。假设我要将这个距离写在一张只有3个数字匡的纸条上的话,我就需要先写上段地址200,再乘上10,再加上偏移地址286,这样就得到了最终的结果。
11、段的概念
错误认识:内存被划分为一个个的段,每一个段都有一个段地址。
其实,内存并没有分段,段的划分来自于CPU,由于8086CPU用“(段地址*16)+偏移地址=物理地址”的方式给出内存单元的物理地址,使得我们可以用分段的方式来管理内存。
因此,在以后的编程中,我们可以根据实际需要,将若干个地址连续的内存单元看做 一个段,用段地址*16来定位段的起始地址(基础地址),用偏移地址定位段中的内存单元。
段地址*16必然是16位的倍数,偏移地址为16位,16位地址的寻址能力为64k,所以一个段的最大长度为64k。
12、内存单元地址小结
CPU访问内存单元时,必须向内存提供内存单元的物理地址;
8086CPU在内部用段地址和偏移地址移位想家的方法形成最终的物理地址。
21F60H这个物理地址,可以有很多种不同的基地址左移一个16位+偏移地址构成。
因此,8086CPU的寻址能力最大也就是64KB个内存单元。比如给定一个段地址1000H,用偏移地址寻址,CPU的寻址范围为:10000H----1FFFFH。
13、段寄存器
段寄存器就是提供段地址的,8086CPU有4个段寄存器:CS、DS、SS、ES
当8086CPU访问内存时,由4个段寄存器提供内存单元的段地址。
14、CS和IP
CS和IP是8086CPU中最关键的寄存器,它们指示了CPU当前要读取指令的地址。
CS为代码段寄存器,ip为指令指针寄存器
CS:ip指向内存单元执行过程如下所示:
(1)从CS:ip中指向的内存单元中读取指令,读取的指令进入指令缓冲区。在此之前,CS:IP要经过地址加法器,然后将算好的20位地址通过内部总线传送到输入输出控制 电路中。再通过20位的地址总线,传送到内存当中,找到物理地址所指向的内存单元。然后将内存单元中的指令通过数据总线传送到指令缓冲区中,执行控制器进行指 令的执行,将结果传到其他部件当中。
(2)执行完一条指令后,ip的值自动增加,具体增加多少就要看指令的长度是多少,三位的指令的话,就在原有基础上增加三位的长度,此时CS:IP发生变化,再重复(1) 中的过程。
15、修改CS、IP的指令
在CPU中,程序猿能够用指令读写的部件只有寄存器,程序员可以通过改变寄存器中的内容实现对CPU的控制。
CPU从何处执行指令,是由CS、IP的内容来决定的,因此对CPU进行控制,也就是对CS、IP的内容进行修改罢了,改变CPU执行的目标而已。
那么我们应该如何改变CS、IP的值呢?
在此之前,我们可以回顾一下如何改变AX(通用寄存器)中的值。通过mov ax 1532H这条mov指令即可改变AX中的值,但是这样的传送指令能用于CS这样的代码寄存器中吗? 答案是不能,因为8086CPU没有提供这样的功能。8086CPU为CS、IP提供了另外的指令来改变它们的值:转移指令。
(1)同时修改CS、IP的内容:jmp 段地址:偏移地址
jmp 2AE3:3 这里意思就是指示CPU跳到2AE33这个物理地址上,用段地址2AE3修改原来的CS,偏移地址3修改原来的ip。
(2)仅修改ip的内容:
jmp 某合法寄存器 jmp ax(类似于传送指令mov一样的效果,mov IP,AX)
这里就是用寄存器中的值来修改IP。
16、代码段
对于8086PC机,在编程时,可以根据需要,将一组内存单元定义为一个段。
可以将长度为N(N<=64KB)的一组代码,存在一组地址连续、起始地址为16的倍数的内存单元中,这段内存是用来存放代码的,从而定义了一个代码段。
如何使得代码段中的指令被执行呢?就是将CPU指向这个代码段,该代码段中的指令就会被执行。CPU只认被CS:IP指向的内存单元中的 内容为指令。
所以要将CS:IP指向所定义的代码段的第一条指令的地址。
17、段寄存器小结
段地址存放在8086CPU的寄存器中,段寄存器提供内存单元的段地址,给CPU去访问内存空间。8086CPU有4个段寄存器,其中CS用来存放指令的段地址。
IP是用来存放指令的偏移地址,在8086PC机中,CPU在任意时刻,都将CS:IP指向的内容当做指令来执行。
8086CPU为CS、IP提供了另外的指令来改变它们的值:转移指令(jmp)。
既然内存单元的访问地址可以干预,那么我们就可以把木马程序的初始访问地址写在杀毒软件的内存访问初始地址之前,这样就可以做到不被杀毒软件给查杀了吧(不知道这样的 想法有没有错误,欢迎大牛不吝赐教!)。