汇编语言笔记

3 篇文章 0 订阅

第2章寄存器

一个典型的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。

2.1通用寄存器

8086CPU的所有寄存器都是16位的,可以存放两个字节。
AX、BX、CX、DX这4个寄存器通常用来存放一般性的数据,被称为通用寄存器。
一个16为存储器可以存储一个16位的数据
想一想,一个16位寄存器所能存储的数据的最大值为多少?
2 16 − 1 2^{16}-1 2161
8086CPU的上一代CPU中的寄存器都是8位的,为了保证兼容,使原来基于上代
CPU编写的程序稍加修改就可以运行在8086之上,8086CPU的AX、BX、CX、DX这4个寄存器都可分为两个可独立使用的8位寄存器来用。
*AX可分为AH和AL
*BX可分为BH和BL
*CX可分为CH和CL
*DX可分为DH和DL
想一想,一个8位寄存器所能存储的数据的最大值为多少?
2 8 − 1 2^8-1 281

2.2字在寄存器中的存储

处于对兼容性的考虑,8086CPU可以一次性处理以下两种尺寸的数据。
字节:记为byte,一个字节由8个bit组成,可以存在8位寄存器中。
字:记为word,一个字由两个字节组成,这两个字节分别称为这个字的高位字节和低位字节
在这里插入图片描述
一个字可以存在一个16位寄存器中,这个字的高位字节和低位字节自然就存在这个寄存器的高8位寄存器和低8位寄存器中。

2.3几条汇编指令

在这里插入图片描述
AX中的数据:00C5H
add al, 93H
指令执行后AX中的数据为多少?
相加后所得的值为:158H,但是 al 为8位就差你器,只能存放两位16进制的数据,所以最高位的1丢失,ax中的数据为:0058H。
(这里的丢失,指的是进位值不能在8位寄存器中保存,但是CPU并不真的丢弃这个进位值,关于这个问题,我们将在后面的课程中讨论)

注意,此时al是作为一个独立的8位寄存器来使用的,和ah没有关系,CPU在执行这条指令时认为ah和al是两个不相关的寄存器。

如果执行 add ax, 93H,低8为的进位会存储在ah中,CPU在执行这条指令时认为只有一个16位寄存器ax,进行的是16位运算

在进行数据传送或运算时,要注意指令的恋歌操作对象的位数应当是一致的。
以下是错误的指令
mov ax, bl (在8位寄存器和16位寄存器之间传送数据)
mov bh, ax (在16位寄存器和8位寄存器之间传送数据)
mov al, 20000 (8位寄存器最大可存放值为255的数据)
add al, 100H (将一个高于8位的数据加到一个8位寄存器中)

检测点2.1

(1)写出每条汇编指令执行后相关寄存器中的值。
mov ax, 62627 AX=F4A3H
mov ah, 31H AX=31A3H//AX=25A3H 错误 注意区分 mov 与 add
mov al, 23H AX=3123H//AX=31C6H 错误 注意区分 mov 与 add
add ax, ax AX=6264H//当操作ax时,低8位的进位会到高8位
mov bx, 826CH BX=826CH
mov cx, ax CX=6264H
mov ax, bx AX=826CH
add ax, bx AX=04D8H//注意进位
mov al, bh AX=0482H//注意区分 mov 与 add
mov ah, bl AX=6C82H
add ah, ah AX=D882H
add al, 6 AX=D888H
add al, al AX=D810H//A在16进制中表示10,1在16进制中表示1
mov ax, cx AX=6264H
(2)只能使用目前学过的汇编指令,最多使用4条指令,编程计算2的4次方
mov ax, 2
add ax, ax
add ax, ax
add ax, ax

2.4物理地址

CPU访问内存单元时,要给出内存单元的地址。
所有内存单元构成的存储空间是一个一维的线性空间,每一个内存单元在这个空间中都有唯一的地址,我们将这个唯一的空间称为物理地址。
CPU通过地址总线送入存储器的,必须是一个内存单元的物理地址。在CPU向地址总线上发出物理地址之间,必须要在内部线形成这个物理地址。

2.51 6位结构的CPU

8086是16位机,也可以说8086是16位结构的CPU。那么什么是16位结构的CPU呢?
概括地讲,16位结构(16位机、字长位16位)描述了一个CPU具有下面几方面的结构特性。
运算器一次最多可以处理16位的数据
寄存器的最大宽度为16位
寄存器和运算器之间的通路为16位

2.6 8086CPU给出物理地址的方法

8086CPU有20位地址总线,可以传送20位地址,达到1MB寻址能力。
8086CPU又是16位结构,在内部一次传输、处理、暂时存储的地址为16位。
从8086CPU内部结构来看,如果将地址从内部简单地发出,那么它只能送出16位的地址,表现出的寻址能力只有64KB。
8086CPU采用一种在内部用两个16位地址合成的方法来形成一个20位的物理地址。
8086CPU相关部件的逻辑结构如图所示
在这里插入图片描述
如图所示,当8086CPU要读写内存是:
(1)CPU中的相关部件提供两个16位的地址,一个称为段地址,另一个称为偏移地址
(2)段地址和偏移地址通过内部总线送入一个称为地址加法器的部件;
(3)地址加法器将两个16位地址合成为一个20位的物理地址
/8086CPU有20位地址总线,所以可以传送20位的物理地址/
(4)地址加法器通过内部总线将20位物理地址送入输入输出控制电路
(5)输入输出控制电路将20位物理地址送上地址总线
(6)20位物理地址被地址总线传送到存储器

地址加法器采用物理地址=段地址×16+偏移地址的方法用段地址和偏移地址合成物理地址。例如,8086CPU要访问地址为123c8H的内存单元,此时,地址加法器的工作过程如图所示(图中数据皆为十六进制表示)。
在这里插入图片描述
“段地址×16”有一个更为常用的说法是左移4位。

2.7“段地址×16+偏移地址=物理地址”的本质含义

“段地址×16+偏移地址=物理地址”的本质含义是:CPU在访问内存时,用一个基础地址(段地址×16)和一个相对于基础地址的偏移地址相加,给出内存单元的物理地址。
更一般地说,8086CPU的这种寻址功能是“基础地址+偏移地址=物理地址

2.6段的概念

其实,内存并没有分段,段的划分来自于CPU,由于8086CPU用“基础地址(段地址×16)+偏移地址=物理地址”的方法给出内存单元的物理地址,使得我们可以用分段的方法来管理内存
在这里插入图片描述
我们可以认为:地址100004-100FFH的内存单元组成一个段,该段的起始地址(基础地址)为100004,段地址为1000H,大小为100H:我们也可以认为地址10000-1007FH、10080H-100FFH的内存单元组成两个段,它们的起始地址
(基础地址)为:1000和10080H,段地址为:1000和1008H,大小都为80H

以后,在编程时可以根据需要,将若干地址连续的内存单元看作一个段,用段地址×16定位段的起始地址(基础地址),用偏移地址定位段中的内存单元。有两点需要注意:段地址×16必然是16的倍数,所以一个段的起始地址也一定是16的倍数;偏移地址为16位,16位地址的寻址能力为64KB,所以一个段的长度最大为64KB

检测点2.2

(1)给定段地址为0001H,仅通过变化偏移地址寻址,CPU的寻址范围为___到___
解析:偏移地址的变化范围:0000H~FFFFH
物理地址=段地址×16+偏移地址
CPU的寻址范围:00010H~1000FH//注意8086CPU有20位地址总线
(2)有一数据存放在内存20000H单元中,现给定段地址为SA,若想用偏移地址寻到此单元。则SA应满足的条件是:最小为___,最大为___
提示,反过来思考一下,当段地址給定为多少,CPU无论怎么变化偏移地址都无法寻到20000H单元?
解析:偏移地址的变化范围:0000H~FFFFH
物理地址=段地址×16+偏移地址
若物理地址最大为20000H,即段地址×16+FFFFH=20000H
此时段地址×16=10001H;满足条件的段地址不存在
若段地址为1000H,则,无法方位内存20000H单元
若段地址为1001H,则,可以访问内存20000H单元
若物理地址最小为20000H,即段地址×16+0000H=20000H
此时段地址×16=20000H
段地址为2000H
SA最小为:1001H,最大为:2000H

2.9段寄存器

我们前面讲到,8086CPU在访问内存时要由相关部件提供内存单元的段地址和偏移地址,送入地址加法器合成物理地址。这里,需要看一下,是什么部件提供段地址。段地址在8086CPU的段寄存器中存放。
8086CPU有4个段寄存器:CS、DS、SS、ES。
当8086CPU要访问内存时由这4个段寄存器提供内存单元的段地址。本章中只看一下CS

2.10 CS和IP

CS和IP是8086CPU中两个最关键的寄存器,它们指示了CPU当前要读取指令的地址。CS为代码段寄存器,IP为指令指针寄存器,从名称上我们可以看出它们和指令的关系。
在8086PC机中,任意时刻,设CS中的内容为M,IP中的内容为N,8086CPU将从内存Mx16+N单元开始,读取一条指令并执行。
也可以这样表述:8086机中,任意时刻,CPU将CS:IP指向的内容当作指令执行。

(1)从CS:IP指向的内存单元读取指令,读取的指令进入指令缓冲器
(2)IP=IP+所读取指令的长度,从而指向下一条指令
(3)执行指令。转到步骤(1),重复这个过程在8086CPU加电启动或复位后(即CPU刚开始工作时CS和IP被设置为CS= FFFFH,IP=0000H,即在8086PC机刚启动时,CPU从内存 FFFFOH单元中读取指令

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

我们在第1章中讲过,在内存中,指令和数据没有任何区别,都是二进制信息,CPU在工作的时候把有的信息看作指令,有的信息看作数据。现在,如果提出一个问题:CPU根据什么将内存中的信息看作指令?如何回答?我们可以说,CPU将CS:IP指向的内存单元中的内容看作指令,因为,在任何时候,CPU将CS、IP中的内容当作指令的段地址和偏移地址,用它们合成指令的物理地址,到内存中读取指令码,执行。如果说,内存中的一段信息曾被CPU执行过的话,那么,它所在的内存单元必然被CS:IP指向过

2.11 修改CS、IP的指令

在CPU中,程序员能够用指令读写的部件只有寄存器,程序员可以通过改变寄存器中的内容实现对CPU的控制。CPU从何处执行指令是由CS、IP中的内容决定的,程序员可以通过改变CS、IP中的内容来控制CPU执行目标指令。
我们如何改变CS、IP的值呢?显然,8086CPU必须提供相应的指令。我们如何修改AX中的值?
可以用mov指令,
如 mov ax,123将ax中的值设为123,显然,我们也可以用同样的方法设置其他寄存器的值,如 mov bx,123, mov cx,123, moy dx,123等。其实8086CPU大部分寄存器的值,都可以用mov指令来改变,mov指令被称为传送指令。
但是,mov指令不能用于设置CS、IP的值,原因很简单,因为8086CPU没有提供这样的功能。8086CPU为CS、P提供了另外的指令来改变它们的值。能够改变CS、IP的内容的指令被统称为转移指令(我们以后会深入研究)。我们现在介绍一个最简单的可以修改CS、IP的指令:jmp指令。
若想同时修改CS、IP的内容,可用形如“jmp 段地址:偏移地址”的指令完成,
如jmp 2AE3:3,执行后:CS=2AE3H,IP=0003H,CPU将从2AE33H处读取指令。
jmp 3:0B16,执行后:CS=0003H,TP=0B16H,CPU将从00B46H处读取指令。
“jmp段地址:偏移地址”指令的功能为:用指令中给出的段地址修改CS,偏移地址修改IP

若想仅修改P的内容,可用形如“jmp某一合法寄存器”的指令完成
“jmp某一合法寄存器”指令的功能为:用寄存器中的值修改IP。
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=0BI6H
jmp ax,在含义上好似:mov IP, ax

2.12代码段

前面讲过,对于8086PC机,在编程时,可以根据需要,将一组内存单元定义为一个段。我们可以将长度为NN≤64KB)的一组代码,存在一组地址连续、起始地址为16的倍数的内存单元中,我们可以认为,这段内存是用来存放代码的,从而定义了一个代码段。
比如,将mov ax, 0000(B8 00 00)
add ax 0123(05 23 01)
mov bx, ax(8B D8)
jmp bx(FF E3)
这段长度为10个字节的指令,存放在123B0H-123B9H的一组内存单元中,我们就可以认为,123B0H-123B9H这段内存是用来存放代码的,是一个代码段,它的段地址为123BH,长度为10个字节
如何使得代码段中的指令被执行呢?将一段内存当作代码段,仅仅是我们在编程时的种安排,CPU并不会由于这种安排,就自动地将我们定义的代码段中的指令当作指令来执行。CPU只认被CS:IP指向的内存单元中的内容为指令。所以,要让CPU执行我们放在代码段中的指令,必须要将CS:IP指向所定义的代码段中的第一条指令的首地址。对于上面的例子,我们将一段代码存放在123B0H-123B9H内存单元中,将其定义为代码段,如果要让这段代码得到执行,可设CS=123BH、IP=0000H。

检测点2.3

下面的3条指令执行后,CPU几次修改IP?都是在什么时候?最后IP中的值是多少?
mov ax, bx
sub ax ax
jmp ax
解析:
执行第一条mov指令后,IP加3,执行下一条指令
执行第二条sub指令后,IP加2,执行下一条指令
执行地三条指令后,IP的值 修改为 ax中的值
//错误,当读取第三条指令时,IP的值也会变

CPU4次修改IP:

1.将mov ax,bx指令读取入指令缓冲器

2.将sub ax,ax读取入指令缓冲器

3.将jmp ax读取入指令缓冲器

4.jmp ax指令被执行后

最后IP值为ax

  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
©️2020 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值