第一章 基础知识

1.1汇编语言的一般概念

计算机程序设计语言分为三类:

a.机器语言:以二进制数码表示

优点:运行速度快,程序长度最短。
缺点:不便于记忆和阅读。

b.高级语言:类似自然语言的语句来编制程序

优点:程序设计简单。
缺点:程序效率较机器语言低。

c.汇编语言

(1)定义

使用字母符号来表示机器语言的命令,用十进制数或十六进制
数来表示数据,这样的计算机程序设计语言就称为汇编语言。

(2)汇编语言程序与机器语言程序的关系

一条汇编语言的语句与一条机器语言指令对应(一对一),汇编语言程序与机器语言程序效率相同。

(3)不同类型计算机有不同的机器指令系统和汇编语言描述

需要熟悉计算机的内部组成结构,但只需要掌握用汇编语言编制程序时所涉及到的那些硬件的结构和功能

1.2 学习和使用汇编语言的目的

1.学习和使用汇编语言可以从根本上认识、理解计算机的工作过程。

即更充分地利用机器硬件的全部功能,发挥机器的长处

3. 汇编语言程序的效率高于高级语言程序

“效率”的含义:

程序的目标代码长度
程序运行的速度

1.3 进位计数制及其相互转换

一. 进位计数制

使用一定个数的数码的组合来表示数字。

一些基本含义

位权:各个位置上所表示的基本数值称为位权, 简称
基数:每个数位上能使用不同数码的个数称为基数。

二. 各种数制间的相互转换

1. 十进制整数转换为二进制数

(1)减权定位法

(2)除基取余法

2.十进制小数转换为二进制数

(1)减权定位法

(2)乘基取整法

3. 二进制整数转换为十进制数

(1)按权相加法

(2)逐次乘基相加法

4. 二进制小数转换为十进制数

(1)按权相加法

(2)逐次除基相加法

5. 二进制与八进制和十六进制间的转换

对应关系:

三位二进制数对应一位八进制数,四位二进制数对应一位十六进制数。

1.4 带符号数的表示

在一般算术表示中使用“+”和“-”来表示正数负数,而在计算机中使用“0”和“1”来表示正数负数。用“+”或“-”表示正负的数叫真值

一、原码表示

二进制数的最高位表示符号,0表示正1表示负。数值部分用二进制数绝对值表示。

二、补码的表示

1.补码的定义

带符号数X的补码表示[X]补定义为:
[X]补=M+X (Mod M)

2.由真值、原码变换为补码

负数的真值变换为补码的方法:将各位变反(0变1,1变0)然后在最低位加1.
负数的原码变换为补码:保持符号位不变,其余各位变反最低位加1

3.补码数的表示范围

当位数为8时:
最大补码为01111111=[+127]补
最小补码为10000000=[-128]补

4. 补码的加减运算

规则:
[X+Y]补=[X]补+[Y]补
[X-Y]补=[X]补-[Y]补=[X]补+[-Y]补
注:[-Y]补是对[Y]补执行一次求补运算

1.5 字符的表示

在计算机内部目前最广泛采用的是ASCII码

标准ASCII码为一字节,其中用低七位表示字符编码,用最高位表示奇偶数验位。

1.6 基本逻辑运算

由于状态“0”和“1”正好与逻辑运算中的逻辑“真”和“假”对应,因此可以用“0”和“1”来表示逻辑变量的取值

1. “与”运算(AND)

“与”运算是指:仅当逻辑变量A与B都是1时,运算结果F才为1。其它情况F为0,即:0 ∧ 0 =0,0 ∧ 1 = 0,1 ∧ 0 = 0,1 ∧ 1 =1

2. “或”运算(OR)

“或”运算是指当逻辑变量A与B中,至少有一个为1时,结果F为1,其他情况F为0。即:0 ∨0=0 ,0 ∨1=1 ,1 ∨0=1 ,1 ∨1=1

3.“非”运算

“非”运算是指对逻辑变量取相反的一个逻辑值,即:1 = 0 ,0 = 1

4. “异或”运算(XOR)

“异或”运算是指:当A和B相同时(同时为1或同时为0),运算结果F为0,而不同时,F为1。即:1 ⊕ 1=0 ,1 ⊕ 0=1 0, ⊕ 1=1 0⊕, 0=0

第二章 IBM-PC微机的功能结构

2.1 IBM-PC微机基本结构

一. 微机的一般构成

五大部件:运算器、控制器、存储器、输入设备和输出设备。

1、中央处理器CPU

概念:将运算器和控制器两大部件集成在一个集成电路芯片上,称为中央处理器 ,简称CPU,也叫微处理器
功能:分析从主存储器取来的各条指令的功能,控制计算机各部件完成指定功能的各项操作

2、主存储器

概念:主存储器是用来存放程序和数据的部件。它由若干个存储单元构成。
存储单元:存储单元的多少表示存储器的容量。每个存储单元使用一个唯一的编号来标识,称为存储单元的地址。
访问规则:对每个存储单元内容的存和取是按照地址进行访问的。

习惯上将CPU与主存储器合称为主机。
在计算机中,除了主存储器之外,一般还配置有辅助存储器,简称辅存。由于它的位置是在主机之外,因此也叫做外存

3、输入输出设备及接口

输入设备:
将外部信息(程序、数据和命令)送入计算机。包括键盘、鼠标等。
输出设备:
将计算机处理后的结果转换为人或其它系统能识别的信息形式向外输出。如显示器、打印机等。
有的设备既具有输入功能又具有输出功能
磁盘、磁带、触摸显示屏等。
I/O接口:主机与I/O设备之间设置的逻辑控制部件。通过它实现主机与I/O设备间的信息传送。

4、系统总线

包括地址总线数据总线控制总线三组。它们分别用于传送不同的信息。

二、 Intel 8086/8088 CPU的功能结构

汇编语言程序是由一系列的指令(指令序列)构成,指令是构成汇编语言程序的最基本单位
CPU执行指令序列就是重复执行以下两个步骤:
从存储器中取指令
执行指令规定的操作

1. 串行方式

缺点:采用串行工作方式的计算机其运行速度较慢

2.指令流水线方式

优点:采用指令流水线工作方式的计算机具有较高的工作效率。

(1)执行单元EU

分析与执行指令

(2)总线接口单元BIU

负责CPU与存储器、I/O的信息传送

2.2 Intel 8086/8088CPU寄存器结构及其用途

一、通用寄存器

Intel 8086/8088有8个16位通用寄存器

1. 数据寄存器

它包括AX、BX、CX和DX四个寄存器,每一个既可以是16位寄存器,也可以分成两个8位寄存器使用。

2. 指针寄存器

堆栈指针SP和基址指针BP,一般被用来存放16位地址,在形成20位的物理地址时常被作为偏移量使用。
SP指针:在进行堆栈操作时,被隐含使用,被用来指向
堆栈顶部单元.
BP指针:被用来指向堆栈段内某一存储单元。

3. 变址寄存器

有两个16位的变址寄存器SI和DI,一般被用来作地址指针.
SI:源变址寄存器
DI:目的变址寄存器

二、段寄存器

段基址:每个存储段用一个段寄存器来指明该段的起始位置。

注:CPU在访问存储器时必须指明两个内容

(1)所访问的存储单元属于哪个段,即指明使用的段寄存器

(2)该存储单元与段起始地址(段基址)的相距多少,即偏移量

三、指令指针IP

概念:当CPU从内存中取出一条指令后,IP内容自动修改为指向下一条指令。

四、标志寄存器

概念:用来反映CPU在程序运行时的某些状态,如是否有进位、奇偶性、结果的符号、结果是否为零等等。
:8086/8088CPU中标志寄存器的长度为16位,但只定义了其中的9位。

1. 进位标志位CF

2. 奇偶标志位PF

3. 辅助进位标志位AF

4. 零值标志位ZF

5. 符号标志位SF

6. 溢出标志位OF

7. 单步标志位TF(Trace Flag)

8. 中断允许标志位IF

9. 方向标志位DF

2.3 存储器组织结构

1. 存储器是由若干个存储单元构成

2. 每个存储单元存放相同长度的二进制数。

3. 每个存储单元有一个唯一的地址编号——地址

4. 任何两个相邻字节单元就构成一个字单元.

5、在定义一个地址时必须指出是字节或字类型属性

二、存储器的段结构

1.每个段最大长度为64K(65536)个字节单元组成。

2. 每个段的基址(段基址)必须是一个小节的首址。(注:段基址为一个段的起始地址)

3. 逻辑段在物理存储器中可以是邻接的、间隔的、部分重叠的和完全重叠的等4种情况。

4. 在任一时刻,一个程序只能访问4个当前段中的内容。

4个段分别是代码段、数据段、堆栈段和附加段,称为当前段。

三、 逻辑地址与物理地址及对应关系

1. 物理地址

在1MB的存储空间中,每个存储单元的物理地址是唯一的,它就是该存储单元的20位地址。
:CPU与存储器之间的任何信息交换都使用物理地址

2. 逻辑地址

一个逻辑地址包括两个部分:段基值和偏移量
段基值:存放在某一个段寄存器中,是一个逻辑段的起始单元地址(段基址)的高16位。
偏移量:表示某个存储单元与它所在段的段基址之间的字节距离。
逻辑地址的表示方法:
段基值:偏移量

3.逻辑地址转换为物理地址

转换方法:将逻辑地址的段基值左移4位,形成20位的段基址(低位为0)然后与16位的偏移量相加,结果即为20位的物理地址。

4.逻辑地址的来源

(1)允许替代来源也叫做段超越,它表示了段基值除使用隐含的段寄存器外是否可以指定其它段寄存器来提供。

(2)有效地址EA,它表示根据指令所采用的寻址方式(下一章介绍)计算出来的段内偏移量。

2.4 堆栈及其操作方法

堆栈的用途:主要用于暂存数据以及在过程调用或处理中断时保存断点信息

一、堆栈的构造

专用堆栈存储器:按堆栈的工作方式专门设计的存储器
软件堆栈:由程序设计人员用软件在内存中划出的一块存储区作为堆栈来使用。
:堆栈的一端是固定的,称为栈底。栈底是堆栈存储区的最大地址单元。另一端是浮动的,称为栈顶
指针sp:SP的内容始终指向栈顶单元,堆栈中数据进出都由SP来控制。
堆栈存取数据规则:“先进后出FILO”。

二、8086/8088堆栈的组织

顶由堆栈指针SP指示。SP中内容始终表示堆栈段基址与栈顶之间的距离(字节数)。当SP内容为最大(初始)值时,表示堆栈为空。而当(SP)=0时,表示堆栈全满.
当SP被初始化时,指向栈底+2单元,其值就是堆栈的长度。

三、堆栈操作

1.设置堆栈:主要是对堆栈段寄存器SS和堆栈指针SP赋值

2.进栈PUSH:是把数据存入堆栈。由指令PUSH或者由机器自动实现,可以将通用寄存器、段寄存器或字存储单元的内容压入堆栈顶部。

进栈的执行过程

(1)首先将堆栈指针SP减2,即指向一个空的堆栈字单元 SP<=(SP)-2
(2)将要储存的内容(寄存器或存储单元的内容)送入SP指向的字单元中。(SP)<=数据

3.出栈POP:出栈操作由POP指令或机器自动实现,它从堆栈顶部弹出一个字到通用寄存器、段寄存器或字存储单元

出栈的操作过程:

(1)将SP指向的字单元(即栈顶字单元)内容送往指定的寄存器或存储器。即:寄存器/存储器<=((SP))
(2)堆栈指针SP内容加2,即:SP<=(SP)+2

第三章 寻址方式与指令系统

3.1 寻址方式

一条指令通常由两大部分构成:

操作码:表示该指令应完成的具体操作,如加法、减法、乘法、移位等等。

操作数: 表示该指令的操作对象。如移位操作的被移位数,加法操作的加数等等。

寻址方式:寻找指令中所需操作数的各种方法,也就是提供指令中操作数的存放信息的方式。

(1)立即数操作数——操作数在指令代码中提供

(2)寄存器操作数——操作数在CPU的通用寄存器或段寄存器中

(3)存储器操作数——操作数在内存的存储单元中

(4)I/O端口操作数——操作数在输入/输出接口的寄存器中

1.立即数寻址:立即数寻址方式的指令中,所需操作数直接包含在指令代码中,这种操作数称为立即数。

:立即数只能作为源操作数,而不能作为目的操作数。

2.寄存器寻址:寄存器寻址方式是指指令中所需的操作数在CPU的某个寄存器中。寄存器可以是8位或16位通用寄存器,或者是段寄存器。

:由于存取寄存器操作数完全在CPU内部进行,不需要总线周期,所以执行速度很快

一个存储单元逻辑地址表示形式:

段基值:偏移量
段基值:由某个段寄存器提供.
偏移量:表示了该存储单元与段起始地址之间的距离,也叫做有效地址EA

有效地址EA是以下三个地址分量的几种组合,由CPU的执行单元EU计算出来的。

(1)位移量:位移量是指令中直接给出的一个8位或16位数。
(2)基址:由基址寄存器BX或基址指针BP提供的内容。
(3)变址:由源变址寄存器SI或目的变址寄存器DI提供的内容

:位移量、基址和变址三个地址分量组合时,若有两个或两个以上分量时,将进行以2^16为模的十六位加法运算。

3.直接寻址:在直接寻址方式的指令中,操作数的有效地址EA只有位移量地址分量。

:用常数表示时,必须用方括号括起来。段寄存器不能省略。

4.寄存器间接寻址:是事先将偏移量存放在某个寄存器(BX、BP、SI或DI)中,这些寄存器就如同一个地址指针。在程序运行期间,只要对寄存器内容进行修改,就可以实现用同一条指令实现对不同存储单元进行操作。

5.基址寻址/变址寻址

操作数的有效地址EA等于基址分量或变址分量加上指令中给出的位移量。

指令中使用BX或BP时为基址寻址

指令中使用SI或DI时为变址寻址

6.基址变址寻址

操作数的有效地址是三个地址分量之和,即:

EA=基址+变址+位移量

注:

当基址选用BX时隐含使用段寄存器DS,而选用BP时则隐含使用段寄存器SS

7.串操作寻址方式

寻找源操作数时,隐含使用SI作为地址指针。

寻找目的串时,隐含使用DI作为地址指针。

串操作完成之后,自动对SI和DI进行修改,使它们指向下一个操作数

8. I/O端口寻址

存储器编址方法:

将I/O端口视为存储器的一个单元,对端口的访问就如同访问存储单元一样。

特点: 程序设计灵活,但需要占用存储地址空间

I/O端口编址方法

I/O端口的地址与存储器地址分开,并使用专门的输入指令和输出指令。寻址方式有如下两种:

(1) 直接端口寻址

在指令中直接给出端口地址,端口地址一般采用2位十六进制数,也可以用符号表示。

(2)寄存器间接端口寻址

寄存器间接端口寻址:把I/O端口的地址先送到DX中,用DX作间接寻址寄存器。

3.2 指令系统

一种计算机所能执行的各种类型的指令的集合称为该计算机的指令系统

Intel8086/8088CPU指令系统的指令可以分为六大类:

1.传送类指令

2.算术运算类指令

3.位操作类指令

4.串操作类指令

5.程序转移类指令

6.处理器控制类指令

从指令的格式划分,一般可以分为三种:

1.双操作数指令:OPR DEST SRC

2.单操作数指令:OPR DEST

3.无操作数指令:OPR

对于无操作数指令,包含两种情况:

(1)指令不需要操作数,如暂停指令HLT。

(2)在指令格式中,没有显式地指明操作数,但是它隐含指明了操作数的存放地方,如指令PUSHF。

一、传送类指令:传送类指令的作用是将数据信息或地址信息传送到一个寄存器或存储单元中

1.通用数据传送指令

指令格式:MOV DEST,SRC

作用:将源操作数指定的内容传送到目的操作数,即DEST<=(SRC)

MOV指令可以是字节数据传送也可以是字数据传送,但是源操作数和目的操作数的长度必须一致。

MOV指令对标志寄存器的各位无影响,MOV指令可以分为以下几种情况:

(1)立即数传送到通用寄存器或存储单元:立即数只能作为源操作数,立即数不能传送给段寄存器。
(2)寄存器之间的传送:段寄存器CS只能作源操作数,不能作目的操作数。
(3)寄存器与存储单元之间传送

总结:

(1)立即数只能作源操作数,且它不能传送给段寄存器。

(2)段寄存器CS只能作源操作数,段寄存器之间不能直接传送。

(3)存储单元之间不能直接传送数据

(4)MOV指令不影响标志位

2.交换指令

指令格式:XCHG DEST,SRC

作用:源操作数和目的操作数两者内容相互交换,即:(DEST)<=>(SRC)。

3.标志传送指令:对标志寄存器进行存取的指令有4条,它们都是无操作数指令,即指令隐含指定标志寄存器AH寄存器堆栈为操作数。

(1)取标志寄存器指令

指令格式:LAHF

作用:将标志寄存器的低8位送入AH寄存器,即将标志SF、ZF、AF、PF和CF分别送入AH的第7、6、4、2、0位,而AH的第5、3、1位不确定。

(2)存储标志寄存器指令

指令格式:SAHF

作用:将寄存器AH中的第7、6、4、2、0位分别送入标志寄存器的SF、ZF、AF、PF和CF各标志位。而标志寄存器高8 位中的各标志位不受影响

(3)标志进栈指令

指令格式:PUSHF

作用:先将堆栈指针SP减2,使其指向堆栈顶部的空字单元,然后将16位标志寄存器的内容送SP指向的字单元。

(4)标志出栈指令

作用:将由SP指向的堆栈顶部的一个字单元的内容送

入标志寄存器,然后SP的内容加2.指令格式:POPF

4.地址传送指令:这类指令有3条,它们的作用是将存储单元的地址送寄存器

(1)装入有效地址

格式:LEA DEST,SRC

其中:源操作数SRC必须是一个字节或字存储器操作数(地址),DEST必须是一个16位通用寄存器。

作用:将SRC存储单元地址中的偏移量,即有效地址EA传送到一个16位通用寄存器中

(2)装入地址指针指令

格式:LDS DEST,SRCLES DEST,SRC

其中:DEST是任意一个16位通用寄存器。SRC必须是一个存储器操作数。

作用:把SRC存储单元开始的4个字节单元的内容(32位地址指针)送入DEST通用寄存器和段寄存器DS(LDS指令)或ES(LES指令),其中低字单元内容为偏移量送通用寄存器,高字单元内容为段基值送DS或ES

二、算术运算类指令

1.加法指令

功能:目的操作数和源操作数相加,其和存放到目的操作数中,而源操作数内容保持不变,即DEST<=(DEST)+(SRC)

2.带进位加法指令

指令格式:ADC,DEST,SRC该指令的功能与ADD基本相同,所不同的是其结果还要加上进位标志CF的值,即:DEST<=(DEST)+(SRC)+CF。根据相加的结果设置标志寄存器中的CF、PF、AF、ZF、SF和OF

注:参加运算的进位CF是本条指令执行之前的值。

3.加1指令

指令格式:INC DEST

功能:该指令为单操作数指令,其功能是将目的操作数加1,并送回到目的操作数,即:DEST<=(DEST)+1

4.减法指令

指令格式:SUB DEST,SRC

功能:目的操作数的内容减去源操作数的内容,结果送入目的操作数,源操作数中内容保持不变。即:DEST<=(DEST)-(SRC)

5.带借位减法

指令格式:SBB DEST,SRC

功能:与SUB指令基本相同,不同的是在两个操作数相减后再减去进位标志CF的值。即:DEST<=(DEST)-(SRC)-CF。

注:该CF的值是本条指令执行前的结果

6.减1指令

指令格式:DEC DEST

该指令为单操作数指令,将目的操作数的内容减1后,送回到目的操作数。即:DEST<=(DEST)-1

7.求负数指令

指令格式:NEG DEST

功能:用零减去目的操作数的内容,并送回目的操作数,即:DEST<=0-(DEST)

三、位操作类指令

1.逻辑运算指令:逻辑运算指令共有4条。

逻辑“与”指令 AND DEST,SRC

逻辑“或”指令 OR DEST,SRC

逻辑“异或”指令 XOR DEST,SRC

逻辑“非”指令 NOT DEST

注:DEST和SRC可以是8位或16位的通用寄存器或存储器操作数,但两者不能同时为存储器操作数,SRC可以为立即数

2.测试指令

指令格式:TEST DEST,SRC

功能:与AND指令相似,实现源操作数与目的操作数进行按位“逻辑与”运算,对标志位的影响与AND指令相同,但运算的结果不送入目的操作数,即目的操作数内容也将保持不变。

3.移位/循环移位指令:这一类指令共有8条,分为3类。

(1)算术移位

算术左移 SAL DEST,COUNT
算术右移 SAR DEST,COUNT

(2)逻辑移位

逻辑左移 SHL DEST,COUNT
逻辑右移 SHR DEST,COUNT

(3)循环移位

小循环

循环左移 ROL DEST,COUNT
循环右移 ROR DEST,COUNT

大循环

带进位循环左移 RCL DEST,COUNT
带进位循环右移 RCR DEST,COUNT

注:这8条指令具有以下几个共同点:

(1)DEST为操作对象,它可以是字节或字操作数,可以是通用寄存器或存储器操作数。当移位次数为1时,使用常数1或寄存器CL。

(2)COUNT用来决定移位/循环的位数,即确定移位的次数。当移位次数大于1时,必须使用寄存器CL。

(3)在执行移位时,根据指令不同,每移位一次,最高位(左移)或最低位(右移)都要送到进位标志CF。

(4)前4条移位指令根据移位结束后修改标志位CF、PF、ZF、SF和OF,而AF不确定。而后4条循环移位指令根据移位结束后的结果仅修改CF和OF。

四、处理器控制类指令

1.标志位操作指令:它们都是无操作数指令,操作数隐含为标志寄存器的某个标志位。能直接操作的标志位有CF、IF和DF。

(1)清除进位标志 CLC ;置CF为0

(2)置1进位标志 STC ;置CF为1

(3)进位标志取反 CMC ;CF的值取反

(4)清除方向标志 CLD;置DF为0

(5)置1方向标志 STD;置DF为1

(6)清除中断标志 CLI;置IF为0

(7)置1中断标志 STI;置IF为1

2、与外部事件同步的指令

HLT ;暂停指令

WAIT ;等待指令

ESC ;外部协处理器指令前缀

LOCK ;总线锁定指令

3、空操作指令: NOP执行一次NOP占用CPU三个时钟周期,它不改变任何寄存器或存储单元内容,主要用于延时。

3.3 指令编码

汇编:将汇编语言程序转换为机器语言程序的过程

汇编程序:在计算机中实现汇编过程的系统程序

汇编指令的编码格式有四种基本格式

1.双操作数指令编码格式

2.单操作数指令编码格式

3.与AX或AL有关的指令编码格式

4.其它指令编码格式

一、双操作数指令编码格式

一个操作数在寄存器中,另一操作数在寄存器存储器中。

目的操作数在寄存器或存储器中,源操作数是立即数

整个指令编码可以包含4个部分

1.操作特征部分:这部分为指令编码的首字节,它又分为以下三个段。

(1)OPCODE:操作码字段

该字段长度为6bit。它表示了该指令所执行的功能和两个操作数的来源。

(2)方向字段d

该字段与第2部分寻址特征一起来决定源操作数和目的操作数的来源。

(3)字/字节字段W

当W=1时,表示两操作数长度为字;当W=0时,表示两操作数长度为字节。

2.寻址特征部分

它与操作特征部分的方向字段d结合,指定两个操作数分别使用什么寻址方式,及使用哪个寄存器。

它包括MOD、REG和R/M三个字段,REG字段确定一个操作数,而MOD和R/M字段确定另一个操作数。

当d=1时,则目的操作数由REG字段确定,而源操作数由MOD和R/M字段确定。

当d=0时,则目的操作数由MOD和R/M 字段确定,而源操作数由REG字段确定。

(1)REG字段

由REG字段确定的一个操作数是某一通用寄存器的内容,即使用的是寄存器寻址方式。第一部分中的W字段决定操作数是字或是字节。

(2)寻址方式字段MOD和寄存器/存储器字段R/M

这两个字段共同确定一个操作数。该操作数可以在寄存器中,也可以在存储器中MOD、R/M和W字段共同确定操作数的寻址方式和所使用的寄存器

3.位移量部分

三种情况:

没有位移量

1字节位移量disp8

2字节位移量disp16

4.立即数部分

如果指令的源操作数为立即数,则指令编码中包含有该部分。它总是位于指令编码的最后1~2字节

二、单操作数指令编码格式

这种编码格式适用于只有一个操作数的指令,如INC、DEC、移位/循环等指令。指令编码为2~3字节

操作特征部分

包括OPCODE 、V和W三个字段,其中V字段只有移位/循环指令中才有该字段。其它指令中没有该字段。

V=0时,指令中使用常数1作为移位或循环次数。

V=1时,指令中使用寄存器CL作移位次数。

:由于单操作数指令中只有一个操作数,因此寻址特征部分就不需要REG字段,而该字段被用作辅助操作码

三、与AX或AL有关的指令编码格式

采用这种编码格式的指令,除一个操作数隐含指定为AX/AL外,另一个操作数可以是立即数或存储单元。

立即数:则编码中应有1~2字节的立即数

存储单元:只能使用直接寻址方式,位移量由disp字段给出。

四、其它指令编码格式

标志位操作指令堆栈操作指令等。这些指令的编码格式一般只有一个字节

第四章 汇编语言程序格式

4.1 汇编语言语句种类及其格式

汇编语言的语句可以分为指令语句伪指令语句

一、指令语句

每一条指令语句在汇编时都要产生一个可供CPU执行的机器目标代码,它又叫可执行语句

一条指令语句最多可以包含4个字段

1.标号字段

标号是可选字段,它后面必须有“:”。标号是一条指令的符号地址,代表了该指令的第一个字节存放地址

标号一般放在一个程序段或子程序的入口处,控制程序的执行转到该程序位置。

在转移指令或子程序调用指令中,可直接引用这个标号。

该字段是一条指令的必选项,它表示这条语句要求,如MOV、ADD、SHL等。

2.指令助记符字段

有些指令还可以在指令助记符的前面加上前缀,实现一定的附加操作。如串操作指令前所加的重复前缀REP。

一条指令可以有一个操作数、两个操作数或者无操作数。

3.操作数字段

如ADD、MOV指令需要两个操作数,INC、NOT指令只需一个操作数,而CLC指令不需要操作数。

4.注释字段

注释字段为可选项,该字段以分号“;”开始。它的作用是为阅读程序的人加上一些说明性内容

注释字段不会产生机器目标代码,它不会影响程序和指令的功能。

注释字段可以是一条指令的后面部分,也可以是整个语句行。

二、伪指令语句

伪指令语句又叫命令语句。

伪指令本身并不产生对应的机器目标代码。它仅仅是告诉汇编程序对其后面的指令语句和伪指令语句的操作数应该如何处理。

一条伪指令语句可以包含四个字段。

1.符号名字段

该字段为可选项。根据伪指令的不同,符号名可以是常量名、变量名、过程名、结构名和记录名等等。

一条伪指令语句的符号名可以作其它伪指令语句或指令语句的操作数,这时它表示一个常 量或存储器地址

:符号名后面没有冒号“:”,这是与指令语句的重要区别。

2.伪指令符字段

该字段是伪指令语句的必选项,它规定了汇编程序所要完成的具体操作。本章后面的章节将对各种伪指令作详细介绍。

3.操作数字段

该字段是否需要,以及需要几个是由伪指令符字段来决定。

操作数可以是一个常数(二进制、十进制、十六进制等)、字符串、常量名、变量名、标号和一些专用符号(如BYTE、FAR、PARA等)。

4.注释字段

注释字段为可选项,该字段必须以分号开始。其作用与指令语句的注释字段相同。

三、标识符

规则:

1.字符的个数为1~31个;

2.第一个字符必须是字母、问号、@或下划线“_”这4种字符之一;

3.从第二个字符开始,可以是字母数字、@ 、 “_”或问号“?”;

4.不能使用属于系统专用的保留字。

保留字: CPU中各寄存器名(如AX、CS等),指令助记符(如MOV、ADD),伪指令符(如SEGMENT、DB)、表达式中的运算符(如GE、EQ)以及属性操作符(如PTR、OFFSET等)。

4.2 汇编语言数据

数据是指令伪指令语句中操作数的基本组成部分。一个数据由数值属性两部分构成。在说明数据时不仅要指定其数值,还需说明它的属性,比如是字节数据还是字数据。在汇编语言中常用的数据形式有:常数变量标号

一、常数

常数在汇编期间其值已完全确定,并且在程序运行过程中,其值不会发生变化

常数有以下几种形式:

1.二进制数:以字母B结尾,如01001001B

2.八进制数:以字母O或Q结尾,如631Q 254O

3.== 十进制数:以字母D==结尾,或者没有结尾字母。如2007D、2007。

4. 十六进制数:以字母H结尾,如3FEH,如果常数的第一个数字为字母,为了与标识符加以区别,必须在其前面冠以数字“0”。

5.实数。一般格式为:±整数部分• 小数部分E ±指数部分

6.字符串常数:用引号(单引号或双引号)括起来的一个或多个字符,这些字符以它的ASCII码值存储在内存。

常数在程序中可以用在以下几种情况:

(1)作指令语句的源操作数

(2)在指令语句的直接寻址方式、变址(基址)寻址方式或基址变址寻址方式中作位移量

(3)在数据定义伪指令中使用。

二、变量

变量用来表示存放数据的存储单元,这些数据在程序运行期间可以被改变 。

程序中以变量名的形式来访问变量,因此,可以认为变量名就是存放数据的存储单元地址

1.变量的定义与预置

定义变量就是给变量在内存中分配一定的存储单元。也就是给这个存储单元赋与一个符号名,即变量名,同时还要将这些存储单元预置初值

注:

当变量被定义后,就具有了以下三个属性:

(1)段属性

它表示变量存放在哪一个逻辑段中。

(2)偏移量属性(OFFSET)

它表示变量所在位置与段起始点之间的字节数。

补:段属性和偏移量属性就构造了变量的逻辑地址

(3)类型属性

它表示变量占用存储单元的字节数。其中DB伪指令定义的变量为字节,DW定义的变量为字,DD定义的为双字(4字节),DQ定义的为4字,DT定义的为5字。

在变量的定义语句中,给变量赋初值的表达式可以使用下面4种形式:

(1)数值表达式

(2)?表达式

(3)字符串表达式

对于DW伪指令可以给两个字符组成的字
符串分配两个字节存储单元。
对于DD伪指令,只能给两个字符组成的字符串分配4个字节单元。
==两个字符存放在较低地址的两个字节单元中。存放顺序与DW伪指令相同,而较高地址的两个字节单元存放0。
:DW和DD伪指令不能用两个以上字符构成的字符串赋初值==,否则将出错。

(4)DUP表达式

2.变量的使用

(1)在指令语句中引用

指令语句中直接引用变量名就是对其存储单元的内容进行存取.当变量出现在变址(基址)寻址或基址变址寻址的操作数中时表示取用该变量的偏移量

(2)在伪指令语句中引用

三、标号

标号写在一条指令的前面,它就是该指令在内存的存放地址的符号表示,也就是指令地址的别名。标号主要用在程序中需要改变程序的执行顺序时,用来标记转移的目的地,即作转移指令的操作数

每个标号具有三属性

(1)段属性(SEG)

它表示该标号所代表的地址在哪个逻辑段中,即段基值

(2)偏移量属性(OFFSET)

它表示该标号所代表的地址在段内与段起点间的字节数,即地址的偏移量

(3)距离属性(也叫类型属性)

它表示该标号可以被段内还是段间的指令调用。
NEAR(近):该标号只能作段内转移,也就是说只能是与该标号所指指令同在一个逻辑段的转移指令和调用指令才能使用它。
FAR(远):该标号可以被非本段的转移和调用指令使用。

标号的距离属性可以有两种方法来指定:

a.隐含方式

当标号加在指令语句前面时,它隐含为NEAR属性。

b.用LABEL伪指令给标号指定距离属性

格式: 标号名 LABEL 类型
类型为NEAR或FAR。该语句应与指令语句连用
:LABEL伪指令还可以用来定义变量的属性,即改变一个变量的属性,如把字变量的高低字节作为字节变量来理。

4.3 符号定义语句

一、等值语句

语句格式:符号名 EQU 表达式

功能:用符号名来表示EQU右边的表达式。后面的程序中一旦出现该符号名,汇编程序将把它替换成该表达式。表达式可以是任何形式。如:

1.常数或数值表达式

2.地址表达式

3.变量、寄存器名或指令助记符

二、等号语句

格式:符号名=表达式

等号语句与等值语句具有相同的作用。但等号语句可以对一个符号进行多次定义

等值语句与等号语句都不会为符号分配存储单元。因此所定义的符号没有段、偏移量和类型等属性

4.4 表达式与运算符

表达式是指令或伪指令语句操作数的常见形式。它由常数、变量、标号通过操作运算符连接而成。

:任何表达式的值在程序被汇编的过程中进行计算确定,而不是到程序运行时才计算。

操作运算符可以分为以下五类

一、算术运算符

1.运算符“+”和“-”也可作单目运算符,表示数的正负。

2.使用“+”、“-”、“*”、和“/”运算符时,参加运算的数和运算结果都是整数。

3.“/”运算为取商的整数部分,而“MOD”运算取除法运算的余数。

4. “SHR ”和“SHL ”为逻辑移位运算符

移位运算符与移位指令区别。 移位运算符的操作对象是某一具体的数(常数),在汇编时完成移位操作。而移位指令是对一个寄存器或存储单元内容在程序运行时执行移位操作

5.下标运算符“[ ]”具有相加的作用

一般使用格式: 表达式1 [表达式2]
作用:将表达式1与表达式2的值相加后形成一个存储器操作数的地址

二、逻辑运算符

逻辑运算符有NOT、AND、OR和XOR等四个,它们执行的都是按位逻辑运算

三、关系运算符

关系运算符包括:

EQ(等于)、NE(不等于)、LT(小于)、 LE(小于等于)、GT(大于)、GE(大于等于

关系运算符用来比较两个表达式的大小。关系运算符比较的两个表达式必须同为常数或同一逻辑段中的变量。

如果是常量的比较,则按无符号数进行比较;如果是变量的比较,则比较它们的偏移量的大小。

关系运算的结果只能是“真”(全1)或“假”(全0

四、数值返回运算符

1.SEG运算符

作用:取变量或标号所在段的段基值

2.OFFSET运算符

作用:取变量或标号在段内的偏移量

3.TYPE运算符

作用:取变量或标号的类型属性,并用数字形式表示。对变量来说就是取它的字节长度

4.LENGTH运算符

作用:用于取变量的长度。

5.SIZE运算符

作用:作用于变量,SIZE取值等于LENGTH和TYPE两个运算符返回值的乘积

五、属性修改运算符

1.PTR运算符

使用格式: 类型 PTR 地址表达式

作用: 将地址表达式所指定的标号、变量或用其它形式表示的存储器地址的类型属性修改为“类型”所指的值。类型可以是BYTE、WORD、DWORD、NEAR和FAR。这种修改是临时的,只在含有该运算符的语句内有效。

2.HIGH/LOW运算符

使用格式:

HIGH 表达式
LOW 表达式

这两个运算符用来将表达式的值分离出高字节低字节

如果表达式为一个常量,则将其分离成高8位和低8位;

如果表达式是一个地址(段基值或偏移量)时,则分离出它的高字节和低字节。

注:HIGH/LOW运算符不能用来分离一个变量、寄存器或存储器单元的高字节与低字节。

3、THIS运算符

THIS运算符一般与等值运算符EQU连用,用来定义一个变量或标号的类型属性。所定义的变量或标号的段基值偏移量与紧跟其后的变量或标号相同

六、运算符的优先级

汇编程序在计算表达式时,按以下规则进行运算。

先执行优先级别高的运算,再算较低级别运算;

相同优先级别的操作,按照在表达式中的顺序从左到右进行;

可以用圆括号改变运算的顺序。

4.5 程序的段结构

8086/8088在管理内存时,按照逻辑段进行划分,不同的逻辑段可以用来存放不同目的的数据。在程序中使用四个段寄存器CS,DS,ES和SS来访问它们。

在源程序设计时,使用伪指令来定义和使用这些逻辑段

一、段定义伪指令

伪指令SEGMENT和ENDS用于定义一个逻辑段。使用时必须配对,分别表示定义的开始结束

段定义伪指令语句各部分的作用如下:

1、段名

段名是由用户自己任意选定的,符合标识符定义规则的一个名称。

一个段的开始与结尾用的段名必须一致

2、定位类型

定位类型用于决定段的起始边界,即第一个可存放数据的位置(不是段基址)。它可以有4种取值。

(1)PAGE: 表示该段从一个页面的边界开始,由于一个页面为256个字节,并且页面编号从0开始,因此,PAGE定位类型的段起始地址的最后8位二进制数一定为0,即以00H结尾的地址。

(2)PARA:表示该段从一个小节的边界开始,如果用户未选定位类型,则缺省为PARA。

(3)WORD:表示该段从一个偶数字节地址开始,即段起始单元地址的最后一位二进制数一定是0

(4)BYTE:表示该段起始单元地址可以是任一地址值。

注:定位类型为PAGE和PARA时,段起始地址与段基址相同。定位类型为WORD和BYTE时,段起始地址与段基址可能不同

3、组合类型

组合类型说明符用来指定段与段之间的连接关系和定位

它有六种取值选择。

(1)若未指定组合类型,表示本段与其它段无连接关系。在装入内存时,本段有自己的物理段,因此有自己的段基址

(2)PUBLIC:在满足定位类型的前提下,将与该段同名的段邻接在一起,形成一个新的逻辑段,共用一个段基址。段内的所有偏移量调整为相对于新逻辑段的段基址。

(3)COMMON: 产生一个覆盖段。在多个模块连接时,把该段与其它也用COMMON说明的同名段置成相同的段基址,这样可达到共享同一存储区。共享存储区的长度由同名段中最大的段确定。

(4)STACK:把所有同名段连接成一个连续段,且系统自动对SS段寄存器初始化为该连续段的段基址。并初始化堆栈指针SP。

(5)AT表达式:表示本段可定位在表达式所指示的小节边界上。表达式的值也就是段基值。

(6)MEMORY:表示本段在存储器中应定位在所有其它段之后的最高地址上。如果有多个用MEMORY说明的段,则只处理第一个用MEMORY说明的段。其余的被视为COMMON

4.类别名:类别名为某一个段或几个相同类型段设定的类型名称。

类别名必须用单引号引起来。所用字符串可任意选定,但它不能使用程序中的标号、变量名或其它定义的符号。

在定义一个段时,段名是必须有的项,而定位类型、组合类型和类别名三个参数是可选项。各个参数之间用空格分隔。各参数之间的顺序不能改变

注:在进行程序设计时,如果程序不大,一般只需要定义三个段就可以了。

二、段寻址伪指令

段寻址伪指令ASSUME的作用是告诉汇编程序,在处理源程序时,定义的段与哪个寄存器关联

ASSUME并不设置各个段寄存器的具体内容,段寄存器的值是在程序运行时设定的

格式

ASSUME段寄存器名:段名,段寄存器名:段名,......

三、段寄存器的装入

段寄存器的初值(段基值)装入需要用程序的方法来实现。

1、DS和ES的装入

在程序中,使用数据传送语句来实现对DS和ES的装入。

2、SS的装入:SS的装入有两种方法

(1)在段定义伪指令的组合类型项中,使用STACK参数,并在段寻址伪指令ASSUME语句中把该段与SS段寄存器关联。

(2)如果在段定义伪指令的组合类型中,未使用STACK参数,或者是在程序中要调换到另一个堆栈,这时,可以使用类似于DS和ES的装入方法。

3、CS的装入

CPU在执行指令之前根据CS和IP的内容来从内存中提取指令,即必须在程序执行之前装入CS和IP的值。因此,CS和IP的初始值就不能用可执行语句来装入。

:装入CS和IP一般有两种情况

(1)由系统软件按照结束伪指令指定的地址装入初始的CS和IP

格式: END 起始地址

:END伪指令的作用是标识源程序结束和指定程序运行时的起始地址

(2)在程序运行期间,当执行某些指令时,CPU自动修改CS和IP,使它们指向新的代码段

4.6 过程定义伪指令(PROC/ENDP)

在程序设计过程中,常常将具有一定功能的程序段设计成一个子程序。

相关概念

过程名:

子程序的名称,它被用作过程调用指令CALL的目的操作数。它类同一个标号的作用。具有段、偏移量和距离三个属性。而距离属性使用NEAR和FAR来指定,若没有指定,则隐含为NEAR

:NEAR过程只能被本段指令调用,而FAR过程可以供其它段的指令调用。每一个过程中必须包含有返回指令RET,其作用是控制CPU从子程序中返回到调用该过程的主程序。

4.7 当前位置计数器$与定位伪指令ORG(Origin)

汇编程序在汇编源程序时,每遇到一个逻辑段,就要为其设置一个位置计数器,它用来记录该逻辑段中定义的每一个数据或每一条指令在逻辑段中的相对位置

在源程序中,使用符号$来表示位置计数器的当前值。因此,$被称为当前计数器。它位于不同的位置具有不同的值。

定位伪指令ORG--用来改变位置计数器的值。

格式: ORG 数值表达式

作用:将数值表达式的值赋给当前位置计数器$。ORG语句为其后的数据或指令设置起始偏移量

:表达式的值必须为正值。表达式中也可以包含有当前位置计数器的现行值$。

4.8 标题伪指令TITLE

语句格式: TITLE 标题名

作用:给所在程序指定一个标题。字符个数不能超过60

4.9 从程序返回操作系统的方法

一、使用程序段前缀PSP(Program Segment Prefix)实现返回

DOS系统将一个.EXE文件(可执行文件)装入内存时,在该文件的前面生成一个程序段前缀PSP,其长度为=100H字节。同时让DS和ES都指向PSP的开始,而CS指向该程序的代码段,即第一条可执行指令

为了使程序执行完后,正确返回DOS,需要做以下三个操作:

1. 将用户程序编制成一个过程,类型为FAR;

2. 将PSP的起始逻辑地址压栈,即将INT 20H指令的地址压栈;

3. 在用户程序结尾处,使用一条RET指令。执行该指令将使保存在堆栈中的PSP的起始地址弹出到CS和IP中。

二、使用DOS系统功能调用实现返回

执行DOS功能调用4CH,也可以控制用户程序结束,并返回DOS操作系统

程序结束时,使用两条指令:

MOV AH,4CH

INT 21H

posted on 2022-03-13 10:12  20192422李俊洁  阅读(176)  评论(0编辑  收藏  举报