1. 字长与寄存器
学习汇编语言以 Intel 8086 CPU 为基础会更容易掌握。
要知道,微型计算机的字长与微处理器的寄存器位数有关。
-
以 Intel 80X86 系列微处理器为例,CPU 是 8086/8088、80286 的字长是 16 位(二进制位 bit),那么它们的寄存器的位数一定是 16 位的;
-
32 位字长的微机 CPU 是 80386/80486 或者 Pentium 系列,它们的寄存器的位数则是 32 位的。
学习汇编语言我们会用到十六进制(H)的数据形式,要使自己尽快习惯用十六进制来思维。
在汇编语言中,
数值后面分别用字母B、H、D代表:
二进制(Binary)、
十六进制(Hexadecimal)、
十进制数(Decimal)(十进制数可以省略 D)。
在计算机中还规定采用字节、字、双字等单位来表示数据。
- 字节(Byte):8 位二进制数。如
00000101B
或表示成05H
;10000101B
或表示成85H
。 - 字(Word):16 位二进制数,等于 2 字节。如
1100010111010110B
或表示成C5D6H
。 - 双字(Double Word):32 位二进制数,又称为双精度数,等于 4 字节。如
23456789H
。
1.1 指令和数据
指令和数据, 都存储在内存和磁盘上,并且都是二进制信息。
那么如何区分,这段二进制信息到底是 数据还是指令呢?
由CPU决定, 这取决于CPU使用这串二进制信息的方式, 即CPU执行这串二进制信息的方式, 是把使用指令的方式执行的, 还是使用数据的方式执行的。
执行为数据时: 1000100111011000 -> 89D8H (数据)
执行为指令时: 1000100111011000 -> MOV AX, BX( 指令)
1.2 统一编址
注意, 在对各类存储器时,进行位置编码时,
是将各类物理存储器被看做是一个统一的存储区,
只不过该统一的存储器是由若干存储单元组成的逻辑存储器;
每个物理存储器在这个逻辑存储器中占有一个地址段, 即一段地址空间;
1.3 CPU中的寄存器
2. 8086 寄存器
8086 寄存器都是 16 位的寄存器,根据用途可分为 4 种类型。分别是数据寄存器、地址寄存器、段寄存器和控制寄存器。
如图所示:
2.1 数据寄存器
数据寄存器中每个寄存器又可以分为 2 个 8 位的寄存器。分别为 AH、AL,BH、BL,CH、CL,DH、DL。H 表示高字节(高 8 位)寄存器、L 表示低字节(低 8 位)寄存器。
例如:用 AX 寄存器存放一个字 1234H,表示为 (AX)=1234H,即高字节 12 放在 AH,低字节 34 放在 AL 中。
2.2 地址寄存器
地址寄存器包括指针和变址寄存器 SP、BP、SI、DI 四个 16 位寄存器。
顾名思义,它们可用来存放存储器操作数的偏移地址。另外,它们也可以作为通用寄存器用。
2.3 段寄存器
8086CPU 有 4 个 16 位的段寄存器,分别是 CS 代码段寄存器、DS 数据段寄存器、ES 附加段寄存器、SS 堆栈段寄存器。
2.4 控制寄存器
控制寄存器包括 IP 和 FLAGS(又称为 PSW 程序状态字)两个 16 位寄存器,用于控制程序的执行。
IP 指令指针寄存器,用来存放代码段中的偏移地址,指出当前正在执行指令的下一条指令所在单元的偏移地址。
FLAGS 标志寄存器中的某位代表 CPU 的 1 个标志,表示出 CPU 的某种执行状态。最低位为 D0,最高位为 D15。8086CPU 的标志寄存器共有 9 个标志,分别为 6 个条件码标志和 3 个控制标志。如图:
条件码标志:
- CF 进位标志。当指令执行结果的最高位向前有进位时,CF=1,否则 CF=0。
- SF 符号标志。当指令执行结果的最高位(符号位)为负时,SF=1,否则 SF=0。
- ZF 零标志。当指令执行结果为 0 时,ZF=1,结果不为 0 时,ZF=0。
- OF 溢出标志。当指令执行结果有溢出(超出了数的表示范围)时,OF=1,否则 OF=0。
- AF 辅助进位标志。当指令执行结果的第 3 位(半字节)向前有进位时,AF=1,否则 AF=0。
- PF 奇偶标志。当指令执行结果中 1 的个数为偶数个时,PF=1,否则 PF=0。
控制标志:
- DF 方向标志。执行串处理指令时,若设置 DF=0,存储单元的地址寄存器的值自动增加,若设置 DF=1,存储单元的地址寄存器的值自动减小。
- IF 中断标志。设置 IF=1,允许 CPU 响应可屏蔽中断,IF=0 则不响应。
- TF 陷阱标志。在 DEBUG 调试时,TF=1,采用单步执行方式,即进入陷阱;TF=0,正常执行程序。
两个二进制数相加运算,有关标志位自动发生变化。
根据计算结果可知 CPU 会自动地把标志位设为:CF=0,SF=1,ZF=0,OF=0,PF=0,即无进位,结果为负数,结果不为 0,没有溢出,奇数个 1。
对溢出的判断也可以从简单的角度理解,因为进行运算的二进制数是补码,可看出本题是一个负数和一个正数相加,结果为负数,不溢出。若两个正数相加,结果为负数,或者两个负数相加,结果为正数,那都是溢出了,说明 8 位补码已经表示不了该结果。
2.5 DEBUG 下的标志位表示
在 DEBUG 调试环境下以字母缩写的形式表示各个标志位的状态。
进入 DEBUG 后,用 R 命令查看寄存器状态时,可以看到除了陷阱标志以外的标志位的状态。
2.6 数的补码运算
在计算机中,对带符号数可用真值和机器数两个概念表示。
真值,就是带有“+”、“-”号的实际数值;所谓机器数,则是把“+”、“-”符号数值化(0、1)后所得到的计算机实际能表示的数。
机器数有三种码表示,分别是原码、反码和补码。汇编语言中,数都是以补码的形式表示的,因此必须掌握数的补码表示和补码的运算。这三种码的定义如下:
- 原码。原码将最高位作为符号位,正数为 0,负数为 1,其余 7 位作为数值位。
- 反码。正数的反码与正数的原码一样。而求负数的反码时,符号位为 1,数值位在原码的基础上求反。
- 补码。正数的补码与正数的原码一样。求负数的补码时,符号位为 1,数值位在原码的基础上求反加 1
十进制数 +5 和 -5 分别表示成二进制数原码、反码和补码。
[+5]原 = [+5]反 = [+5]补 = 00000101B
[-5]原 = 10000101B
[-5]反 = 11111010B
[-5]补 = 11111011B
3. 内存
在汇编语言中,内存是非常重要的学习内容。我们先要对内存地址和存储单元的概念进行学习。
对存储单元的标识可以用物理地址或逻辑地址表示。
3.1 物理地址
物理地址是内存单元的真实地址,存储单元的物理地址是唯一的。
Intel 8086 CPU 有 20 根地址线,因此其存储空间可达 2 的 20 次方 = 1 M 个字节单元(1MB)。
地址都是从 0 开始的,在 20 位地址线的存储空间中采用十六进制表示的物理地址范围是 00000H ~ FFFFFH
。
3.2 逻辑地址
逻辑地址是用户编程时使用的地址,分为段地址和偏移地址两部分。
在 8086 汇编语言中,把内存地址空间划分为若干逻辑段,每段由一些存储单元构成,每段最大为 65536 个字节单元(0 号单元~65535 号单元 0000H~FFFFH
。
用段地址指出是哪一段,偏移地址标明是该段中的哪个单元。
段地址和偏移地址都是 16 位二进制数。
逻辑地址的形式:段地址:偏移地址
。
在上图中,内存划分出了若干段。0 号段,1 号段,…,每一段都有 0 号单元、1 号单元、2 号单元,…。每段的长度可以不一样,如 0 号段从 0 号单元到 0FH 号单元共 16 个字节单元,1 号段从 0 号单元到 0139H 号单元共 314 个字节单元。
用段地址表示段号,偏移地址代表每一段中的单元号,比如 0000:0002H 代表 0 号段的 2 号单元,0001:0002H 代表 1 号段的 2 号单元,以此类推。因此,偏移地址的通俗含义是在该段内,相对于段地址偏移了多少个单元。
3.3 逻辑地址转换为物理地址
用户编程时采用的逻辑地址在 CPU 执行程序时都要转换成实际的物理地址,这个转换过程是由 CPU 中的地址加法器自动完成的。
转换时先将 16 位的段地址左移 4 位,相当于乘以 16 或十六进制的 10H,再和偏移地址相加。转换公式为:
物理地址 = 段地址 × 10H + 偏移地址
例:若某单元的逻辑地址为 0001:0002H,其物理地址 = 0001H × 10H + 0002H = 00012H;另一单元的逻辑地址为 3020:055AH,其物理地址 = 3020H × 10H + 055AH = 3075AH。
存储器逻辑分段类型如下:
- 代码段:用于存放指令,段地址存放在段寄存器 CS。
- 数据段:用于存放数据,段地址存放在段寄存器 DS。
- 附加段:用于辅助存放数据,段地址存放在段寄存器 ES。
- 堆栈段:是重要的数据结构,可用来保存数据、地址和系统参数,段地址存放在段寄存器 SS。
存储单元中的数据称为存储单元内容,一个实际的存储单元只能存放一个字节(8 位二进制)的数据。存储单元的地址和内容的表示形式为用括号将地址括起来以代表单元的内容。
如(3075AH)=12H,表示 3075AH 号单元中的内容是 12 H,称为字节单元;
若(37692H)=5678H,表示 37692H 单元和 37693H 单元一起存放 5678H,该单元是字单元。字单元在存储的时候,高字节放在高地址单元,低字节放在低地址单元,即 56H 放在 37693H 单元,78H 放在 37692H 单元。
如图:
有关 CPU 和存储单元的概念我们已经了解了,那么如何观察实际机器内部的情况呢?能不能看到具体的寄存器、标志、存储单元的内容呢?可不可以修改和控制它们呢?
这一系列的疑问我们可以在调试工具软件 DEBUG 的支持下得到解答。通过上机实验,可加强相关理论概念的理解;而掌握了 DEBUG 这个有力工具,就可以深入到机器内部进行观察了。