1、指令概述

 

  • 指令:通知 CPU执行某种操作的“命令” , CPU全部指令的集合,称为指令系统
  • 指令的书写格式
    • 目标指令(机器指令)格式为:二进制形式的序列(即:一串0,1代码)。注意:硬件只能识别,存储,运行目标指令
    • 符号指令:用规定的操作码和操作数助记符, 按照规定的书写格式书写的指令,格式为:字 符串形式的序列
  • 指令的组成:大多数指令由操作码和操作数两个部分组成
    • 操作码:通知CPU执行什么操作(唯一)
    • 操作数:指令的操作对象(一个或多个)

汇编语言学习笔记(3)——指令系统_寄存器

  • 目标程序的生成
    • CPU只能识别,存储,运行目标指令,而用机器指令编程非常困难。于是早期的专家们发明了符号指令,再经过软件把符号指令→机器指令。 图示如下:

汇编语言学习笔记(3)——指令系统_伪指令_02

 

 

 

  • 指令长度:指令在存储器中占用的字节数称为指令长度。 86x86指令长度(机器指令长度)为1~16字节。
  • 指令地址:单字节指令占用1个内存单元,多字节指令占用连续的内存单元,存放指令第一字节的内存单元地址,称为“指令地址” 。
  • 指令存放:指令存放在内存中时,先存放操作码,再存放操 作数。多字节操作数连续存放。顺序依据小端法原则,即: 低位字节存放在低地址单元,高位字 节存放在相邻的高地址单元

汇编语言学习笔记(3)——指令系统_变址_03

 

  • 符号指令的书写格式

汇编语言学习笔记(3)——指令系统_寄存器_04

    • 操作码:CPU执行的操作
    • 操作数:指令执行时的操作对象(一个或多个)
    • 标号:以字母开头,后跟字母,数字,下划线,长度 ≤31字符,标号又称符号地址,代表该指令的逻辑地 址。可有可无,设置是为了程序的转向
    • 注解:以“ ;”开头,不执行,打印程序清单时照 原样打印,“系统保留字”不能做标号。


 

2、寻址方式

  •  寻址方式:操作数是指令的操作对象,寻址方式就是在指令中,使用特定的助忆符(地址表达式), 告知 CPU 如何计算出操作数的地址,从而可以正确去除操作数进行后继指令操作与地址码有 密切关系。形成操作数地址码的过程就是寻址。
  • 操作数所在的四种不同的物理位置

汇编语言学习笔记(3)——指令系统_伪指令_05

 

  • 操作数的分类
    • 操作数包含在指令中,这种操作数称为立即数
    • 操作数存放在CPU的某个寄存器中,这种操作数称为寄存器操作数
    • 操作数存放在存储器中,这种操作数称为存储器操作数 (内存操作数)
    • 操作数存放在I/O端口中,这种操作数称为 I/O端口操作数
  • 立即寻址:操作数包含在本条指令中,是指令 的一部分,完整地取出该条指令,也就获得了操作数。

汇编语言学习笔记(3)——指令系统_伪指令_06

 

    • 下例源操作数即为立即寻址
MOV EAX,12345678H
MOV BL,10101010B ;AAH → BL
MOV CL, – 4 ;FCH →CL
MOV DL,’A’ ;41H →DL
ADD AL,0C8H
MOV SI,3*5 ;15 →SI

 

    • 立即数书写规定:
      • 立即数以数字开头,以A~F开头的16进制数,必须前缀0。
      • 立即数的数制用后缀表示,B表示二进制数,H表示十六 进制数, D或缺省为十进制数,单引号括起来的字符编 译成相应的ASCII码 。
      • 可以用+ – * / 组成立即数表达式
  • 寄存器寻址:操作数在CPU的某个寄存器中, 符号指令中直接写出寄存器名称。

汇编语言学习笔记(3)——指令系统_寻址_07

    • 下述6条指令,目标操作数即为寄存器寻址
MOV EAX,12345678H
MOV BL,10101010B ;AAH → BL
MOV CL, – 4 ;FCH →CL
MOV DL,’5’ ;35H →DL
ADD AL,0C8H
MOV SI,3*5 ;15 →SI
    • 下述指令,目标操作数和源操作数均为寄存器寻址
MOV AX , DS ;DS内容 → AX
    • 下述单操作数指令,操作数均为寄存器寻址
INC SI ;SI+1 → SI (Increase 增量)
DEC DI ;DI – 1 → DI (Decrease 减量)

 

 

 

  •  存储器操作数寻址方式
    • 在读写内存操作数之前,CPU必须知道相关存 储单元的物理地址。
    • 由于CPU对存储器采用分段管理, 因此指令格式 中只能写出存放操作数的内存单元的“逻辑地 址” 。
    • 程序员的责任仅在于正确的书写逻辑地址表达 式,然后由CPU自动运算以求出物理地址。
    • 存储单元逻辑地址表达式的一般形式

  汇编语言学习笔记(3)——指令系统_寻址_08

 

    • 实模式下,物理地址=段寄存器×24 +偏移地址
    • 直接寻址
      • 地址表达式的格式1:段寄存器:[偏移地址]
        • 如:MOV AL, ES:[2CH]
        • 注:这种格式很少使用,通常情况下,程序员 并不知道某单元的偏移地址。
      • 地址表达式的格式2: 段寄存器:变量名。用变量名代表存储单元的有效地址

汇编语言学习笔记(3)——指令系统_伪指令_09

 

      • 汇编语言允许为某单元起一个“名字” ,这个 名字就称为该单元的“变量名”,经汇编之后, 变量名有段基址和偏移量两种属性。
      • 由于变量名是唯一的,程序中不能有重复的变 量名, “段寄存器:”可以省略。
    • 寄存器间接寻址(寄存器间接寻址又称间接寻址,间址):操作数在内存单元,该单元的段基址在段寄存器中 有效地址在间址寄存器中,CPU首先进行地址计算
      • 间接寻址的地址表达式:段寄存器:[间址寄存器]
        • 某单元的物理地址=段寄存器内容×16+间址寄存器
      • 访问约定的逻辑段,间接寻址的地址表达式 简化为: [间址寄存器]
        • 某单元的物理地址=约定的段寄存器内容×16+ 间址寄存器
      • 间址寄存器和约定访问的逻辑段

汇编语言学习笔记(3)——指令系统_寻址_10

汇编语言学习笔记(3)——指令系统_伪指令_11

 

      • 注意:BX间址,约定访问的是数据段,因此, “DS:”可省;BP间址约定访问的是堆栈段,因此 “DS:”不可省
    • 基址寻址
      • 在基址寻址中,有效地址由两部分组成。 一部分在基址寄存器中,另一部分为常量 。
      • 基址寻址的地址表达式:段寄存器:[基址寄存器+位移量]
        • 物理地址=段寄存器内容×16+基址寄存器+位移量
      • 访问约定的逻辑段,简化的地址表达式: [基址寄存器+位移量]
        • 物理地址=约定的段寄存器内容×16+基址寄存器 +位移量
      • 基址寄存器和约定访问的逻辑段

汇编语言学习笔记(3)——指令系统_操作数_12

汇编语言学习笔记(3)——指令系统_寄存器_13

 

    • 变址寻址
      • 有比例因子的变址寻址其地址表达式为段寄存器:[比例因子*变址寄存器+位移量]
        • 物理地址=段寄存器×16+比例因子×变址寄存器 +位移量
      • 没有比例因子的变址寻址其地址表达式为:段寄存器:[变址寄存器+位移量]
        • 访问约定的逻辑段可简化为 : [变址寄存器+位移量]
        • 物理地址=约定的段寄存器×16+变址寄存器+位移量
      • 物理地址=约定的段寄存器×16+变址寄存器+位移量

 

汇编语言学习笔记(3)——指令系统_操作数_14

汇编语言学习笔记(3)——指令系统_操作数_15

 

    • 基址加变址寻址
      • 存储单元的有效地址由3部分组成
      • 有比例因子的基址加变址的地址表达式为: 段寄存器:[基址寄存器+比例因子*变址寄存器+位移量]
        • 访问约定逻辑段其地址表达式简化为: [基址寄存器+比例因子*变址寄存器+位移量]
      • 无比例因子基址加变址的地址表达式为: 段寄存器:[基址寄存器+变址寄存器+位移量]
        • 访问约定逻辑段:[基址寄存器+变址寄存器+位移量]
      • 基址寄存器和变址寄存器都是16位或都是32位, 否则(16位寻址和32位寻址混合使用)是非法 指令
      • 默认的段寄存器不一致,这样的组合虽然是合 法,但容易出错

汇编语言学习笔记(3)——指令系统_变址_16

 

  • 要点总结:
    • 指令中的操作数有4种:立即数、寄存器 操作数、内存操作数和I/O端口操作数。
    • 访问立即数使用立即寻址方式。
    • 访问寄存器操作数使用寄存器寻址方式。
    • 访问内存操作数有5种寻址方式: 直接寻址、间址、基址、变址、基址加变址。
    • 访问I/O端口操作数使用I/O端口寻址方式。
    • 关于16位寻址和32位寻址
      • 16位寻址:采用16位间址、基址、变址、基址加变址
      • 32位寻址:采用32位间址、基址、变址、基址加变址
    • 在实模式下,一个逻辑段的体积最大为64K, 存储 单元的有效地址为16位,不可能超过 FFFFH,因此,在实模式下运行的程序通常采 用16位寻址
    • 关于段约定和段超越在用间址、基址、变址、基址加变址寻址内存操作数时,其地址表达式都有2种书写格式——有段前缀和无段前缀
      • 如用BP、EBP、ESP参与寻址,CPU自动认为是访问堆栈段, 因此段超越前缀“SS:” 可省
      • 如用BP、EBP、ESP参与寻址非堆栈段,必须明确写出段超越前缀
      • 如用BX、SI、DI、EAX~EDX、ESI、EDI参与寻址, CPU自动认为是访问数据段,因此“ DS:”可省
      • 如用BX、SI、DI、EAX、EDX、ESI、EDI参与寻址非数据段,必须明确写出段超越前缀
    • 使用段约定访问内存操作数是最常用的编程风格

 



3、标志寄存器

汇编语言学习笔记(3)——指令系统_操作数_17

  • 80486标志寄存器为32位,实际使用15位
  • 15位标志分为两类:状态标志和控制标志
    • 状态标志记录了当前指令执行后的状态信息
    • 控制标志用来控制微处理器操作
  • 状态标志
    • C标志—进位/借位标志
      • 字节加/减,最高位(D7)产生进位/借位时: C标志置1,否则置0
      • 字加/减,最高位(D15)产生进位/借位时: C标志置1,否则置0
      • 双字加/减,最高位(D31)产生进位/借位时: C标志置1,否则置0
    • A标志—辅助进位/辅助借位标志
      • 字节、字、双字加/减,D3位产生进位/借位时: A标志置1,否则置0
    • S标志—符号标志
      • 字节运算后,结果的最高位D7位为1, S标志置1,否则置0
      • 字运算后,结果的最高位D15位为1, S标志置1,否则置0
      • 双字运算后,结果的最高位D31位为1, S标志置1,否则置0
    • Z标志—结果标志
      • 运算结果为全0时,Z标志置1,否则置0
    • P标志—奇偶标志(实际上是偶标志)
      • 运算结果中,最低的1个字节中“1”的个数为偶数个(没有“1”也是偶数),P标 志置1,否则置0
    • O标志—溢出标志
      • 运算结果产生溢出,则O标志置1,否则置0


 4、语句类型和格式

  • 语句类型
    • 汇编语言源程序包括的语句类型为:指令性语句指示性语句
    • 指令性语句即为通常所说的符号指令。
      • 符号指令:经汇编后,其机器指令通知CPU进行什么操作。
    • 指示性语句包括伪指令和宏指令。
      • 伪指令:是非机器指令,是在汇编链接期间 进行操作的。为汇编程序,链接程序提供汇编链接信息
    • 符号指令和伪指令区别

汇编语言学习笔记(3)——指令系统_变址_18

    • 指令性语句(符号指令)的格式为:

汇编语言学习笔记(3)——指令系统_伪指令_19

 

    • 指示性语句(伪指令)的格式为:

汇编语言学习笔记(3)——指令系统_寻址_20

      • 说明:标号名、变量名命名规则:以除数字以外的字母或符号 开头,后跟字母、数字…长度≤31个字符
    • 常用的伪指令:
      • 数据定义:DB、DW、DD、DF、DQ、DT
        • DB:字节字义伪指令
        • DW:字定义伪指令
        • DD:双字定义伪指令
        • DF:三字定义伪指令
        • DQ:四字定义伪指令
        • DT:五字定义伪指令
      • 符号定义:EQU、=
        • 用EQU定义的符号常数,其值在后继语句中不能 更改;用“=”定义的符号常数,其值在后继语句中 可以重新定义
    • 常用运算符:$、SEG、OFFSET、PTR、算术运算、逻辑运算、 关系运算
      • $运算符
        • 汇编程序对源程序是逐行汇编的,$运算符可以返回汇编计数器的当前值。
        • 应用:$运算符紧跟在 DB、DW、DD伪指令之后,统 计字符串的长度。
      • SEG运算符
        • 格式: SEG 段名或变量名或标号名
        • 功能: 计算某一逻辑段的段基址
      • OFFSET运算符
        • 格式:OFFSET 变量名或标号名
        • 功能:算出某个变量或标号名所在单元的 相对于段首的偏移地址(有效地址)。
      • PTR运算符
        • 格式: 类型说明符 PTR 地址表达式
        • 功能: 在本条指令中临时修改地址表达式的属性
        • 应用:在下列指令中必须用PTR临时修改或者显示说明 内存操作数的属性
          • 在双操作数指令中(如:MOV,ADD,SUB,CMP……)
            • 源操作数为立即数,目标为直接寻址的内存操作数, 当二者类型属性不一致时,后者必须用PTR临时修改其 属性,使源目两个操作数类型属性一致。
            • 源为单字节/双字节立即数,目标操作数为间址、 变址、基址或基址加变址寻址的内存操作数,无论两者 类型属性是否已经一致,后者都必须用PTR显示说明其 属性,使其与源操作数属性一致。
            • 源操作数,目标操作数中有一方为直接寻址的内存 器操作数,但二者类型属性不一致,必须用PTR临时修 改其中存储器操作数的属性 。
          • 在单操作数指令中(如:INC,DEC……)
            • 操作数为间址、变址、基址或基址加变址寻址的存储器操作数,必须用PTR说明是字节操作,字操作,还是 双字操作(具体要根据使用该条指令操作的意图);
            • 操作数是直接寻址方式的存储器操作数,是否使用 PTR要看:指令对操作数的类型属性要求是否与操作数的 类型属性一致(例: PUSH 指令)或依据该条指令的操作 意图(按照字节方式?字方式?等)。
      • 方括号运算符
        • 用方括号括起来的地址表达式是访问内存操 作数常用的寻址方式,方括号的另一用途是 标注数组元素的下标,下标从0开始。
      • 算术运算符、逻辑运算符、关系运算符
        • 算术运算符: +, -, *, /
        • 逻辑运算符: AND(与), OR(或), XOR(异或),NOT(非), SHL(左移位),SHR(右移位)
        • 关系运算符: EQ(等于), NE(不等于), GT(大于),LT(小 于), GE(大于或等于),LE(小于等于)
          • 注:指令汇编后,如果为真,则结果为FFFFH, 如果为假,则结果为0