汇编之条件跳转指令(JCC)指令和无条件指令

文章目录

    • JCC 指令
      • 详细说明和示例
    • 无条件指令
      • 详细说明和示例
    • 条件跳转指令和无条件跳转指令的共同点和显著的不同点
      • 详细对比
        • 相同点
        • 不同点
      • 示例对比
        • 条件跳转指令
        • 无条件跳转指令
    • 总结


JCC 指令

在汇编语言中,条件跳转指令(JCC 指令)用于根据特定条件跳转到代码的其他部分。这些条件通常由前面的比较或测试指令设置的标志位决定。以下是常见的 JCC 指令。

指令名称 条件 描述 示例
JE / JZ 等于/零 如果零标志 (ZF) 置位,则跳转 JE label
JNE / JNZ 不等于/非零 如果零标志 (ZF) 清零,则跳转 JNE label
JG / JNLE 大于 如果零标志 (ZF) 清零且符号标志与溢出标志相等,则跳转 JG label
JGE / JNL 大于或等于 如果符号标志与溢出标志相等,则跳转 JGE label
JL / JNGE 小于 如果符号标志与溢出标志不相等,则跳转 JL label
JLE / JNG 小于或等于 如果零标志 (ZF) 置位或符号标志与溢出标志不相等,则跳转 JLE label
JA / JNBE 无符号大于 如果零标志 (ZF) 清零且进位标志 (CF) 清零,则跳转 JA label
JAE / JNB 无符号大于或等于 如果进位标志 (CF) 清零,则跳转 JAE label
JB / JNAE 无符号小于 如果进位标志 (CF) 置位,则跳转 JB label
JBE / JNA 无符号小于或等于 如果零标志 (ZF) 置位或进位标志 (CF) 置位,则跳转 JBE label
JC 进位 如果进位标志 (CF) 置位,则跳转 JC label
JNC 无进位 如果进位标志 (CF) 清零,则跳转 JNC label
JO 溢出 如果溢出标志 (OF) 置位,则跳转 JO label
JNO 无溢出 如果溢出标志 (OF) 清零,则跳转 JNO label
JS 如果符号标志 (SF) 置位,则跳转 JS label
JNS 如果符号标志 (SF) 清零,则跳转 JNS label
JP / JPE 奇偶 如果奇偶标志 (PF) 置位,则跳转 JP label
JNP / JPO 无奇偶 如果奇偶标志 (PF) 清零,则跳转 JNP label

详细说明和示例

  • JE label / JZ label: 如果零标志 (ZF) 置位,则跳转到指定标签。常用于检测两个操作数是否相等。

    • 示例:CMP EAX, EBXJE equal_label,如果 EAX 等于 EBX,则跳转到 equal_label
  • JNE label / JNZ label: 如果零标志 (ZF) 清零,则跳转到指定标签。常用于检测两个操作数是否不等。

    • 示例:CMP EAX, EBXJNE not_equal_label,如果 EAX 不等于 EBX,则跳转到 not_equal_label
  • JG label / JNLE label: 如果零标志 (ZF) 清零且符号标志与溢出标志相等,则跳转到指定标签。用于有符号比较。

    • 示例:CMP EAX, EBXJG greater_label,如果 EAX 大于 EBX,则跳转到 greater_label
  • JGE label / JNL label: 如果符号标志与溢出标志相等,则跳转到指定标签。用于有符号比较。

    • 示例:CMP EAX, EBXJGE greater_or_equal_label,如果 EAX 大于或等于 EBX,则跳转到 greater_or_equal_label
  • JL label / JNGE label: 如果符号标志与溢出标志不相等,则跳转到指定标签。用于有符号比较。

    • 示例:CMP EAX, EBXJL less_label,如果 EAX 小于 EBX,则跳转到 less_label
  • JLE label / JNG label: 如果零标志 (ZF) 置位或符号标志与溢出标志不相等,则跳转到指定标签。用于有符号比较。

    • 示例:CMP EAX, EBXJLE less_or_equal_label,如果 EAX 小于或等于 EBX,则跳转到 less_or_equal_label
  • JA label / JNBE label: 如果零标志 (ZF) 清零且进位标志 (CF) 清零,则跳转到指定标签。用于无符号比较。

    • 示例:CMP EAX, EBXJA above_label,如果 EAX 无符号大于 EBX,则跳转到 above_label
  • JAE label / JNB label: 如果进位标志 (CF) 清零,则跳转到指定标签。用于无符号比较。

    • 示例:CMP EAX, EBXJAE above_or_equal_label,如果 EAX 无符号大于或等于 EBX,则跳转到 above_or_equal_label
  • JB label / JNAE label: 如果进位标志 (CF) 置位,则跳转到指定标签。用于无符号比较。

    • 示例:CMP EAX, EBXJB below_label,如果 EAX 无符号小于 EBX,则跳转到 below_label
  • JBE label / JNA label: 如果零标志 (ZF) 置位或进位标志 (CF) 置位,则跳转到指定标签。用于无符号比较。

    • 示例:CMP EAX, EBXJBE below_or_equal_label,如果 EAX 无符号小于或等于 EBX,则跳转到 below_or_equal_label
  • JC label: 如果进位标志 (CF) 置位,则跳转到指定标签。用于检测溢出。

    • 示例:ADD EAX, 1JC carry_label,如果产生了进位,则跳转到 carry_label
  • JNC label: 如果进位标志 (CF) 清零,则跳转到指定标签。用于检测没有溢出。

    • 示例:ADD EAX, 1JNC no_carry_label,如果没有产生进位,则跳转到 no_carry_label
  • JO label: 如果溢出标志 (OF) 置位,则跳转到指定标签。用于检测溢出。

    • 示例:ADD EAX, EAXJO overflow_label,如果产生了溢出,则跳转到 overflow_label
  • JNO label: 如果溢出标志 (OF) 清零,则跳转到指定标签。用于检测没有溢出。

    • 示例:ADD EAX, EAXJNO no_overflow_label,如果没有产生溢出,则跳转到 no_overflow_label
  • JS label: 如果符号标志 (SF) 置位,则跳转到指定标签。用于检测负值。

    • 示例:CMP EAX, 0JS negative_label,如果 EAX 为负,则跳转到 negative_label
  • JNS label: 如果符号标志 (SF) 清零,则跳转到指定标签。用于检测非负值。

    • 示例:CMP EAX, 0JNS non_negative_label,如果 EAX 为非负,则跳转到 non_negative_label
  • JP label / JPE label: 如果奇偶标志 (PF) 置位,则跳转到指定标签。用于检测偶数个 1。

    • 示例:TEST EAX, 1JP even_parity_label,如果有偶数个 1,则跳转到 even_parity_label
  • JNP label / JPO label: 如果奇偶标志 (PF) 清零,则跳转到指定标签。用于检测奇数个 1。

    • 示例:TEST EAX, 1JNP odd_parity_label,如果有奇数个 1,则跳转到 odd_parity_label

这些 JCC 指令结合条件标志使用,可以实现各种条件判断和控制流转移,是汇编语言中控制程序流程的重要工具。

无条件指令

无条件跳转指令在汇编语言中用于直接跳转到代码的另一部分,无需任何条件判断。这些指令在控制流中非常重要,特别是在实现循环、函数调用和中断处理等场景中。以下是无条件跳转指令。

指令名称 描述 示例
JMP 无条件跳转到指定标签或地址 JMP label
CALL 调用子程序,跳转到指定的子程序地址并保存返回地址 CALL subroutine
RET 从子程序返回,跳转到之前保存的返回地址 RET
JMPF 远跳转到指定段:偏移地址 JMPF segment:offset
INT 触发中断,跳转到中断处理程序 INT 0x80
IRET 从中断返回,恢复中断前的状态 IRET

详细说明和示例

  • JMP label: 无条件跳转到指定的标签。

    • 示例:JMP loop_start,直接跳转到 loop_start 标签处的指令执行。
  • CALL subroutine: 调用子程序,将当前指令的下一条地址压入堆栈,然后跳转到指定的子程序地址。

    • 示例:CALL my_function,调用 my_function 子程序。
  • RET: 从子程序返回,将堆栈顶部的地址弹出并跳转到该地址。

    • 示例:在子程序末尾使用 RET,返回到调用 CALL 指令的下一条指令。
  • JMPF segment:offset: 远跳转到指定的段:偏移地址,用于跨段跳转。

    • 示例:JMPF 0x1000:0x2000,跳转到段地址 0x1000 和偏移地址 0x2000 处的指令。
  • INT 0x80: 触发中断,跳转到中断向量表中指定的中断处理程序。

    • 示例:INT 0x80,触发 Linux 系统调用中断。
  • IRET: 从中断返回,恢复中断前的状态。

    • 示例:在中断处理程序末尾使用 IRET,返回到中断发生时的指令执行。

这些无条件跳转指令在汇编语言中提供了直接控制程序流的机制,使得程序能够执行复杂的逻辑跳转和调用。

条件跳转指令和无条件跳转指令的共同点和显著的不同点

条件跳转指令和无条件跳转指令在汇编语言中有一些共同点和显著的不同点。。

特性 条件跳转指令 (JCC) 无条件跳转指令
跳转条件 根据特定条件(标志位)决定是否跳转 无条件,直接跳转
指令类型 JE, JNE, JG, JL JMP, CALL, RET, JMPF, INT, IRET
使用场景 主要用于条件判断和控制流转移 主要用于无条件跳转、子程序调用和返回、中断处理
依赖标志位 依赖条件标志(ZF, CF, OF, SF, PF 等) 不依赖标志位
标志位变化 可能会改变标志位(条件满足时) 通常不改变标志位
典型示例 JE label - 如果相等则跳转 JMP label - 无条件跳转
性能影响 可能导致分支预测失败而影响性能 跳转开销相对固定

详细对比

相同点
  • 基本功能: 两者都用于改变程序执行的流向。
  • 操作方式: 都需要指定目标地址或标签。
  • 应用领域: 都广泛用于实现循环、分支、函数调用和异常处理。
不同点
特性 条件跳转指令 (JCC) 无条件跳转指令
条件控制 仅在特定条件满足时才跳转(依赖标志位的状态) 每次执行时都跳转
复杂性 需要检查标志位状态,逻辑更复杂 逻辑简单,直接跳转
使用频率 经常用于实现条件分支和循环控制 经常用于子程序调用、返回和中断处理
灵活性 提供了多种基于标志位的条件判断跳转 提供了多种形式的无条件跳转和调用返回
代码可读性 条件跳转能提高代码的可读性(显示逻辑条件) 无条件跳转能简化代码结构
执行开销 可能因条件判断和分支预测失败增加执行开销 执行开销较为固定

示例对比

条件跳转指令
CMP EAX, EBX
JE equal_label     ; 如果 EAX == EBX,则跳转到 equal_label
JNE not_equal_label; 如果 EAX != EBX,则跳转到 not_equal_label
无条件跳转指令
JMP next_section   ; 无条件跳转到 next_section
CALL my_function   ; 调用 my_function 子程序
RET                ; 从子程序返回

总结

  • 条件跳转指令:用于实现条件判断和控制流转移,依赖于特定的标志位,只有在条件满足时才跳转。
  • 无条件跳转指令:用于实现无条件的跳转、子程序调用和返回以及中断处理,不依赖于任何条件,每次执行都会跳转。

这两类指令在汇编语言中各有用途,共同为实现复杂的程序控制流提供了必要的工具。

你可能感兴趣的:(汇编,经验分享)