3.9 控制转移指令

2024-09-13 13:15:44 浏览数 (2)

3.9 控制转移指令

1. 修改IP, CS
无条件转移指令 JMP 用于直接跳转到指定的代码位置,无需判断任何条件。这在改变程序的执行流程时非常有用。
  • 段内跳转: 常用于同一段中的跳转。
  • 段间跳转: 用于不同段之间的跳转。
  • 直接跳转: 直接指定目标地址或标号。
  • 间接跳转: 通过寄存器或内存地址间接指定跳转目标。
1. 段内直接转移 (JMP 目标标号)
  • 用途: 在同一个代码段内跳转到某个标号。
  • 语法:
代码语言:javascript复制
JMP 目标标号
  • 示例:
代码语言:javascript复制
JMP START   ; 跳转到标号 START
2. 段内直接转移 (使用 NEAR PTR)段内直接近转移指令
  • 用途: 类似于 JMP 目标标号,显式指定跳转到同一个段内。
  • 语法:
代码语言:javascript复制
JMP NEAR PTR 目标标号
  • 示例:
代码语言:javascript复制
JMP NEAR PTR NEXT_STEP   ; 跳转到标号 NEXT_STEP
3. 段内直接短转移 (JMP SHORT)
  • 用途: 用于在同一个段内跳转,但跳转距离较小(-128 到 127 字节内)。
  • 语法:
代码语言:javascript复制
JMP SHORT 目标标号
  • 示例:
代码语言:javascript复制
JMP SHORT LOOP_END   ; 短跳转到标号 LOOP_END
4. 段内间接转移 (JMP WORD PTR)
  • 用途: 跳转地址由内存中的一个 16 位地址(段内地址)指定。
  • 语法:
代码语言:javascript复制
JMP WORD PTR [内存地址]
  • 示例:
代码语言:javascript复制
JMP WORD PTR [BX]   ; 跳转到 BX 指向的地址
5. 段间直接转移 (JMP FAR PTR)
  • 用途: 在不同代码段之间进行跳转,指定段选择子和偏移量。
  • 语法:
代码语言:javascript复制
JMP FAR PTR 段:偏移
  • 示例:
代码语言:javascript复制
JMP FAR PTR 0x1234:0x5678   ; 跳转到段 0x1234 中偏移 0x5678 的位置
6. 段间间接转移 (JMP DWORD PTR)
  • 用途: 跳转地址由内存中的一个 32 位地址(段:偏移)指定,用于段间跳转。
  • 语法:
代码语言:javascript复制
JMP DWORD PTR [内存地址]
  • 示例:
代码语言:javascript复制
JMP DWORD PTR [SI]   ; 跳转到 SI 指向的 32 位段间地址
2. 条件转移指令 ★★
检测单个标志位
  • 相等/不相等:
    • JZ/JE: ZF=1, 0/相等则转移
    • JNZ/JNE: ZF=0, 非0/不相等则转移
  • 符号:
    • JS: SF=1, 结果为负则转移
    • JNS: SF=0, 结果为正则转移
  • 溢出:
    • JO: OF=1, 结果溢出则转移
    • JNO: OF=0, 结果不溢出则转移
  • 奇偶性:
    • JP/JPE: PF=1, 低8位中“1”的个数为偶数则转移
    • JNP/JPO: PF=0, 低8位中“1”的个数为奇数则转移
  • 进位:
    • JC: CF=1, 有进位则转移
    • JNC: CF=0, 无进位则转移
无符号数比较大小
  • 大于/不低于且不等于:
    • JA/JNBE: CF=0 且 ZF=0, A > B 则转移
  • 大于等于/不低于:
    • JAE/JNB: CF=0 或 ZF=1, A ≥ B 则转移
  • 低于/不高于且不等于:
    • JB/JNAE: CF=1 且 ZF=0, A < B 则转移
  • 低于等于/不高于:
    • JBE/JNA: CF=1 或 ZF=1, A ≤ B 则转移
代码语言:javascript复制
MOV AL, 5       ; AL = 5
MOV BL, 10      ; BL = 10

CMP AL, BL      ; 比较 AL 和 BL

JA GREATER      ; 如果 AL > BL 跳转到 GREATER(这里不会跳转,因为 AL < BL)
JB LESS_THAN    ; 如果 AL < BL 跳转到 LESS_THAN(这里会跳转到 LESS_THAN)
JAE GREATER_EQUAL ; 如果 AL ≥ BL 跳转到 GREATER_EQUAL(这里不会跳转)
JBE LESS_THAN_OR_EQUAL ; 如果 AL ≤ BL 跳转到 LESS_THAN_OR_EQUAL(这里会跳转到 LESS_THAN_OR_EQUAL)

; 定义标号
GREATER:
    ; AL > BL 的处理代码
    JMP END
LESS_THAN:
    ; AL < BL 的处理代码
    JMP END
GREATER_EQUAL:
    ; AL ≥ BL 的处理代码
    JMP END
LESS_THAN_OR_EQUAL:
    ; AL ≤ BL 的处理代码
    JMP END

END:
    ; 程序结束
JA/JNBE**)">1. 大于/不低于且不等于 (**<font style="color:#117CEE;">JA/JNBE</font>**)
  • 条件: 当 CF=0ZF=0 时,表示 A > B(A 大于 B),执行跳转。
  • 语法:
代码语言:javascript复制
JA 目标标号   ; 若 A > B 则跳转
  • 示例:
代码语言:javascript复制
CMP AX, BX     ; 比较 AX 和 BX
JA  GREATER    ; 若 AX > BX 则跳转到 GREATER
JAE/JNB)">2. 大于等于/不低于 (<font style="color:#117CEE;">JAE/JNB</font>)
  • 条件: 当 CF=0ZF=1 时,表示 A ≥ B(A 大于或等于 B),执行跳转。
  • 语法:
代码语言:javascript复制
JAE 目标标号   ; 若 A ≥ B 则跳转
  • 示例:
代码语言:javascript复制
CMP AX, BX     ; 比较 AX 和 BX
JAE  NOTLESS   ; 若 AX ≥ BX 则跳转到 NOTLESS
JB/JNAE)">3. 低于/不高于且不等于 (<font style="color:#117CEE;">JB/JNAE</font>)
  • 条件: 当 CF=1ZF=0 时,表示 A < B(A 小于 B),执行跳转。
  • 语法:
代码语言:javascript复制
JB 目标标号   ; 若 A < B 则跳转
  • 示例:
代码语言:javascript复制
CMP AX, BX     ; 比较 AX 和 BX
JB  LESS       ; 若 AX < BX 则跳转到 LESS
JBE/JNA)">4. 低于等于/不高于 (<font style="color:#117CEE;">JBE/JNA</font>)
  • 条件: 当 CF=1ZF=1 时,表示 A ≤ B(A 小于或等于 B),执行跳转。
  • 语法:
代码语言:javascript复制
JBE 目标标号   ; 若 A ≤ B 则跳转
  • 示例:
代码语言:javascript复制
CMP AX, BX     ; 比较 AX 和 BX
JBE  NOTGREATER ; 若 AX ≤ BX 则跳转到 NOTGREATER
具体使用场景
  • 控制程序流程: 这些指令用于控制程序的流程,如在比较两个无符号数后,根据结果决定程序的下一步操作。
  • 循环: 这些指令可以与循环结合使用,根据循环体内某些条件来决定是否继续循环或跳出循环。
  • 分支选择: 根据比较结果在不同的代码路径之间进行选择,实现条件分支。
示例代码
代码语言:javascript复制
CMP AX, BX      ; 比较 AX 和 BX
JA  GREATER     ; 若 AX > BX 跳转到 GREATER
JBE LESS_EQUAL  ; 否则跳转到 LESS_EQUAL

GREATER:
    ; 执行 AX > BX 时的代码
    JMP END

LESS_EQUAL:
    ; 执行 AX ≤ BX 时的代码
    JMP END

END:
    ; 程序结束

在上述示例中,根据 AXBX 的比较结果,程序会跳转到不同的标号来执行相应的代码。

有符号数比较大小
  • 大于/不小于且不等于:
    • JG/JNLE: SF=OF 且 ZF=0, A > B 则转移
  • 大于等于/不小于:
    • JGE/JNL: SF=OF 或 ZF=1, A ≥ B 则转移
  • 小于/不大于且不等于:
    • JL/JNGE: SF≠OF 且 ZF=0, A < B 则转移
  • 小于等于/不大于:
    • JLE/JNG: SF≠OF 或 ZF=1, A ≤ B 则转移
代码语言:javascript复制
ORG 100h      ; 指令段的起始地址

MOV AL, -5    ; AL = -5
MOV BL, 3     ; BL = 3

CMP AL, BL    ; 比较 AL 和 BL

; 检查是否大于
JG GREATER    ; 如果 AL > BL (SF=OF 且 ZF=0) 跳转到 GREATER

; 检查是否大于等于
JGE GREATER_EQUAL ; 如果 AL ≥ BL (SF=OF 或 ZF=1) 跳转到 GREATER_EQUAL

; 检查是否小于
JL LESS_THAN  ; 如果 AL < BL (SF≠OF 且 ZF=0) 跳转到 LESS_THAN

; 检查是否小于等于
JLE LESS_THAN_OR_EQUAL ; 如果 AL ≤ BL (SF≠OF 或 ZF=1) 跳转到 LESS_THAN_OR_EQUAL

; 如果没有跳转,执行默认操作
DEFAULT_ACTION:
    MOV DX, OFFSET NOT_JUMPED
    MOV AH, 09h
    INT 21h         ; 打印字符串
    JMP END_PROGRAM

; 大于的处理
GREATER:
    MOV DX, OFFSET GREATER_MSG
    MOV AH, 09h
    INT 21h         ; 打印字符串
    JMP END_PROGRAM

; 大于等于的处理
GREATER_EQUAL:
    MOV DX, OFFSET GREATER_EQUAL_MSG
    MOV AH, 09h
    INT 21h         ; 打印字符串
    JMP END_PROGRAM

; 小于的处理
LESS_THAN:
    MOV DX, OFFSET LESS_THAN_MSG
    MOV AH, 09h
    INT 21h         ; 打印字符串
    JMP END_PROGRAM

; 小于等于的处理
LESS_THAN_OR_EQUAL:
    MOV DX, OFFSET LESS_THAN_OR_EQUAL_MSG
    MOV AH, 09h
    INT 21h         ; 打印字符串
    JMP END_PROGRAM

; 程序结束
END_PROGRAM:
    MOV AH, 4Ch
    INT 21h         ; 终止程序

; 字符串数据
GREATER_MSG DB 'AL is greater than BL$', 0
GREATER_EQUAL_MSG DB 'AL is greater than or equal to BL$', 0
LESS_THAN_MSG DB 'AL is less than BL$', 0
LESS_THAN_OR_EQUAL_MSG DB 'AL is less than or equal to BL$', 0
NOT_JUMPED DB 'No jump occurred$', 0
3. 循环控制指令 ★
1. 基本循环指令 (LOOP)