汇编学习笔记 第五章

5.1 顺序程序设计

  1. 从键盘获取一个字节

    • 说明:存入AL
    • 代码
      MOV AH, 01H
      INT 21H
  2. 输出一个字节

    • 说明:输出DL的对应ASCII值
    • 代码
      MOV DL, *
      MOV AH, 02H
      INT 21H
  3. 输出字符串

    • 说明:输出偏移地址存入DX
    • 代码

      MOV DX, OFFSET LABLE
      MOV AH, 09H
      INT 21H

5.2 分支程序设计

  1. CMP的详细解释

    • ZF标志位

      • ZF = 1:DST = SRC
      • ZF = 0:DST != SRC
    • CF标志位(无符号数

      • CF = 0 且 ZF = 0:DST > SRC
      • CF = 1:DST < SRC
    • OF标志位(带符号数

      • OF = 0 且 SF = 0:DST > SRC
      • OF = 0 且 SF = 1:DST < SRC
      • OF = 1 且 SF = 0:DST < SRC
      • OF = 0 且 SF = 1:DST > SRC
    • 单标志条件转移指令

      • JC/JNC
      • JZ/JNZ:结果为0/不为0
      • JS/JNS:结果为负/为正
    • 无符号数条件转移指令

      • JA/JNBE:A > B
      • JAE/JNB:A >= B
      • JB/JNAE:A < B
      • JBE/JNA:A <= B
    • 带符号数条件转移指令

      • JG/JNLE:A > B
      • JGE/JNL:A >= B
      • JL/JNGE:A < B
      • JLE/JNG:A <= B
    • CX寄存器条件转移指令

      • JCXZ/JECX:CX/ECX = 0 时转移
    1. OF = 0 的情况比较方便记忆,OF = 1的情况可以相反记忆
    2. JS是值为负时转移,应当特别关注
  2. SET*条件设置指令

  3. 跳转表

    • 方式:标号 + 跳转指令
    • 重要代码
      MOV AH, 0H
      SHL AX, 1
      ADD AX, OFFSET TABLE
      JMP AX

5.3 循环程序结构

  1. 核心思想:Do - While

  2. 循环控制指令

    • LOOP/LOOPW/LOOPD:CX不等于0,继续循环
    • LOOPE/LOOPZ:CX不等于0且ZF等于1,继续循环
    • LOOPNE/LOOPNZ:CX不等于0且ZF等于0,继续循环
  3. 串操作指令

    • 要求

      • 源操作数存放在 DS:[SI] 中,目的操作数存放在 ES:[DI] 中(相对重要
      • DF = 0 为自动增量,反之为自动减量
      • 重复次数保存在CX中
    • 重复前缀指令

      1. 指令:REP
        • 适用指令:MOVS/STOS/LODS/INS/OUTS
        • 作用:使串操作能重复进行
      2. 指令:REPZ/REPE
        • 适用指令:CMPS/SCAS
        • 作用:CX != 0 且 ZF = 1 时重复操作
      3. 指令:REPNZ/REPNE
        • 适用指令:CMPS/SCAS
        • 作用:CX != 0 且 ZF = 0 时重复操作
    • 串传送

      • 指令:MOVS
      • 功能:将DS:[SI]中存放的数据传入 ES:[DI],并将SI、DI分别移动一个 字节/字/双字
      • 注意点:该指令的操作数可以同为内存操作数,偏移寄存器的移动方向由DF决定
    • 串存储

      • 指令:STOS
      • 功能:将AL/AX/EAX内容存入ES:[DI]中,并将DI移动一个 字节/字/双字
      • 注意点:重复操作时,将AL/AX/EAX 存入一个长度为CX的缓冲区中
    • 串装入

      • 指令:LODS
      • 功能:将DS:[SI] 中的内容存入AL/AX/EAX,并将SI移动一个 字节/字/双字
      • 注意点:一般不与REP联用,若联用,其实只装入串末尾,CX变为串长
    • 串比较

      • 指令:CMPS
      • 功能:DS[SI] - ES:[DI],并将SI、DI分别移动一个 字节/字/双字
    • 串搜索

      • 指令:SCAS
      • 功能:AL/AX/EAX - DST,并将DI移动一个 字节/字/双字
      • 注意点:一般都与REPE/REPZ联用,CX存放搜索空间长度
    • 串输入

      • 适用型号:80386以上
      • 指令:INS
      • 功能:将DX端口号所指空间的一个 字节/字/双字 送入ES:[DI],并自增DI
    • 串输出

      • 适用型号:80386以上
      • 指令:OUTS
      • 功能:将ES:[DI]所指内存的一个 字节/字/双字 送入DX端口,并自增DI
    • 常用初始化指令:CLD/STD(设置DF的值)

    • 例题经典部分

      1. 巧妙解决上述问题只有两个偏移地址寄存器

        XCHG BX, DI
        STOSW
        XCHG BX, DI
      2. 输出一个两位数(原值存放在BX中)

        MOV AX, BX
        MOV BL, 10
        DIV BL      ;因为是两位数,所以不需要DX
        
        ;先输出十位数,存放在AL中
        MOV BH, AH  ;保存余数
        MOV DL, AL
        MOV AH, 2
        OR DL, 30H
        INT 21H
        
        ;输出个位数,现存放在BH中
        MOV DL, BH
        OR DL, 30H
        INT 21H

    注:DI/SI 名字的含义值得深思

  4. 值得关注的例题

    1. 把寄存器EBX中的二进制以十六进制的形式显示

      START:
          MOV EBX 11AA22BBH
          MOV CH, 8           ;8位十六进制数,每次处理一位,共8次
      
      ROTATE:
          MOV CL, 4
          ROL EBX, CL         ;循环移动,每次将最高位移动到最低位
          MOV AL, BL
          AND AL, 0FH
          ADD AL, 30H
          CMP AL, 39H
          JBE DISP
          ADD AL, 7
    2. 将字变量X转换为十进制输出(逐个输出)

      DATA SEGMENT
          DIV1 DW 10000,1000,100,10,1
      DATA ENDS
      CODE SEGMENT
          ASSUME:CS:CODE, DS:DATA
      START:
          MOV AX, DATA
          MOV DS, AX
          MOV AX, X
          MOV CX, 5
          MOV SI, OFFSET DIV1
      REP1:
          XOR DX, DX
          DIV WORD PTR [SI]
          PUSH DX             ;保存余数
      
          OR AL, 30H
          MOV DL, AL
          MOV AH, 2
          INT 21H
      
          INC SI
          INC SI
          POP AX              ;将余数存入AX
          LOOP REP1
      
          MOV AX, 4C00H
          INT 21H
      CODE ENDS
          END START
      

      注:关键代码是循环,但机械化的循环5次会有多余的0输出

    3. 将字变量X转换为十进制输出(一起输出)

      REP1:
          XOR DX, DX
          MOV BX, 10
          DIV BX
          OR DL, 30H
          PUSH DX
          LOOP REP1
      
          MOV CX, 5
      
      REP2:
          POP DX
          MOV AH, 2
          INT 21H
          LOOP REP2
    4. 连接三个字符串

          MOV DI, OFFSET BUFF
      LP1:
          MOV BX, LEN
          SUB BX, 2
          CMP DI, BX
          JZ  DEL_END             ;输出字符串
      
          CMP WORD PTR[DI], 0A0DH 
          JNZ CONTINUE            ;不是回车换行就继续查找
      
          PUSH DI
          MOV SI, DI
          INC SI
          INC SI                  ;跳过换行
          MOV CX, LEN
          SUB CX, DI              ;计算移动总长度
      
          CLD
          REP MOVSB               ;将DS/ES定义在同一个DATA段,巧用SI/DI
          MOV AX, LEN
          SUB AX, 2
          POP DI
                                  ;巧妙的承接,递增了DI
      CONTINUE:
          INC DI
          JMP LP1

      注:不足为也删除了空格

    5. 将字节变量BUFFER中的10个压缩的BCD码转换成非压缩的BCD码存入RESULT中

      ...
          LEA SI, BUFFER
          LEA DI, RESULT
          MOV CX, 10
      L1:
          MOV DL, [SI]
          MOV AL, DL
          PUSH CX
      
          MOV CL, 4
          SHR AL, CL      ;右移一个BCD码
      
          POP CX
          MOV [DI], AL    ;存入高位BCD码
          INC DI
          AND DL, 0FH     ;高位清零
          MOV [DI], DL    ;存入低位BCD码
          INC DI
          INC SI
          LOOP L1

你可能感兴趣的:(汇编笔记)