问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

汇编语言——寄存器

创作时间:
作者:
@小白创作中心

汇编语言——寄存器

引用
CSDN
1.
https://m.blog.csdn.net/2302_80756830/article/details/143073549

在计算机科学领域,汇编语言是与机器语言最为接近的一种编程语言,它使用助记符来表示机器指令,使得程序员能够更直观地理解和编写底层代码。本文将详细介绍汇编语言中的寄存器相关知识,包括通用寄存器、数据传送与运算指令、物理地址的计算方法、段寄存器以及控制转移指令等核心概念。

对于一个汇编程序员来说,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位的物理地址。

当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指向的内容当做指令执行

如上图,在CS=2000H,IP=0000,CPU将从2000H+0000H处开始读取指令。

CS、IP的内容送入地址加法器。

地址加法器将物理地址送入输入输出控制电路。

输入输出控制电路将物理地址20000H送上地址总线。

从内存20000H单元开始存放的机器指令B8 23 01通过数据总线被送入CPU。

输入输出控制电路将机器指令B8 23 01送入指令缓冲器。

IP中的值自动增加。

执行控制器执行指令B8 23 01。

指令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才会去执行这段代码。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号