最近学了王爽教授写的《汇编语言》,整理一下学习笔记。
寄存器是CPU内部用来存放数据的一些小型存储区域,用来暂时存放参与运算的数据和运算结果。因此不同的CPU,寄存器的个数,结构是不相同的。8086CPU有14个寄存器,每个寄存器都有各自的名称,AX,BX,CX,DX,SI,DI,SP,BP,IP,CS,SS,DS,ES,PSW。
寄存器是可以用指令读写的部件,程序员可以通过改变寄存器的内容来实现对CPU的控制。
在8086CPU中寄存器都是16位的,可以存放两个字节。AX,BX,CX,DX这四个寄存器用来存放一般性的数据,因此叫做通用寄存器。
8086CPU中一个16位寄存器被分为两个8位寄存器,以AX为例,分别为AX的高8位(AH)和低8位(AL)。
字,word,一个字有两个字节构成,类比上面16位寄存器分成两个8位寄存器,这两个字节又分别称为这个字的高位字节和低位字节。
以AX寄存器为例,将16位寄存器的高8位和低8位与字的高位字节和低位字节对比,不难发现,AX在存储一个字时,AH存高位字节,AL存低位字节。
以十进制数20000为例,它的十六进制数为4E20H(这里的H并不是数值,它放在数值的末尾表示这个数是16进制数),它的二进制数为0100111000100000,它在AX中的存储情况为
mov,数据传输指令,传送字或字节,比如 “mov ax 8”表示“将8送入寄存器ax(AX跟ax都是一个寄存器,不区分大小写)”,mov指令可以有以下几种形式:
add,算数运算指令,加法,比如“add ax 8” 表示 “将寄存器ax中的数值加上8”,同时add指令也有以下形式:
sub,算数运算指令,减法,比如“sub ax 8” 表示 “将寄存器ax中的数值减去8”,同时sub指令也有以下形式:
一个CPU由运算器,控制器,寄存器等器件构成,这些器件靠内部总线相连,上一章说的总线(数据,地址,控制总线)相对于CPU是外部总线。
内部总线实现CPU内部各个器件之间的联系,外部总线实现CPU和主板上其他器件的联系。可以概括为以下几点:
(1)运算器进行信息处理
(2)寄存器进行信息处理
(3)控制器控制各种器件进行工作
(4)内部总线连接各种器件,在它们之间进行数据的传送。
我们知道8086CPU是16位结构的CPU,这个16位是什么意思呢?
它其实描述了CPU的以下特性:
(1)运算器一次最多可以处理16位的数据
(2)寄存器的最大宽度为16位
(3)寄存器和运算器之间的通路为16位
要知道,内存单元的地址在送往地址总线之前,要在CPU中处理,传输,暂时存放,所以16位CPU能一次性处理,传输和暂时存储16位的地址以及最大长度为16位的信息。
物理地址(Physical Address),又叫实际地址或绝对地址。在存储器里以字节为单位存储信息,所有的内存单元构成存储空间,为正确地存放或取得信息,每一个内存单元在空间中都有唯一的地址,这个地址就是物理地址。
地址从0开始编号,顺序地每次加1,因此存储器的物理地址空间是呈线性增长的。它是用二进制数来表示的,是无符号整数,书写格式为十六进制数。
16位结构的8086CPU有20位地址总线,可以传送20位地址,达到1MB的寻址能力,但它是16位结构,在内部一次性传输,处理,暂时存储的地址为16位,表现出的寻址能力只有64KB,所以问题来了
它是怎么形成一个20位的物理地址呢?
806CPU是采用在内部用两个16位地址合成的方法来形成一个20位的物理地址
其运行的步骤如下:
地址加法器采用 物理地址 = 段地址*16 + 偏移地址的方法用段地址和偏移地址合成物理地址。
例如8086CPU访问地址为123C8H的内存单元,其地址加法器的工作流程如下(图中数字皆为16进制数)
其实说白了,段地址*16就是16进制段地址左移一位。但问题又来了
这个公式是怎么个思想呢? 举个例子:
从家到网吧要走2222米,当走了222米时会经过学校
家–222米----学校-------2000米-----------------------------------网吧
家-------------------------2222米-------------------------------------网吧
我现在要记录下我从家走到学校的距离,很显然这个距离是个四位数,但我一次性只能写三位数,于是我可以记录下这样的三位数字200和222,然后用200(段地址)*10 + 222(偏移地址)= 2222(物理地址),就可以得到总距离了。8086CPU就是这样只能提供两个三位数的CPU。
段的划分来自于CPU,由于8086CPU用“段地址*16+偏移地址=物理地址”的方式给出内存单元的物理地址,使得我们可以用分段的方法管理内存。如图所示:
由图可知
左边的图,地址10000H-100FFH的内存单元组成一个段,该段的起始地址为10000H,段地址为1000H,大小为100H。右边的类比左边。
需要注意的是,偏移地址为16位,16位地址的寻址能力为64KB,所以一个段的长度最大为64KB。
前面讲到了段地址和偏移地址,那么问题来了,什么东西提供段地址呢?
段地址在8086CPU的段寄存器中存放,8086CPU有4个段寄存器,CS,DS,SS,ES。当8086CPU访问内存时,由这四个段寄存器提供内存单元的段地址。
CS和IP是8086CPU中两个最关键的寄存器,它们指示了CPU当前要读取指令的地址。
CS放段地址,IP放偏移地址。8086机中,任意时刻,CPU将CS:IP指向的内容当作指令执行。
举个例子,看下图:
图中的说明如下:
其运行步骤如下:
(1)从CS:IP指向的内存单元读取指令,读取的指令进入指令缓冲器
(2)IP=IP+所读取指令的长度,从而指向下一条指令
(3)执行指令,转到步骤(1)重复整个过程。
(1)想要同时修改CS和IP的指令,可以用形如“jmp 段地址:偏移地址”的指令完成。如下:
(2)想要只修改IP的内容,可以用形如“jmp 某一合法寄存器”。如:
以上为本人学习汇编语言时的摘录总结,主要内容来源于汇编语言(第四版) 王爽 著,大家若是感兴趣可以看看原书,很值得推荐,以上内容如果有什么错误的话,还请大家指正!