标志寄存器

在哪看?OD 已经把 32 位拆分好列出来了,C就是表示CF,P就表示PF…最下面那个 EFL 就是拆开前的样子,需要自己拆的时候就把这个 16 进制数展开成 32 位二进制就行

记住这几个寄存器的位置和名称:

  1. 进位标志 CF(Carry Flag):如果运算结果的最高位产生了一个进位或借位,那么,其值为 1,否则 0

    • 研究进位时,要先确定数字的宽度,知道了宽度才能确定最高位
    1
    2
    3
    MOV AL, 0xEF     MOV AL, 0xFE     MOV 指令不影响标志寄存器
    ADD AL, 2 ADD AL, 2
    CF=0 CF=1
  2. 奇偶标识为 PF(Parity Flag):用于反映运算结果中 1的个数的奇偶性,“1”的个数为偶数,PF 的值为1,否则 0,只看低八位,不管数据宽度是多少

    1
    2
    3
    MOV AL, 3
    ADD AL, 3 PF=0
    ADD AL, 2 PF=1
  3. 辅助进位标志 AF(Auxiliary Carry Falg):

    在发生下列情况时,辅助进位标志 AF 的值被置为 1,否则 0(加醋的部分发生进位,就会是 1):

    (1)在字操作时,发生低字节向高字节进位或借位时 FFFFFFFF

    (2)在字节操作时,发生低 4 位向高 4 位进位或借位时 FFFF

    1
    2
    MOV EAX, 0x55EEFFFF       MOV AX, 0x5EFE       MOV AL, 4E
    ADD EAX, 2 ADD AX, 2 ADD AL, 2
  4. 零标志 ZF(Zero Flag):零标志 ZF 用来反映运算结果是否为 0,是 0 则被置为 1,否则 0。用于判读啊结果是否为 0

    1
    XOR EAX, EAX
  5. 符号标志 SF(Sign Flag):用来反映运算结果的符号位,与运算结果的最高位相同

    1
    2
    MOV AL, 7F
    ADD AL, 2
  6. 溢出标志 OF(Overflow Flag):用于反映有符号数加减运算所得结果是否溢出。如果运算结果超过当前运算位数所能表示的范围,则置 1,否则 0

    最高位进位(CF)与溢出(OF)的区别:

    • 进位标志表示无符号数运算结果是否超出范围

    • 溢出标志表示有符号数运算结果是否超出范围

    • 溢出主要是给有符号数运算用的,在有符号的运算中,有如下的规律:

      • 正 + 正 = 正 如果结果是负数,则说明有溢出
      • 负 + 负 = 负 如果结果是正数,则说明有溢出
      • 正 + 负 永远都不会有溢出

      做有符号数运算关注 OF,做无符号数运算关注 CF

    • 小练习:

      • 无符号、有符号都不溢出

        1
        2
        MOV AL, 8
        ADD AL, 8
      • 无符号溢出,有符号不溢出

        1
        2
        MOV AL, 0xFF
        ADD AL, 2
      • 无符号不溢出,有符号溢出

        1
        2
        MOV AL, 0x7F
        ADD AL, 2
      • 无符号、有符号都溢出

        1
        2
        MOV AL, 0xFE
        ADD AL, 80

拓展:几个指令

  • ADC 指令:带进位加法(不仅仅计算两个数相加,还把 CF 位也一起加上了)

    格式:ADC R/M, R/M/IMM 两边不能同时为内存,宽度要一样

  • SBB 指令:带借位减法(同加法)

    格式:SBB R/M, R/M/IMM 两边不能同时为内存,宽度要一样

  • XCHG 指令:交换数据

    格式:XCHG R/M, R/M(没有立即数,得是俩容器) 两边不能同时为内存,宽度要一样

  • MOVS 指令:移动数据,内存-内存

    BYTE/WORD/DWORD

    1
    2
    3
    MOVSB: MOVS BYTE PTR ES:[EDI], BYTE PTR DS:[ESI]
    MOVSW: MOVS WORD PTR ES:[EDI], WORD PTR DS:[ESI]
    MOVSD: MOVS DWORD PTR ES:[EDI], DWORD PTR DS:[ESI]

    注意:

    • 将后面 ESI 中存的内存地址编号中的值(按照给定的数据宽度来取),存入到前面的 EDI 中存的内存地址编号中
    • 指令执行后,ESI 和 EDI 都加了 4,方便下一个值的赋值,这里加 4 还是加 2 取决于 movsd 还是 movsw,加还是减取决于 DF 标志位(DF=1的时候是减)
    • 如果遇到 MOVS 指令,很可能是字符串的复制
  • STOS 指令:将 AL/AX/EAX 的值存储到 [EDI] 指定的内存单元

    1
    2
    3
    STOS BYTE PTR ES:[EDI]    简写为 STOSB
    STOS WORD PTR ES:[EDI] 简写为 STOSW
    STOS DWORD PTR ES:[EDI] 简写为 STOSD

    AL/AX/EAX 取决于给的数据宽度是 byte、word 还是 dword,EDI 依据 DF 标志位为 0 or 1 以及数据宽度,加 1/2/4 或者减 1/2/4

  • REP 指令:按计数寄存器(ECX)中指定的次数重复执行字符串执行

    每执行一次,ECX的值会减1,最终减为0结束执

课后作业

  1. 熟练记住 CF/PF/AF/ZF/SF/OF 的位置

  2. 写汇编指令只影响 CF 位的值(不能影响其他标志位!)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    等价条件:
    1-CF (Carry Flag):最高位发生进位
    0-ZF (Zero Flag):结果不能为 0
    0-SF (Sign Flag):结果的最高位不能为 1
    0-OF (Overflow Flag):不能发生有符号溢出
    0-AF (Auxiliary Flag):低半部分不能发生进位
    0-PF (Parity Flag):低 8 位中 1 的个数要是奇数
    汇编指令:
    mov al, 0xF0
    add al, 11
  3. 写汇编指令只影响 PF 位的值

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    等价条件:
    0-CF (Carry Flag):最高位不能发生进位
    0-ZF (Zero Flag):结果不能为 0
    0-SF (Sign Flag):结果的最高位不能为 1
    0-OF (Overflow Flag):不能发生有符号溢出
    0-AF (Auxiliary Flag):低半部分不能发生进位
    1-PF (Parity Flag):低 8 位中 1 的个数要是偶数
    汇编指令:
    mov ax, 0x6AAA
    add ax, 0x02
  4. 写汇编指令只影响 AF 位的值

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    等价条件:
    0-CF (Carry Flag):最高位不能发生进位
    0-ZF (Zero Flag):结果不能为 0
    0-SF (Sign Flag):结果的最高位不能为 1
    0-OF (Overflow Flag):不能发生有符号溢出
    1-AF (Auxiliary Flag):低半部分发生进位
    0-PF (Parity Flag):低 8 位中 1 的个数要是奇数
    汇编指令:
    mov ax, 0x6AFF
    add ax, 0x02
  5. 写汇编指令只影响 SF 位的值

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    等价条件:
    0-CF (Carry Flag):最高位不能发生进位
    0-ZF (Zero Flag):结果不能为 0
    1-SF (Sign Flag):结果的最高位为 1
    0-OF (Overflow Flag):不能发生有符号溢出
    0-AF (Auxiliary Flag):低半部分不能发生进位
    0-PF (Parity Flag):低 8 位中 1 的个数要是奇数
    汇编指令:
    mov ax, 0xAAAA
    add ax, 0x01
  6. 写汇编指令只影响 OF 位的值

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    等价条件:
    0-CF (Carry Flag):最高位不能发生进位
    0-ZF (Zero Flag):结果不能为 0
    0-SF (Sign Flag):结果的最高位不能为 1
    1-OF (Overflow Flag):发生有符号溢出
    0-AF (Auxiliary Flag):低半部分不能发生进位
    0-PF (Parity Flag):低 8 位中 1 的个数要是奇数
    思路:
    有符号运算结果溢出,ADD 指令有两种情况:
    1、正数 + 正数 = 负数 (SF=1,舍弃)
    2、负数 + 负数 = 正数 (CF=1,不能用)
    都不能用,但是还有 SUB,也是分为两种情况:
    1、正数 - 负数 = 负数 (正减负应该更正,结果变负了,溢出)
    2、负数 - 正数 = 正数 (负减正应该更负,结果变正了,溢出)
    但是情况一是不可以选择的,CF 它不管你正负,它看的是两个无符号数之间谁大谁小,在它的眼里,情况一就是一个小数减去了一个大数,CF 必为 1,所以不可以选择。于是我们选择情况二,构造一个负数减去一个正数,并使得结果为正
    汇编指令:
    mov ax, 0x90
    add ax, 0x20
  7. 用 MOVS 指令分别移动 5 个字节、5 个字、5 个双字

  8. 用 STOS 指令分别移动 5 个字节、5 个字、5 个双字

  9. 使用 REP 指令重写 7、8 题