汇编语言程序设计——邢建川

第一章 基础知识

  • 1.1 汇编语言的一般概念

    程序设计语言:机器语言、高级语言、汇编语言

    机器语言:把控制计算机的命令各种数据直接用二进制数码表示的一种程序设计语言

    优点:运行速度最快,程序长度最短
    缺点:用二进制数表示的内容既不便于记忆又难于阅读

    高级语言:屏蔽操作细节,更像自然语言

    特点:程序设计简单,但程序效率较机器语言低

    汇编语言:使用字母符号来表示机器语言的命令,用十进制数十六进制数来表示数据的计算机程序设计语言

    与机器语言的关系:一条汇编语言的语句与一条机器语言指令对应,汇编语言程序与机器语言程序效率相同
    不同类型计算机有不同的机器指令系统和汇编语言描述

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

    • 学习和使用汇编语言可以从根本上认识、理解计算机的工作过程
    • 在计算机系统中,某些功能必须用汇编语言程序来实现
    • 汇编语言程序的效率高于高级语言程序
  • 1.3 进位计数制及其相互转化

    • 进位计数制

    使用一定个数的数码的组合来表示数字,这种表示方法称为进位计数制。根据所使用的数码的个数,就产生了不同的进位计数制

    :将各个位置上所表示的基本数值称为位权,简称权

    不同的进位制和不同的位置其位权是不同的。
    位权乘以对应位置上的数码就等于该数位上数值
    的大小

    基数:每个数位上能使用不同数码的个数称为基数

    例如十进制有十个数码0~9,基数为10,二进制基
    数为2
    每个数位能取的最大数码值=基数-1

    在计算机中数据表示一般采用二进制数,
    因为它在计算机中最容易表示存储,且适合于逻辑值的表达与运算
    来说二进制不便于书写和阅读,因此书写时常使用8进制和16进制
    在书写不同进位计数制数时,为了区别,常
    在数的尾部用一个字母来表示。

    B(Binary)--二进制数
    O (Octal)或Q--八进制数
    D (Decimal)--十进制数
    H (Hexadecimal)--十六进制数
    如未使用任何字母,则默认表示是十进制数

    • 各种数制间的相互转换
    1. 十进制整数转换为二进制数
    • 减权定位法

    从二进制数高位起,依次用待转换的十进制数与各位权值进行比较;如够减,则该数位系数Ki=1,同时减去该位权值,余数作为下一次比较的值;如不够减,则Ki=0

    • 除基取余法

    将十进制数除以基数2,其余数为二进制数的最低位,再用其商除2,其余数为次低位,反复做下去,直到商0

    1. 十进制小数转换为二进制数
    • 减权定位法

    转换时应根据程序要求的精度或计算机的字长来确

    • 除基取余法
    1. 二进制整数转换为十进制数
    • 按权相加法
    • 逐次乘基相加法
    1. 二进制小数转换为十进制数
    • 按权相加法
    • 逐次乘基相加法
    1. 二进制与八进制和十六进制间的转换

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

  • 1.4 带符号数的表示

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

    用“+”或“-”表示正负的数叫真值
    用“0”或“1”表示正负的数叫机器数

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

    0的原码有两种表示形式:00000000和10000000(+0和-0)

    1. 补码的表示
    • 补码的定义

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

    • 由真值、原码变换为补码

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

    1. 补码数的表示范围

    当位数为8时:
    最大补码为01111111=[+127]补
    最小补码为10000000=[-128]补
    0的补码只有一个,[0]补=00000000

    1. 补码的加减运算

规则:
[X+Y]补=[X]补+[Y]补
[X-Y]补=[X]补-[Y]补=[X]补+[-Y]补

  • 1.5 字符的表示

    在计算机内部,各种字符(字母、符号、数字码)都是按一定的方式编写成二进制信息。不同的计算机以及不同的场合所采用的编码形式可能不同。目前最广泛采用的是ASCII码

    非打印ASCII码:共33个,用于控制操作, 如BEL(响铃07H), DEL(删除7FH),CR(回车,0DH), LF(换行,0AH)

    可打印ASCII码:共95个,如数字符0~9,大小写字母等

  • 1.6 基本逻辑运算

    1. “与”运算(AND)

    “与”运算也叫逻辑乘,常用 ∧ 或 · 表示
    “与”运算是指:仅当逻辑变量A与B都是1时,运算结果F才为1。其它情况F为0

    1. “或”运算(OR)

    “或”运算也叫逻辑加,用∨或+表示
    “或”运算是指当逻辑变量A与B中,至少有一个为1时,结果F为1,其他情况F为0

    1. “非”运算

    “非”运算是指对逻辑变量取相反的一个逻辑值。
    逻辑“非”运算通常是在逻辑变量上方加一横线表示

    1. “异或”运算(XOR)

    通常用⊕表示
    “异或”运算是指:当A和B相同时(同时为1或同时为0),运算结果F为0,而不同时,F为1

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

  • 2.1 IBM-PC微机基本结构

    • 微机的一般构成

    一般计算机应包括五大部件:运算器控制器存储器输入设备输出设备

    CPU:将运算器和控制器两大部件集成在一个集成电路芯片上,称为中央处理器,简称CPU,也叫微处理器
    系统采用总线结构,具有较大的灵活性和扩展性

    1. 中央处理器CPU

    微型计算机中的中央处理器也叫微处理器。它包括
    运算器和控制器

    功能: 分析从主存储器取来的各条指令的功能,控制计算机各部件完成指定功能的各项操作

    1. 主存储器

    主存储器是用来存放程序和数据的部件。它由若干个存储单元构成

    每个存储单元使用一个唯一的编号来标识,称为存储单元的地址。对每个存储单元内容的存和取是按照地址进行访问的

    习惯上将CPU与主存储器合称为主机

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

    1. 输入输出设备及接口

    输入设备 将外部信息(程序、数据和命令)送入计算机。包括键盘、鼠标等。

    输出设备 将计算机处理后的结果转换为人或其它系统能识别的信息形式向外输出。如显示器、打印机等。

    I/O接口 是主机与I/O设备之间设置的逻辑控制部件。通过它实现主机与I/O设备间的信息传送。

    1. 系统总线

    系统总线 将CPU、存储器和I/O设备连接起来,实现各大部件之间的各种信息传送
    系统总线包括 地址总线数据总线控制总线 三组。它们分别用于传送不同的信息

    • Intel 8086/8088 CPU的功能结构

    汇编语言程序是由一系列的指令(指令序列)构成。指令是构成汇编语言程序的最基本单位,就象高级语言中的语句。

    CPU执行指令序列就是重复执行以下两个步骤:
    从存储器中取指令
    执行指令规定的操作
    这两个步骤的执行又分为串行方式和指令流水线方式

    1. 串行方式
      特点:
    1. 系统总线的空闲时间比较多
    2. 大部分时间处于闲置状态

    采用串行工作方式的计算机其运行速度较慢
    2. 指令流水线方式

    执行单元(EU)与总线接口单元(BIU)
    特点:减少了系统总线的空闲时间

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

    通用寄存器8个+控制寄存器2个+段寄存器4个

    • 通用寄存器

  1. 数据寄存器

    它包括AX、BX、CX和DX四个寄存器。它们中的每一个既可以是16位寄存器,也可以分成两个8位寄存器使用
    数据寄存器既可以用来存放参加运算的操作数,也可以存放运算的结果。

  2. 指针寄存器
    指针寄存器有堆栈指针SP和基址指针BP

    它们一般被用来存放16位地址,在形成20位的物理地址时常被作为偏移量使用

    SP指针——在进行堆栈操作时,被隐含使用,被用来指向堆栈顶部单元

    BP指针——被用来指向堆栈段内某一存储单元。BP除用作地址指针外也可以象数据寄存器一 样,存放参加运算的操作数和运算的结果

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

    SI——源变址寄存器
    DI——目的变址寄存器

    • 段寄存器

    代码段,数据段,堆栈段,附加段
    地址增长方向:从上往下

    CPU在访问存储器时必须指明:

    1. 所访问的存储单元属于哪个段(指明使用的段寄存器)
    2. 该存储单元与段基址的偏移量
    • 指令指针IP

    CPU在从存储器取指令时,以段寄存器CS作为代码段的基址指针,以IP的内容作为偏移量,共同形成一条指令的存放地址。

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

    注意:IP的内容不能被直接访问,既不能用指令去读IP的值 ,也不能用指令给它赋值。但是可以通过某些指令的执行而自动修改IP的内容

    • 标志寄存器

    标志寄存器是用来反映CPU在程序运行时的某些状态,如是否有进位、奇偶性、结果的符号、结果是否为零等等。

    1. 进位标志位CF

    在进行算术运算时,若最高位(对字操作是第15位,字节操作是第7位)产生进位或借位时CF被自动置“1”,否则置“0”
    在移位类指令中,CF也被用来存放从最高位(左移时)或最低位(右移时)移出的数值(0或1)

    1. 奇偶标志位PF

    当指令操作结果的低8位中含有1的个数为偶数时,则PF被置1,否则PF被置0

    注意:PF只反映操作结果的低8位的奇偶性,与指令操作数的长度无关

    1. 辅助进位标志位AF

    AF标志位用于十进制运算的调整

    AF只反映运算结果低八位,与操作数长度无关

    1. 零值标志位ZF

    若运算结果各位全为0,则ZF被置1,否则置0

    1. 符号标志位SF

    将运算结果视为带符号数,当运算结果为负数时SF被置1,为正数时,则置0

    1. 溢出标志位OF

    当运算结果超过机器用补码所能表示数的范围时,则OF置1,否则置0

    注意:溢出与进位是两个完全不同的概念,不能相互混淆。

    1. 单步标志位TF

    单步标志也叫跟踪位,该标志为控制标志位。单步标志位供调试程序使用

    1. 中断允许标志位IF

    该标志位为控制标志位。当IF被设置为1时,CPU可以响应可屏蔽中断,否则不允许响应可屏蔽中断

    1. 方向标志位DF

    DF也是控制标志位。它被用来规定串操作指令的增减方向。

  • 2.3 存储器组织结构

    • 存储器的组成

    1. 存储器是由若干个存储单元构成
    2. 每个存储单元存放相同长度的二进制数
    3. 每个存储单元有一个唯一的地址编号——地址

    为了方便书写,在源程序中常用5位十六进制数或一个符号来表示一个存储单元的地址

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

    一个字存储单元(WORD)的长度为16位二进制数,即两个字节。字单元的地址为两个字节单元中较小地址字节单元的地址

    16位长数据的存放规则是低8位放在较低地址字节单元中,高8位放在较高地址字节单元中

    1. 在定义一个地址时必须指出是字节或字类型属性
    • 存储器的段结构

    1. 8086/8088CPU将1MB的存储空间划分成若干个段,每个段最大长度为64K(65536)个字节单元组成
    2. 每个段的基址(段基址)必须是一个小节的首址

    每个小节的首地址最低位必为0(0000H)

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

    内存中的一个物理存储单元可以映象到一个或多个逻辑段中

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

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

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

    1. 物理地址
      CPU与存储器之间的任何信息交换都使用物理地址
    2. 逻辑地址
      一个逻辑地址包括两个部分:段基值和偏移量

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

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

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

    1. 逻辑地址 的来源
  • 2.4 堆栈及其操作方法

    堆栈是一个特定的存储区,访问该存储区一般需要按照专门的规则进行操作

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

    • 堆栈的构造

    堆栈一般分为:专用堆栈存储器软件堆栈

    专用堆栈存储器:按堆栈的工作方式专门设计的存储器

    软件堆栈:由程序设计人员用软件在内存中划出的一块存储区作为堆栈来使用

    在堆栈中存取数据的规则是:“先进后出FILO” 。即最先送入堆栈的数据要到最后才能取出,而最后送入堆栈的数据,最先取出

    当SP被初始化时,指向栈底+2单元,其值就是堆栈的长度

    数据在堆栈中存放格式:以(两字节)为单位存放,数据的低8位放在较低地址单元,高8位放在较高地址单元

    • 堆栈操作
    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. 立即数寻址
      立即数寻址方式的指令中,所需操作数直接包含在指令代码中,这种操作数称为立即数

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

    1. 寄存器寻址
      寄存器寻址方式是指指令中所需的操作数在CPU的某个寄存器中,其执行速度很快

    一个存储单元逻辑地址表示形式:段基值:偏移量

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

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

    1. 位移量:位移量是指令中直接给出的一个8位或16位数。一般源程序中以操作数名字(变量名或标号)的形式出现
    2. 基址:由基址寄存器BX或基址指针BP提供的内容
    3. 变址:由源变址寄存器SI或目的变址寄存器DI提供的内容
    1. 直接寻址
      在直接寻址方式的指令中,操作数的有效地址EA只有位移量地址分量

    在汇编语言源程序中,直接寻址方式用符号或常数来表示

    1. 用符号表示
    2. 用常数表示

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

    1. 寄存器间接寻址
      操作数有效地址EA直接从基址寄存器(BX或BP)或变址寄存器(SI或DI)中获得
    2. 基址寻址 /变址寻址
      操作数的有效地址EA等于基址分量或变址分量加上指令中给出的位移量

    由于这两种寻址方式中寄存器中的内容是相对于由
    位移量指定的初始单元。因此也叫寄存器相对寻址。它们能够很方便地访问数组和表格数据

    1. 基址变址寻址
      操作数的有效地址是三个地址分量之和:
      EA=基址+变址+位移量
    2. 串操作寻址方式

    8086/8088设置有专门用于串操作的指令,这些指令的操作数虽然也在存储器中,但它们不使用前面介绍的各种寻址方式,而隐含地使用变址寄存器SI和DI专门指示

    1. I/O端口寻址
      在计算机系统,对I/O端口的寻址方式有以下两种方法:

      1. 存储器编址方法

      将I/O端口视为存储器的一个单元,对端口的访问就如同访问存储单元一样。访问存储器的指令和各种寻址方式同样适用对I/O端口的访问

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

      1. 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)
    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. 标志出栈指令
      指令格式:POPF
      作用:将由SP指向的堆栈顶部的一个字单元的内容送入标志寄存器,然后SP的内容加2
    5. 地址传送指令
      这类指令有3条,它们的作用是将存储单元的地址送寄存器
      1. 装入有效地址
        格式:LEA DEST,SRC
        作用:将SRC存储单元地址中的偏移量,即有效地址EA传送到一个16位通用寄存器中
      2. 装入地址指针指令
        格式:
        LDS DEST,SRC
        LES DEST,SRC
        作用:把SRC存储单元开始的4个字节单元的内容(32位地址指针)送入DEST通用寄存器和段寄存器DS(LDS指令)或ES(LES指令),其中低字单元内容为偏移量送通用寄存器,高字单元内容为段基值送DS或ES
    • 算术运算类指令

    这些指令可以对字节数据或字数据进行加、减、乘、除运算

    参加运算的数可以是无符号数,也可以是带符号数。带符号数用补码表示

    1. 加法指令
      指令格式:ADD DEST,SRC
      功能:目的操作数和源操作数相加,其和存放目的操作数中,而源操作数内容保持不变,即DEST<=(DEST)+(SRC)
    2. 带进位加法指令
      指令格式:ADC DEST,SRC
      功能:该指令的功能与ADD基本相同,所不同的是其结果还要加上进位标志CF的值,即:DEST<=(DEST)+(SRC)+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
    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
    2. 测试指令
    指令格式:TEST DEST,SRC
    功能:该指令的功能与AND指令相似,实现源操作数与目的操作数进行按位“逻辑与”运算,对标志位的影响与AND指令相同,但运算的结果不送入目的操作数,即目的操作数内容也将保持不变
    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为操作对象,它可以是字节或字操作数,
    可以是通用寄存器或存储器操作数
  2. COUNT用来决定移位/循环的位数,即确定移位
    的次数
  3. 在执行移位时,根据指令不同,每移位一次,最高
    位(左移)或最低位(右移)都要送到进位标志CF
  4. 前4条移位指令根据移位结束后修改标志位CF、
    PF、ZF、SF和OF,而AF不确定。而后4条循环移
    位指令根据移位结束后的结果仅修改CF和OF

*处理器控制类指令
处理器控制类指令包括以下三种情况:

  1. 标志位操作指令
  2. 与外部事件同步的指令
  3. 空操作指令 NOP
  • 3.3 指令编码

    汇编:将汇编语言程序转换为机器语言程序的过程
    汇编程序:在计算机中实现汇编过程的系统程序

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

    1. 双操作数指令编码格式
    2. 单操作数指令编码格式
    3. 与AX或AL有关的指令编码格式
    4. 其它指令编码格式
    • 双操作数指令编码格式

      1. 一个操作数在寄存器中,另一操作数在寄存器或存储器中
      2. 目的操作数在寄存器或存储器中,源操作数是立即数

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

    1. OPCODE:操作码字段
    2. 方向字段d
    3. 字/字节字段W

    2.寻址特征部分
    它包括MOD、REG和R/M三个字段,REG字段确定一个操作数,而MOD和R/M字段确定另一个操作数

    1. REG字段
    2. 寻址方式字段MOD和寄存器/存储器字段R/M

    3.位移量部分
    根据寻址特征中MOD和R/M字段确定的有效地址计算方法,位移量可以是以下三种情况之一:

    1. 没有位移量
    2. 1字节位移量disp8
    3. 2字节位移量disp16

    4.立即数部分
    该指令功能为将16位立即数送存储单元,目的操作数为直接寻址方式

    • 单操作数指令编码格式

    操作特征部分:
    包括OPCODE、V和W三个字段,其中V字段只有移位/循环指令中才有该字段。

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

    这种编码格式用于隐含指定AX/AL作为一个操作数的双操作数指令.

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

    • 其它指令编码格式

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

第四章 汇编语言程序格式

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

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

    • 指令语句

    每一条指令语句在汇编时都要产生一个可供CPU执行的机器目标代码,它又叫可执行语句
    一条指令语句最多可以包含4个字段:

    1. 标号字段
    2. 指令助记符字段
    3. 操作数字段
    4. 注释字段
    • 伪指令语句

    伪指令语句又叫命令语句

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

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

    1. 符号名字段
    2. 伪指令符字段
    3. 操作数字段
    4. 注释字段
    • 标识符

    指令语句中的标号和伪指令语句中符号名统称为标识符
    标识符构成规则:

    1. 字符的个数为1~31个
    2. 第一个字符必须是字母、问号、@或下划线“_”这4种字符之一
    3. .从第二个字符开始,可以是字母、数字、@ 、 “_”或问号“?”
    4. 不能使用属于系统专用的保留字
  • 4.2 汇编语言数据

    数据由数值和属性两部分构成
    在汇编语言中常用的数据形式有:常数、变 量和标号

    • 常数

    常数在汇编期间其值已完全确定,并且在程序运行过程中,其值不会发生变化
    常数有以下几种形式:

    1. 二进制数:以字母B结尾,如01001001B
    2. 八进制数:以字母O或Q结尾,如631Q 254O
    3. 十进制数:以字母D结尾,或者没有结尾字母。如2007D、2007
    4. 十六进制数:以字母H结尾,如3FEH,如果常数的第一个数字为字母,为了与标识符加以区别,必须在其前面冠以数字“0”。
    5. 实数.一般格式为:
      ±整数部分• 小数部分E ± 指数部分
      2.134 E +10
    6. 字符串常数:用引号(单引号或双引号)括起来的一个或多个字符,这些字符以它的ASCII码值存储在内存

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

    1. 作指令语句的源操作数
    2. 在指令语句的直接寻址方式、变址(基址)寻址方式或基址变址寻址方式中作位移量
    3. 在数据定义伪指令中使用
    • 变量

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

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

    1. 变量的定义与预置

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

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

    1. 段属性:它表示变量存放在哪一个逻辑段中。
    2. 偏移量属性(OFFSET):它表示变量所在位置与段起始点之间的字节数。
    3. 类型属性:它表示变量占用存储单元的字节数。

    给变量赋初值的语句的4种表达形式:

    1. 数值表达式
    2. ?表达式(不带引号的问号“?”表示可以预置任意内容)
    3. 字符串表达式
    4. DUP表达式
    1. 变量的使用
    1. 在指令语句中引用
    2. 在伪指令语句中引用
    • 标号

    标号写在一条指令的前面,它就是该指令在内存的存放地址的符号表示,也就是指令地址的别名
    标号的三个属性:

    1. 段属性(SEG)
    2. 偏移量属性(OFFSET)
    3. 距离属性(也叫类型属性)
  • 4.3 符号定义语句

    • 等值语句

    语句格式:符号名 EQU 表达式
    功能:用符号名来表示EQU右边的表达式。后面的程序中一旦出现该符号名,汇编程序将把它替换成该表达式。
    常见的表达式形式:

    1. 常数或数值表达式
    2. 地址表达式
    3. 变量、寄存器名或指令助记符
    • 等号语句

    格式:符号名=表达式

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

  • 4.4 表达式与运算符

    • 算术运算符

    1. 运算符“+”和“-”也可作单目运算符,表示数的正负
    2. 使用“+”、“-”、“*”、和“/”运算符时,参加运算的数和运算结果都是整数
    3. “/”运算为取商的整数部分,而“MOD”运算取除法运算的余数
    4. “SHR ”和“SHL ”为逻辑移位运算符
    5. 下标运算符“[ ]”具有相加的作用
    • 逻辑运算符

    逻辑运算符有NOTANDORXOR等四个,它们执行的都是按位逻辑运算

    • 关系运算符

    关系运算符包括:EQ(等于)、NE(不等于)、LT(小于)、 LE(小于等于)、GT(大于)、 GE(大于等于)

    • 数值返回运算符

    1. SEG运算符
      作用:取变量或标号所在段的段基值
    2. OFFSET运算符
      作用:取变量或标号在段内的偏移量
    3. TYPE运算符
      作用:取变量或标号的类型属性,并用数字形式表示。(对变量来说就是取它的字节长度)
    4. LENGTH运算符
      作用:该运算符用于取变量的长度
    5. SIZE运算符
      作用:SIZE取值等于LENGTH和TYPE两个运算符返回值的乘积(该运算符只能作用于变量)
    • 属性修改运算符

    这一类运算符用来对变量、标号或存储器操作数的类型属性进行修改或指定

    1. PTR运算符
      使用格式: 类型 PTR 地址表达式
      作用: 将地址表达式所指定的标号、变量或用其它形式表示的存储器地址的类型属性修改为 “类型”所指的值
    2. HIGH/LOW运算符
      使用格式:
      HIGH 表达式
      LOW 表达式
      作用: 将表达式的值分离出高字节和低字节
    3. THIS运算符
      THIS运算符一般与等值运算符EQU连用,用来定义一个变量或标号的类型属性。所定义的变量或标号的段基值和偏移量与紧跟其后的变量或标号相同
    • 运算符的优先级

    在一个表达式中如果存在多个运算符时,在计算时就有先后顺序问题。不同的运算符具有不同的运算优先级别

    1. 先执行优先级别高的运算,再算较低级别运算
    2. 相同优先级别的操作,按照在表达式中的顺序,从左到右进行
    3. 可以用圆括号改变运算的顺序
  • 4.5 程序的段结构

    在程序中使用四个段寄存器CS,DS,ES和SS来访问它们

    • 段定义伪指令

    1. 段名
      段名是由用户自己任意选定的,符合标识符定义规则的一个名称
    2. 定位类型
      定位类型用于决定段的起始边界,即第一个可存放数据的位置(不是段基址)。它可以有4种取值:
    1. PAGE: 表示该段从一个页面的边界开始
    2. PARA:表示该段从一个小节的边界开始
    3. WORD:表示该段从一个偶数字节地址开始,即段起始单元地址的最后一位二进制数一定是0
    4. BYTE:表示该段起始单元地址可以是任一地址值

    3.组合类型
    组合类型说明符用来指定段与段之间的连接关系和定位。它有六种取值选择:

    1. 若未指定组合类型,表示本段与其它段无连接关系。在装入内存时,本段有自己的物理段,因此有自己的段基址
    2. PUBLIC:在满足定位类型的前提下,将与该段同名的段邻接在一起,形成一个新的逻辑段,共用一个段基址。段内的所有偏移量调整为相对于新逻辑段的段基址
    3. COMMON: 产生一个覆盖段。在多个模块连接时,把该段与其它也用COMMON说明的同名段置成相同的段基址,这样可达到共享同一存储区。共享存储区的长度由同名段中最大的段确定
    4. STACK:把所有同名段连接成一个连续段,且系统自动对SS段寄存器初始化为该连续段的段基址。并初始化堆栈指针SP
    5. AT表达式:表示本段可定位在表达式所指示的小节边界上。表达式的值也就是段基值
    6. MEMORY:表示本段在存储器中应定位在所有其它段之后的最高地址上。如果有多个用MEMORY说明的段,则只处理第一个用MEMORY说明的段。其余的被视为COMMON
    1. 类别名
      类别名为某一个段或几个相同类型段设定的类型名称。
    • 段寻址伪指令

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

    • 段寄存器的装入

    1. DS和ES的装入
      在程序中,使用数据传送语句来实现对DS和ES的装入
    2. SS的装入
    1. 在段定义伪指令的组合类型项中,使用STACK参数,并在段寻址伪指令ASSUME语句中把该段与SS段寄存器关联
    2. 如果在段定义伪指令的组合类型中,未使用STACK参数,或者是在程序中要调换到另一个堆栈,这时,可以使用类似于DS和ES的装入方法
    1. CS的装入
      CPU在执行指令之前根据CS和IP的内容来从内存中提取指令,即必须在程序执行之前装入CS和IP的值。因此,CS和IP的初始值就不能用可执行语句来装入
  • 4.6 过程定义伪指令(PROC/ENDP)

    在MASM宏汇编程序中,用过程(PROCEDURE)来构造子程序

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

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

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

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

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

  • 4.8 标题伪指令TITLE

    语句格式:TITLE 标题名
    作用:给所在程序指定一个标题。以便在列表文件的每一页的第一行都显示这个标题

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

    两种使程序运行结束后,能够正确地返回到操作系统的语句:

    1. 使用程序段前缀PSP(Program Segment Prefix)实现返回
    2. 使用DOS系统功能调用实现返回
    • 使用程序段前缀PSP实现返回

      1. 将用户程序编制成一个过程,类型为FAR
      2. 将PSP的起始逻辑地址压栈,即将INT 20H指令的地址压栈
      3. 在用户程序结尾处,使用一条RET指令。执行该指令将使保存在堆栈中的PSP的起始地址弹出到CS和IP中
    • 使用DOS系统功能调用实现返回

      执行DOS功能调用4CH,也可以控制用户程序结束,并返回DOS操作系统
      在程序结束时,使用两条指令:
      1. MOV AH,4CH
      2. INT 21H