汇编语言——寄存器


前言

对于一个汇编程序员来说,CPU中的主要部件是寄存器。寄存器是CPU中程序员可以用指令读写的部件,可通过改变各种寄存器中的内容来实现对CPU的控制。
不同CPU的寄存器的个数与结构是不同的。8086CPU有14个寄存器:AX、BX、CX、DX、SI、DI、SP、BP、IP、CS、SS、DS、ES、PSW。


一、通用寄存器

8086CPU的所有寄存器都是16位的,可存放两个字节。AX,BX,CX,DX这四个寄存器通常用来存储一般性的数据,称为通用寄存器。
8086CPU的每个通用寄存器都可以分离为两个独立的8位寄存器(高8位和低8位)来使用。

AX可分为AH和AL
BX可分为BH和BL
CX可分为CH和CL
DX可分为DH和DL

出于兼容性的考虑,8086CPU可以一次性处理以下两种尺寸的数据:
字节(byte),可寄存在8位寄存器中。
字(word),由两个字节组成,分别称为这个字的高位字节和低位字节。

任何数据,在计算机中都以二进制的形式存储。为了描述不同的问题,常常将它们用其他的进制来表示,如0100111000100000可表示成4(0100)、E(1110)、2(0010)、0(0000)四位十六进制数。计算机中一个内存单元可存放8位数据,CPU中的寄存器又可存放N个8位数据,也就是说,计算机中的大多数数据是由1~N个8位数据构成的,用十六位数据来表示可以更直观地看出组成数据的各字节数据的值,因此后面我们多用十六进制来表示一个数据。为区分不同的进制,在十六进制数后加H,在二进制数后加B,十进制数后什么也不加。如:
十进制:20000
二进制:0100111000100000B
十六进制:4E20H

二、mov,add与sub指令

1.mov

mov是数据传送指令,用于将数据从一个位置复制到另一个位置。例如:

mov ax,18

表示将18送入寄存器AX,指令执行成功后AX的值变为0012H。
注:在写一条汇编指令或一个寄存器的名称时不区分大小写

2.add与sub

add用于将目标寄存器与某个数据或某特定寄存器中的数据相加,并将结果保存在目标寄存器中;
sub则是令目标寄存器减去某个数据或某特定寄存器中的数据,并保存结果于目标寄存器中。
例如:
初始时AX=0012H(18),BX=0101H(257),CX=2233H

add ax,78

执行成功后AX=0060H(96)

add bl,al

执行成功后BX=0161H(将AX的低8位加至BX的低8位)

sub ch,11H

执行成功后CX=1133H

sub bl,ch

执行成功后BX=0150H(将BX的低8位减去CX的高8位)


若AX=0083H,在成功执行add al,81H指令后,AX的值为多少?

首先83H加上81H的结果是104H,但是al是8位寄存器,只能存放两位十六进制数据,所以最高位的1丢失,此时AX的数据应为:0004H(这里的“丢失”指的是进位值不能在8位寄存器中保存,但是CPU并不是真的丢弃这个进位值
因为此时al是作为一个独立的8位寄存器来使用的,和ah并没有关系,CPU在执行这条指令时认为ah和al是两个不相关的寄存器。不要错误地认为此类指令产生的进位会存储在ah中。


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


三、物理地址

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

1.16位结构的CPU

8086是典型的16位结构的CPU,其具有以下几方面的结构特性:

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

2.8086CPU给出物理地址的方法

内存单元的地址在送上地址总线之前,必须在CPU中处理,传输,暂时存放。8086CPU有20位地址总线,可传达20位地址,达到1MB寻址能力。但8085是16位结构,在内部一次性处理、传输。暂时存储的地址为16位,如果只是将地址从内部简单地发出,那么它只能送出16位的地址,寻址能力只能达到64KB。8086CPU采用一种在内部用两个16为地址合成的方法来形成一个20位的物理地址。
8085CPU相关的逻辑结构
当8086CPU要读写内存时:
1)CPU中的相关部件提供两个16位的地址,一个称为段地址,另一个称为偏移地址;
2)段地址和偏移地址通过内部的总线送入一个称为地址加法器的部件;
3)地址加法器将两个16位地址合成位一个20位的物理地址;
4)地址加法器通过内部总线将20位物理地址送入输入输出控制电路;
5)输入输出控制电路将20位物理地址送上地址总线;
6)20位物理地址被地址总线送到存储器。
在上面第3步中,地址加法器采用物理地址=段地址*16+偏移地址的方法用段地址和偏移地址合成物理地址。例如,8086CPU要访问地址为123C8H的存储单元,此时地址加法器的工作过程如图所示:
地址加法器工作过程

3.“段地址*16+偏移地址=物理地址”的本质含义

“段地址16+偏移地址=物理地址”的本质含义是:CPU在访问内存时,用一个基础地址(段地址16)和一个相对于基础地址的偏移地址相加,给出内存单元的物理地址。即基础地址+偏移地址=目标地址。例如,假定学校、体育馆与图书馆处在同一条直线上,以我们所在的学校为基点,图书馆的地址可以描述为:从学校走2000m到图书馆,也可描述为从学校走1200m到体育场,再走800m到达图书馆。从该例子上看,2000m便是目的地址,也可认为“物理地址”,1200m可认为成“基础地址”,即“段地址*16”,800m则可认为是“偏移地址”。8086CPU就是如此描述物理地址的。

4.段的概念

“段地址”名称中虽包含了段,但内存本身并没有被分段,段的划分来自于CPU。由于CPU用“段地址*16+偏移地址=物理地址”的方式给出内存单元物理地址,使我们可以用分段的方式管理内存。
分段
如上图,我们可以以10000H作为基础地址,将10000H ~ 100FFH作为一个段,段地址为1000H,大小为FFH;我们也可以以10000H和10080H作为基础地址,将10000H ~ 100FFH分为两个段,段地址为1000H和1008H,大小都为80H。

四、段寄存器

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

1.CS和IP

CS、IP是8086CPU中最关键的寄存器,CS为段寄存器,IP为指针指令寄存器。
在8086机的任意时刻,设CS中的内容为M,IP中的内容为N,8086CPU将从内存M*16+N单元开始,读取一条指令并执行。
换句话说,8086机中,任意时刻,CPU将CS:IP指向的内容当做指令执行
8086CPU读取和执行指令的相关部件
如上图,在CS=2000H,IP=0000,CPU将从2000H+0000H处开始读取指令。
CS、IP的内容送入地址加法器
CS、IP的内容送入地址加法器。
地址加法器将物理地址送入输入输出控制电路
地址加法器将物理地址送入输入输出控制电路。
输入输出控制电路将物理地址20000H送上地址总线
输入输出控制电路将物理地址20000H送上地址总线。
从内存20000H单元开始存放的机器指令B8 23 01通过数据总线被送入CPU
从内存20000H单元开始存放的机器指令B8 23 01通过数据总线被送入CPU。
输入输出控制电路将机器指令B8 23 01送入指令缓冲器
输入输出控制电路将机器指令B8 23 01送入指令缓冲器。
IP中的值自动增加
IP中的值自动增加。
执行控制器执行指令B8 23 01
执行控制器执行指令B8 23 01。
指令B8 23 01被执行后AX中的内容为0123H
指令B8 23 01被执行后AX中的内容为0123H。
通过上面的过程展示,8086CPU的工作过程可以简略描述如下:

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

在8086CPU加电启动或复位后(即CPU刚开始工作时)CS和IP被设置为CS=FFFFH,IP=0000H,即在8086机刚启动时,CPU从内存FFFF0H单元中读取指令执行,FFFF0H单元中的指令是8086机开机后执行的第一条指令。
上一章中我们讲过,在内存中,指令和数据没有任何区别,都是二进制信息。那么CPU根据什么将内存中的二进制信息看做指令?现在我们可以知道,CPU将CS:IP指向的内存单元中的内容看做指令如果说,内存中的一段信息曾被CPU执行过的话,那么,它所在的内存单元必然被CS:IP指过。

2.jmp指令

我们现在知道,CPU从何处执行指令是由CS、IP中的内容决定的,那么,我们是否能够改变CS、IP中的值,从而控制CPU执行目标指令呢?
答案当然是可以的,我们可以通过jmp指令来达到这一目的。
若想同时修改CS.IP的内容,可用“jmp 段地址:偏移地址”的指令完成。如:

jmp 2AE3,3

指令执行成功后CS=2AE3H,IP=0003H,CPU将从2AE33H处读取命令。
若想仅修改IP的内容,可用“jmp 某一合法寄存器”的指令完成,其功能可表示为:用寄存器中的值修改IP,如:
执行前,AX=1000H,CS=2000H,IP=0003H

jmp ax

执行后,AX=1000H,CS=2000H,IP=1000H

3.代码段

对于8086PC机,在编程时,可根据需要,将一组内存单元定义为一个段,我们可以将长度<=64KB的一组代码,存放在一组地址连续起始地址为16的倍数的内存单元中,我们可以认为,这段内存时用来存放代码的,从而定义了一个代码段。例如,将:

mov ax,0000(B8 00 00)
add ax,0123H(05 23 01)
mov bx,ax(8B D8)
jmp bx(FF E3)

这段指令存放在123B0H ~ 123B9H的一组内存单元中,我们就可以认为,这一段内存是用来存放代码的,是一个代码段。段地址位123BH。那么如何使得这段代码的指令被执行呢?首先,代码段仅仅只是我们自己的安排,CPU并不会因为这些安排而自动地执行这些代码,而是需要我们通过修改CS和IP的内容,使得CS:IP指向123B0H,CPU才会去执行这段代码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值