一、寄存器基础知识
一个典型的CPU(此处讨论的不是某一具体的CPU)由运算器、控制器、寄存器(CPU 工作原理)等器件构成,这些器件靠内部总线相连。前一章所说的总线,相对于CPU内部来说是外部总线。内部总线实现CPU内部各个器件之间的联系,外部总线实现CPU和主板上其他器件的联系。简单地说,在CPU中:
●运算器进行信息处理;
●寄存器进行信息存储;
●控制器控制各种器件进行工作;
●内部总线连接各种器件,在它们之间进行数据的传送。
对于一个汇编程序员来说,CPU中的主要部件是寄存器。寄存器是CPU中程序员可以用指令读写的部件。程序员通过改变各种寄存器中的内容来实现对CPU的控制。
不同的CPU,寄存器的个数、结构是不相同的。8086CPU有14个寄存器,每个寄存器有一个名称。这些寄存器是:AX、BX、CX、DX、SI、DI、SP、BP、IP、CS、SS、 DS、ES、PSW。
1、通用寄存器
8086CPU的所有寄存器都是16位的,可以存放两个字节。AX、BX、CX、DX这4 个寄存器通常用来存放一般性的数据,被称为通用寄存器。
8086CPU的上一代CPU中的寄存器都是8位的,为了保证兼容,使原来基于上代CPU编写的程序稍加修改就可以运行在8086之上,8086CPU的AX、BX、CX、DX这4 个寄存器都可分为两个可独立使用的8位寄存器来用:
● AX可分为AH和AL;
● BX可分为BH和BL;
● CX可分为CH和CL;
● DX可分为DH和DL。
AX的低8位(0位~7位)构成了AL寄存器,高8位(8位-15位)构成了AH寄存器。 AH和AL寄存器是可以独立使用的8位寄存器。
2、字在寄存器中的存储
出于对兼容性的考虑,8086CPU可以一次性处理以下两种尺寸的数据。
●字节:记为byte,一个字节由8个bit组成,可以存在8位寄存器中
●字:记为word,一个字由两个字节组成,这两个字节分别称为这个字的高位字节和低位字节
一个字可以存在一个16位寄存器中,这个字的高位字节和低位字节自然就存在这个寄存器的高8位寄存器和低8位寄存器中。如下图所示,一个字型数据20000,存在AX寄存器中,在AH中存储了它的高8位,在AL中存储了它的低8位。AH和AL中的 数据,既可以看成是一个字型数据的高8位和低8位,这个字型数据的大小是20000;又可以看成是两个独立的字节型数据,它们的大小分别是78和32。
注:计算机里所使用数制
任何数据,到了计算机中都是以二进制的形式存放的。但为了方便我们一般将其用十六进制数来表示。理由如下:
- 十六进制数的一位相当于二进制数的四位,如0100111000100000可表示成:4(0100)、E(1110)、2(0010)、0(0000)四位十六进制数。
- 很多时候,需要直观地看出组成数据的各个字节数据的值,用十六进制来表示数据可以直观地看出这个数据是由哪些8位数据构成的。比如20000写成4E20就可以直观地看出,这个数据是由4E和20两个8位数据构成的,如果AX中存放4E20,则AH里是4E,AL里是20。
3、几条汇编指令
汇编指令 | 控制CPU完成的操作 | 用高级语言的语法描述 |
---|---|---|
mov ax,18 | 将18送入寄存器AX | AX=18 |
mov ah,78 | 将78送入寄存器AH | AH=78 |
add ax,8 | 将寄存器AX中的数值加上8 | AX=AX+8 |
mov ax,bx | 将寄存器BX中的数据送入寄存器AX | AX=BX |
add ax,bx | 将AX和BX中的数值相加,结果存在AX中 | AX=AX+BX |
注:
-
在写一条汇编指令或一个寄存器的名称时不区分大小写
-
CPU在执行时会认为ah和al为两个不相关的寄存器
-
在进行数据传送或运算时,要注意指令的两个操作对象的位数应当是一致的
4、物理地址
CPU访问内存单元时,要给出内存单元的地址。所有的内存单元构成的存储空间是一个一维的线性空间,每一个内存单元在这个空间中都有唯一的地址,我们将这个唯一的地址称为物理地址。
CPU通过地址总线送入存储器的,必须是一个内存单元的物理地址。在CPU向地址总线上发出物理地址之前,必须要在内部先形成这个物理地址。不同的CPU可以有不同的形成物理地址的方式。
5、16位结构的CPU
8086CPU的上一代CPU(8080、8085)等是8位机,而8086是16位机,也可以说8086是16位结构的CPU。
概括地讲,16位结构(16位机、字长为16位等常见说法,与16位结构的含义相同) 描述了一个CPU具有下面几方面的结构特性。
●运算器一次最多可以处理16位的数据
●寄存器的最大宽度为16位
●寄存器和运算器之间的通路为16位
8086是16位结构的CPU,这也就是说,在8086内部,能够一次性处理、传输、暂时存储的信息的最大长度是16位的。内存单元的地址在送上地址总线之前,必须在CPU中处理、传输、暂时存放,对于16位CPU,能一次性处理、传输、暂时存储16位的地址。
6、8086CPU给出物理地址的方法
8086CPU有20位地址总线,可以传送20位地址,达到1MB寻址能力。8086CPU又是16位结构,在内部一次性处理、传输、暂时存储的地址为16位。从8086CPU的内部结构来看,如果将地址从内部简单地发出,那么它只能送出16位的地址,表现出的寻址能力只有64KB。
这是因为8086CPU采用一种在内部用两个16位地址合成的方法来形成一个20位的物理地址。
如图所示,当8086CPU要读写内存时:
- CPU中的相关部件提供两个16位的地址,一个称为段地址,另一个称为偏移地址
- 段地址和偏移地址通过内部总线送入一个称为地址加法器的部件
- 地址加法器将两个16位地址合成为一个20位的物理地址
- 地址加法器通过内部总线将20位物理地址送入输入输出控制电路
- 输入输出控制电路将20位物理地址送上地址总线
- 20位物理地址被地址总线传送到存储器
地址加法器采用物理地址=段地址×16+偏移地址的方法用段地址和偏移地址合成物理地址
注:段地址x16
“段地址×16”有一个更为常用的说法是左移4位。计算机中的所有信息都是以二进制的形式存储的,段地址当然也不例外。机器只能处理二进制信息,“左移4位”中的位,指的是二进制位。
我们看一个例子,一个数据为2H,二进制形式为10B, 对其进行左移运算:
左移位数 | 二进制 | 十六进制 | 十进制 |
---|---|---|---|
0 | 10B | 2H | 2 |
1 | 100B | 4H | 4 |
2 | 1000B | 8H | 8 |
3 | 10000B | 10H | 16 |
4 | 100000B | 20H | 32 |
观察上面移位次数和各种形式数据的关系,我们可以发现:
(1)一个数据的二进制形式左移1位,相当于该数据乘以2
(2)一个数据的二进制形式左移N 位,相当于该数据乘以2的N 次方
(3)地址加法器如何完成段地址×16的运算?就是将以二进制形式存放的段地址左移4位
进一步思考,我们可看出:一个数据的十六进制形式左移1位,相当于乘以16:一个数据的十进制形式左移1位,相当于乘以10;一个X进制的数据左移1位,相当于乘以X。
7、”段地址×16+偏移地址=物理地址“的本质含义
“段地址×16+偏移地址=物理地址”的本质含义是:CPU在访问内存时,用一个基础地址(段地址×16)和一个相对于基础地址的偏移地址相加,给出内存单元的物理地址。
8、段的概念
内存并没有分段,段的划分来自于CPU,由于8086CPU用“基础地址(段地址×16)+偏移地址=物理地址”的方式给出内存单元的物理地址,使得我们可以用分段的方式来管理内存。如图所示,我们可以认为:地址10000H~100FFH 的内存单元组成一个段,该段的起始地址(基础地址)为10000H, 段地 址为1000H,大小为100H;我们也可以认为地址10000H~1007FH、10080H-100FFH的内存单元组成两个段,它们的起始地址(基础地址)为:10000H和10080H,段地址为:1000H和1008H,大小都为80H。
在编程时可以根据需要,将若干地址连续的内存单元看作一个段,用段地址×16定位段的起始地址(基础地址),用偏移地址定位段中的内存单元。有两点需要注意:段地址×16必然是16的倍数,所以一个段的起始地址也一定是16的倍数;偏移地址 为16位,16位地址的寻址能力为64KB, 所以一个段的长度最大为64KB。
内存单元地址小结
- CPU访问内存单元时,必须向内存提供内存单元的物理地址。8086CPU在内部用段地址和偏移地址移位相加的方法形成最终的物理地址
- CPU可以用不同的段地址和偏移地址形成同一个物理地址,比如CPU要访问21F60H单元,则它给出的段地址SA和偏移地址EA满足SA×16+EA=21F60H即可
- 如果给定一个段地址,仅通过变化偏移地址来进行寻址,最多可定位64KB个内存单元(偏移地址16位,变化范围为0-FFFFH,仅用偏移地址来寻址最多可寻64KB个内存单元)
- “数据在21F60H内存单元中。”这句话对于8086PC机一般不这样讲,取而代之的是两种类似的说 法:①数据存在内存2000:1F60单元中;②数据存在内存的2000H段中的1F60H单元中。这两种描述都示“数据在内存21F60H单元中”
- 可以根据需要,将地址连续、起始地址为16的倍数的一组内存单元定义为一个段
9、段寄存器
8086CPU在访问内存时要由相关部件提供内存单元的段地址和偏移地址,送入地址加法器合成物理地址。其中段地址在8086CPU的段寄存器中存放。8086CPU有4个段寄存器:CS、DS、SS、ES。当 8086CPU要访问内存时由这4个段寄存器提供内存单元的段地址。
10、CS和IP
CS和IP是8086CPU中两个最关键的寄存器,它们指示了CPU当前要读取指令的地址。CS为代码段寄存器,IP为指令指针寄存器,从名称上我们可以看出它们和指令的关系。
在8086PC机中,任意时刻,设CS中的内容为M,IP中的内容为N,8086CPU将从内存M×16+N单元开始,读取一条指令并执行。
也可以这样表述:8086机中,任意时刻,CPU将CS:IP指向的内容当作指令执行。
8086CPU的工作过程可以简要描述如下:
(1)从CS:IP指向的内存单元读取指令,读取的指令进入指令缓冲器
(2)IP=IP+所读取指令的长度,从而指向下一条指令
(3)执行指令。转到步骤(1),重复这个过程
11、修改CS、IP的指令
在CPU中,程序员能够用指令读写的部件只有寄存器,程序员可以通过改变寄存器中的内容实现对CPU的控制。CPU从何处执行指令是由CS、IP中的内容决定的,程序可以通过改变CS、IP中的内容来控制CPU执行目标指令。
8086CPU大部分寄存器的值,都可以用mov指令来改变,mov指令被称为传送指令。
但是,mov指令不能用于设置CS、IP的值,原因很简单,因为8086CPU没有提供这样的功能。8086CPU为CS、IP提供了另外的指令来改变它们的值。能够改变CS、IP的内容的指令被统称为转移指令(我们以后会深入研究)。我们现在介绍一个最简单的可以修改CS、IP的指令:jmp指令
-
若想同时修改CS、IP的内容,可用形如“jmp段地址:偏移地址”的指令完成,如
jmp 2AE3:3,执行后:CS=2AE3H,IP=0003H,CPU将从2AE33H处读取指令。
jmp 3:0B16,执行后:CS=0003H,IP=0B16H,CPU将从00B46H处读取指令。 “jmp段地址:偏移地址”指令的功能为:用指令中给出的段地址修改CS,偏移地址修改IP。 -
若想仅修改IP的内容,可用形如“jmp 某一合法寄存器”的指令完成,如
jmp ax,指令执行前:ax=1000H,CS=2000H,IP=0003H 指令执行后:ax=1000H,CS=2000H,IP=1000H
jmp bx,指令执行前:bx=0B16H,CS=2000H,IP=0003H 指令执行后:bx=0B16H,CS=2000H,IP=0B16H
jmp某一合法寄存器”指令的功能为:用寄存器中的值修改IP。
12、代码段
前面讲过,对于8086PC 机,在编程时,可以根据需要,将一组内存单元定义为一个段。我们可以将长度为N(N≤64KB)的一组代码,存在一组地址连续、起始地址为16的倍数的内存单元中,我们可以认为,这段内存是用来存放代码的,从而定义了一个代码段。比如,将
mov ax,0000 (B8 00 00)
add ax,0123H (05 23 01)
mov bx,ax (8B D8)
jmp bx (FF E3)
这段长度为10个字节的指令,存放在123BOH~123B9H 的一组内存单元中,我们就可以认为,123BOH~123B9H这段内存是用来存放代码的,是一个代码段,它的段地址为123BH, 长度为10个字节。
如何使得代码段中的指令被执行呢?将一段内存当作代码段,仅仅是我们在编程时的一种安排,CPU 并不会由于这种安排,就自动地将我们定义的代码段中的指令当作指令来执行。CPU 只认被 CS:IP 指向的内存单元中的内容为指令。所以,要让 CPU 执行我们 放在代码段中的指令,必须要将CS:IP 指向所定义的代码段中的第一条指令的首地址。对于上面的例子,我们将一段代码存放在123BOH~123B9H内存单元中,将其定义为代码段,如果要让这段代码得到执行,可设CS=123BH 、IP=0000H。
小结
- 段地址在8086CPU的段寄存器中存放。当8086CPU要访问内存时,由段寄存器提供内存单元的段地址。8086CPU有4个段寄存器,其中CS用来存放指令的段地址。
- CS存放指令的段地址,IP存放指令的偏移地址。8086机中,任意时刻,CPU将CS:IP指向的内容当作指令执行。
- 8086CPU的工作过程:
①从CS:IP指向的内存单元读取指令,读取的指令进入指令缓冲器;
②IP指向下一条指令;
③执行指令。(转到步骤①,重复这个过程 - 8086CPU提供转移指令修改CS、IP的内容。
二、检测习题
检测点1
(1)写出每条汇编指令执行后相关寄存器中的值。
mov ax,62627 | AX= |
---|---|
mov ah,31H | AX= |
mov al,23H | AX= |
add ax,ax | AX= |
mov bx,826CH | BX= |
mov cx,ax | CX= |
mov ax,bx | AX= |
add ax,bx | AX= |
mov al,bh | AX= |
mov ah,bl | AX= |
add ah,ah | AX= |
add al,6 | AX= |
add al,al | AX= |
mov ax,cx | AX= |
(2)只能使用目前学过的汇编指令,最多使用4条指令,编程计算2的4次方。
检测点2
(1)给定段地址为0001H,仅通过变化偏移地址寻址,CPU的寻址范围为_____到_____。
(2)有一数据存放在内存20000H单元中,现给定段地址为SA,若想用偏移地址寻 到此单元。则SA应满足的条件是:最小为_____,最大为_____。
提示,反过来思考一下,当段地址给定为多少,CPU无论怎么变化偏移地址都无法寻到20000H单元?
检测点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 |
只能使用目前学过的汇编指令,最多使用4条指令,编程计算2的4次方。
mov ax,2
add ax,ax
add ax,ax
add ax,ax
检测点2
(1)给定段地址为0001H,仅通过变化偏移地址寻址,CPU的寻址范围为__00010H_到1000FH__。
(2)有一数据存放在内存20000H单元中,现给定段地址为SA,若想用偏移地址寻 到此单元。则SA应满足的条件是:最小为1001H,最大为2000H___。
提示,反过来思考一下,当段地址给定为多少,CPU无论怎么变化偏移地址都无法寻到20000H单元?
SA<=1000H 或 SA>2000H
检测点3
下面的3条指令执行后,CPU 几次修改IP? 都是在什么时候?最后IP中的值是多少?
mov ax,bx
sub ax,ax
jmp ax
四次;分别在:
- 读取mov ax,bx后
- 读取sub ax,ax后
- 读取jmp ax后
- 执行jmp ax后
四、拓展知识之Intel系列微处理器的3种工作模式
微机中常用的Intel系列微处理器的主要发展过程是: 8080,8086/8088,80186,80286,80386,80486,Pentium,Pentium Ⅱ,PentiumlII,Pentium4
8086/8088是一个重要的阶段,8086和8088是略有区别的两个功能相同的CPU。 8088被IBM用在了它所生产的第一台微机上,该微机的结构事实上成为以后微机的基本结构。
80386是第二个重要的型号,随着微机应用及性能的发展,在微机上构造可靠的多任务操作系统的问题日益突出。人们希望(或许是一种潜在的希望,一旦被挖掘出来,便形成了一个最基本的需求)自己的PC机能够稳定地同时运行多个程序,同时处理多项工作;或将PC机用作主机服务器,运行UNIX那样的多用户系统。
8086/8088不具备实现一个完善的多任务操作系统的功能。为此Intel开发了80286, 80286具备了对多任务系统的支持。但对8086/8088的兼容却做得不好。这妨碍了用户对原8086机上的程序的使用。IBM最早基于80286开发了多任务系统OS/2,结果犯了一个战略错误。
随后Intel又开发了80386微处理器,这是一个划时代的产品。它可以在以下3个模式下工作。
(1)实模式:工作方式相当于一个8086。
(2)保护模式:提供支持多任务环境的工作方式,建立保护机制(这与VAX等小型机类似)。
(3)虚拟8086模式:可从保护模式切换至其中的一种8086工作方式。这种方式的提供使用户可以方便地在保护模式下运行一个或多个原8086程序。
任何一台使用Intel系列CPU的PC机只要一开机,CPU就工作在实模式下。如果你的机器装的是DOS, 那么在 DOS 加载后CPU仍以实模式工作。如果你的机器装的是Windows, 那么Windows 加载后,将由Windows将CPU 切换到保护模式下工作,因为Windows是多任务系统,它必须在保护模式下运行。如果你在Windows中运行一个DOS下的程序,那么 Windows 将CPU切换到虚拟8086模式下运行该程序。或者是这样,你点击开始菜单在程序项中进入MS-DOS 方式,这时,Windows也将CPU切换到虚拟8086模式下运行。
可以从保护模式直接进入能运行原8086程序的虚拟8086模式是很有意义的,这为用 户提供了一种机制,可以在现有的多任务系统中方便地运行原8086系统中的程序。这一点,在Windows 中我们都可以体会到,你在Windows 中想运行一个原DOS中的程序, 只用鼠标点击一下它的图标即可。80286CPU的缺陷在于,它只提供了实模式和保护模式,但没有提供虚拟8086模式。这使基于80286构造的多任务系统,不能方便地运行原8086系统中的程序。如果运行原8086系统中的程序,需要重新启动计算机,使CPU工作在实模式下才行。这意味着什么?意味着将给用户造成很大的不方便。假设你使用的是基于80286构造的Windows 系统,就会发生这样的情况:你正在用Word写一篇论文,其中用到了一些从前的数据,你必须运行原DOS下的DBASE系统来看一下这些数据。这时你只能停下现有的工作,重新启动计算机,进入实模式工作。你看完了数据,继续写论文,可过了一会儿,你发现又有些数据需要参考,于是你又得停下现有的工作,重新启动计算机……
幸运的是,我们用的Windows 是基于80386的,我们可以以这样轻松的方式工作,开两个窗口,一个是工作于保护模式的Word, 一个是工作于虚拟8086模式的DBASE, 我们可以方便地在两个窗口中切换,只要用鼠标点一下就行。
着将给用户造成很大的不方便。假设你使用的是基于80286构造的Windows 系统,就会发生这样的情况:你正在用Word写一篇论文,其中用到了一些从前的数据,你必须运行原DOS下的DBASE系统来看一下这些数据。这时你只能停下现有的工作,重新启动计算机,进入实模式工作。你看完了数据,继续写论文,可过了一会儿,你发现又有些数据需要参考,于是你又得停下现有的工作,重新启动计算机……
幸运的是,我们用的Windows 是基于80386的,我们可以以这样轻松的方式工作,开两个窗口,一个是工作于保护模式的Word, 一个是工作于虚拟8086模式的DBASE, 我们可以方便地在两个窗口中切换,只要用鼠标点一下就行。
标签:16,汇编语言,地址,指令,寄存器,ax,习题,CPU,王爽 From: https://blog.csdn.net/2403_86637060/article/details/141104308