JMP

只修改 EIP,其余什么也不做

1
MOV EIP, 寄存器/立即数     ;简写为:JMP 寄存器/立即数

CALL

修改 EIP,ESP 也会 -4,把下一句要执行的地址压栈

1
2
PUSH 地址B
MOV EIP, 地址A/寄存器 ;简写为:CALL 地址A/寄存器

RETN

修改 EIP,ESP + 4,弹出栈顶返回地址赋给 EIP。类似于 POP EIP

1
2
LEA ESP, [ESP+4]
MOV EIP, [ESP-4] ;简写为:RET

比较指令(CMP、TEST)

  1. CMP 指令

    指令格式:CMP R/M, R/M/IMM(不能同时为内存)

    相当于 SUB 指令,但是并不像 SUB 一样保存结果,只改标志寄存器的值,根据相减的结果来改变零标志位

    常用于比较两个数是否相等,相等时 ZF=1,==一般看 ZF 和 SF 位比较多==

    • 无符号数比较
    CMP结果 ZF CF
    目的操作数 < 源操作数 0 1
    目的操作数 > 源操作数 0 0
    目的操作数 = 源操作数 1 0
    • 有符号数比较
    CMP结果 标志位
    目的操作数 < 源操作数 SF ≠ OF
    目的操作数 > 源操作数 SF = OF
    目的操作数 = 源操作数 ZF = 1
  2. TEST 指令

    指令格式:TEST R/M, R/M/IMM

    在一定程序上与 CMP 指令是类似的,两个数值进行与操作,也是不保存结果,但是影响标志位 ZF

    常见用法:判断某个寄存器是不是等于 0,只有是 0 是自己跟自己 and 才会是 0

    1
    TEST EAX, EAX   ;用来判断eax中值是否为0,如果是0,则ZF置为1

JCC 指令

  1. JE、JZ

    JE:Jump Equal 相等时跳转

    JZ:Jump Zero 结果为 0 时跳转

    根据 ZF 位判断是否跳转,ZF=1 则跳转,否则不跳。也就是结果相等就跳转

  2. JNE、JNZ

    遇上面相反,ZF=0 时跳转,也就是结果不相等的时候就跳

  3. JS

    JS:Jump if Sign

    根据 SF 位判断是否跳转,SF=1 则跳转,否则不跳。也就是结果为负数就跳转

  4. JNS

    与上面相反,SF=0 时跳转,也就是结果为非负数则跳转

  5. JP、JPE

    JP:Jump if Parity

    JPE:Jump if Parity Even

    根据 PF 位判断是否跳转,PF=1 则跳转,也就是如果结果低8位中1的个数为偶数则跳转

  6. JNP、JPO

    JPO:Jump if Parity Odd

    与上面相反,PF=0 则跳转,也就是如果结果低8位中1的个数为奇数则跳转

  7. JO

    JO:Jump if Overflow

    根据 OF 位判断是否跳转,OF=1 则跳转,也就是如果结果溢出了就跳

  8. JNO

    与上面相反,OF=0 则跳,也就是没溢出就跳

  9. JB、JNAE

    JB:Jump if Below

    JNAE:Jump if Not Above or Equal

    前面的数跟后面的数比较小于则跳转(无符号数),即 CF=1 跳转

  10. JNB、JAE

    与上面相反,大于等于则跳转(无符号数),即 CF=0 跳转

  11. JBE、JNA

    JBE:Jump if Below or Equal

    JNA:Jump if Not Above

    小于等于则跳转(无符号数),即 CF=1 或者 ZF=1 跳转

  12. JNBE、JA

    与上面相反,大于则跳转(无符号数),即 CF=0 并且 ZF=0 跳转

  13. JL、JNGE

    JL:Jump if Less

    JNGE:Jump if Not Greater or Equal

    小于则跳转(有符号数),即 SF≠OF 跳转(注意这里的小于是指我们平时所说的有符号的数的大小,不是看计算机中存的二进制数的大小)

  14. JNL、JGE

    与上面相反,大于等于则跳转(有符号数),即 SF=OF 跳转

  15. JLE、JNG

    JLE:Jump if Less or Equal

    JNG:Jump if Not Greater

    小于等于则跳转(有符号数),即 SF≠OF 或者 ZF=1

  16. JNLE、JG

    与上面相反,大于则跳转(有符号数),即 SF=OF 并且 ZF=0

指令 跳转条件 英文解释 标志位判断依据
JE, JZ 结果相等(或结果为0)则跳转 JE: Jump Equal
JZ: Jump Zero
ZF=1
JNE, JNZ 结果不相等(或结果不为0)则跳转 JNE: Jump Not Equal
JNZ: Jump Not Zero
ZF=0
JS 结果为负数则跳转 JS: Jump if Sign SF=1
JNS 结果为非负数则跳转 JNS: Jump if Not Sign SF=0
JP, JPE 结果低8位中1的个数为偶数则跳转 JP: Jump if Parity
JPE: Jump if Parity Even
PF=1
JNP, JPO 结果低8位中1的个数为奇数则跳转 JNP: Jump No Parity
JPO: Jump if Parity Odd
PF=0
JO 结果溢出则跳转 JO: Jump if Overflow OF=1
JNO 结果没溢出则跳转 JNO: Jump if Not Overflow OF=0
JB, JNAE 小于则跳转(无符号数) JB: Jump if Below
JNAE: Jump if Not Above or Equal
CF=1
JNB, JAE 大于等于则跳转(无符号数) JNB: Jump if Not Below
JAE: Jump if Above or Equal
CF=0
JBE, JNA 小于等于则跳转(无符号数) JBE: Jump if Below or Equal
JNA: Jump if Not Above
CF=1 or ZF=1
JNBE, JA 大于则跳转(无符号数) JNBE: Jump if Not Below or Equal
JA: Jump if Above
CF=0 and ZF=0
JL, JNGE 小于则跳转(有符号数) JL: Jump if Less
JNGE: Jump if Not Greater or Equal
SF≠OF
JNL, JGE 大于等于则跳转(有符号数) JNL: Jump if Not Less
JGE: Jump if Greater or Equal
SF=OF
JLE, JNG 小于等于则跳转(有符号数) JLE: Jump if Less or Equal
JNG: Jump if Not Greater
SF≠OF or ZF=1
JNLE, JG 大于则跳转(有符号数) JNLE: Jump if Not Less or Equal
JG: Jump if Greater
SF=OF and ZF=0

课后作业

  1. CALL 执行时堆栈有什么变化?EIP 有变化吗?

    ESP-4,将 call 指令的下一条指令的地址压栈。EIP 变为 call 指令中的那个地址

  2. RET 执行时堆栈有什么变化?EIP 有变化吗?

    栈顶 +4,栈顶弹出赋值给 EIP

  3. 使用汇编指令修改标志寄存器中的某个位的值,实现 JCC 的十六种跳转

    不允许在 OD 中通过双击的形式修改标志寄存器

    要通过汇编指令的执行去影响标志位,能用 CMP 和 TEST 实现的优先考虑

    第一组:ZF 标志位(相等/零)

    • JE, JZ(ZF=1)

      1
      2
      3
      4
      5
      6
        MOV EAX, 0
      TEST EAX, EAX
      JE ...

      - JNE, JNZ(ZF=0)

      MOV EAX, 0x10
      MOV ECX, 0x20
      CMP EAX, ECX
      JNE …

      1
      2
      3
      4
      5

      第二组:SF 标志位(符号/正负)

      - JS(SF=1)

      MOV EAX, 0x80000000
      TEST EAX, EAX
      JS …

      1
      2
      3

      - JNS(SF=0)

      MOV EAX, 0x7FFFFFFF
      TEST EAX, EAX
      JNS …

      1
      2
      3
      4
      5
      6
      7

      第三组:PF 标志位(奇偶性)

      - JP, JPE(PF=1)

      需注意:PF 只看最后八位

      MOV AL, 0x9F
      TEST AL, AL
      JP …

      1
      2
      3

      - JNP, JPO(PF=0)

      MOV AL, 0x7F
      TEST AL, AL
      JNP …

      1
      2
      3
      4
      5

      第四组:OF 标志位(溢出)

      - JO(OF=1)

      MOV EAX, 0x80000000 ;负数
      MOV ECX, 0x00000001 ;正数
      CMP EAX, ECX ;负-正=正 0x7FFFFFFF
      JO …

      1
      2
      3

      - JNO(OF=0)

      MOV EAX, 0x00000001
      MOV ECX, 0x7FFFFFFF
      CMP EAX, ECX ;正+负 永远不会有溢出
      JNO …

      1
      2
      3
      4
      5

      第五组:无符号数比较 (CF, ZF)

      - JB, JNAE(CF=1)

      MOV EAX, 0x00000001 ;小数
      MOV ECX, 0xFFFFFFFF ;大数(无符号看)
      CMP EAX, ECX ;小-大 要借位
      JB …

      1
      2
      3

      - JNB, JAE(CF=0)

      MOV EAX, 0xFFFFFFFF
      MOV ECX, 0x00000001
      CMP EAX, ECX
      JNB …

      1
      2
      3

      - JBE, JNA(CF=1 or ZF=1)

      MOV EAX,0x11111111
      MOV ECX,0x22222222
      CMP EAX, ECX
      JBE …

      1

      MOV EAX, 0x88888888
      MOV ECX, 0x88888888
      CMP EAX, ECX
      JBE …

      1
      2
      3

      - JNBE, JA(CF=0 and ZF=0)

      MOV EAX, 0x20000000
      MOV ECX, 0x10000000
      CMP EAX, ECX
      JA …

      1
      2
      3
      4
      5

      第六组:有符号数比较 (SF, OF, ZF)

      - JL, JNGE(OF≠SF)

      MOV EAX, 0x11111111
      MOV ECX, 0x77777777
      CMP EAX, ECX ;小正数-大正数=负数,SF=1,但是不溢出,OF=0
      JL …

      1
      2
      3

      - JNL, JGE(OF=SF)

      MOV EAX, 0x77777777
      MOV ECX, 0x11111111
      CMP EAX, ECX
      JNL …

      1
      2
      3

      - JLE, JNG(OF≠SF or ZF=1)

      MOV EAX, 0x11111111
      MOV ECX, 0x77777777
      CMP EAX, ECX
      JLE …

      1

      MOV EAX, 0
      TEST EAX, EAX
      JLE …

      1
      2
      3

      - JNLE, JG(OF=SF and ZF=0)

      MOV EAX, 0x00000001
      MOV ECX, 0xFFFFFFFF
      CMP EAX, ECX
      JG …