3.9 控制转移指令
1. 修改IP, CS
无条件转移指令 JMP
用于直接跳转到指定的代码位置,无需判断任何条件。这在改变程序的执行流程时非常有用。
- 段内跳转: 常用于同一段中的跳转。
- 段间跳转: 用于不同段之间的跳转。
- 直接跳转: 直接指定目标地址或标号。
- 间接跳转: 通过寄存器或内存地址间接指定跳转目标。
1. 段内直接转移 (JMP 目标标号
)
- 用途: 在同一个代码段内跳转到某个标号。
- 语法:
JMP 目标标号
- 示例:
JMP START ; 跳转到标号 START
2. 段内直接转移 (使用 NEAR PTR
)段内直接近转移指令
- 用途: 类似于
JMP 目标标号
,显式指定跳转到同一个段内。 - 语法:
JMP NEAR PTR 目标标号
- 示例:
JMP NEAR PTR NEXT_STEP ; 跳转到标号 NEXT_STEP
3. 段内直接短转移 (JMP SHORT
)
- 用途: 用于在同一个段内跳转,但跳转距离较小(-128 到 127 字节内)。
- 语法:
JMP SHORT 目标标号
- 示例:
JMP SHORT LOOP_END ; 短跳转到标号 LOOP_END
4. 段内间接转移 (JMP WORD PTR
)
- 用途: 跳转地址由内存中的一个 16 位地址(段内地址)指定。
- 语法:
JMP WORD PTR [内存地址]
- 示例:
JMP WORD PTR [BX] ; 跳转到 BX 指向的地址
5. 段间直接转移 (JMP FAR PTR
)
- 用途: 在不同代码段之间进行跳转,指定段选择子和偏移量。
- 语法:
JMP FAR PTR 段:偏移
- 示例:
JMP FAR PTR 0x1234:0x5678 ; 跳转到段 0x1234 中偏移 0x5678 的位置
6. 段间间接转移 (JMP DWORD PTR
)
- 用途: 跳转地址由内存中的一个 32 位地址(段:偏移)指定,用于段间跳转。
- 语法:
JMP DWORD PTR [内存地址]
- 示例:
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 则转移
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=0
且ZF=0
时,表示A > B
(A 大于 B),执行跳转。 - 语法:
JA 目标标号 ; 若 A > B 则跳转
- 示例:
CMP AX, BX ; 比较 AX 和 BX
JA GREATER ; 若 AX > BX 则跳转到 GREATER
JAE/JNB)">2. 大于等于/不低于 (<font style="color:#117CEE;">JAE/JNB</font>
)
- 条件: 当
CF=0
或ZF=1
时,表示A ≥ B
(A 大于或等于 B),执行跳转。 - 语法:
JAE 目标标号 ; 若 A ≥ B 则跳转
- 示例:
CMP AX, BX ; 比较 AX 和 BX
JAE NOTLESS ; 若 AX ≥ BX 则跳转到 NOTLESS
JB/JNAE)">3. 低于/不高于且不等于 (<font style="color:#117CEE;">JB/JNAE</font>
)
- 条件: 当
CF=1
且ZF=0
时,表示A < B
(A 小于 B),执行跳转。 - 语法:
JB 目标标号 ; 若 A < B 则跳转
- 示例:
CMP AX, BX ; 比较 AX 和 BX
JB LESS ; 若 AX < BX 则跳转到 LESS
JBE/JNA)">4. 低于等于/不高于 (<font style="color:#117CEE;">JBE/JNA</font>
)
- 条件: 当
CF=1
或ZF=1
时,表示A ≤ B
(A 小于或等于 B),执行跳转。 - 语法:
JBE 目标标号 ; 若 A ≤ B 则跳转
- 示例:
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:
; 程序结束
在上述示例中,根据 AX
和 BX
的比较结果,程序会跳转到不同的标号来执行相应的代码。
有符号数比较大小
- 大于/不小于且不等于:
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 则转移
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
)
- 作用