JMP
用于直接跳转到指定的代码位置,无需判断任何条件。这在改变程序的执行流程时非常有用。JMP 目标标号
)JMP 目标标号
JMP START ; 跳转到标号 START
NEAR PTR
)段内直接近转移指令JMP 目标标号
,显式指定跳转到同一个段内。JMP NEAR PTR 目标标号
JMP NEAR PTR NEXT_STEP ; 跳转到标号 NEXT_STEP
JMP SHORT
)JMP SHORT 目标标号
JMP SHORT LOOP_END ; 短跳转到标号 LOOP_END
JMP WORD PTR
)JMP WORD PTR [内存地址]
JMP WORD PTR [BX] ; 跳转到 BX 指向的地址
JMP FAR PTR
)JMP FAR PTR 段:偏移
JMP FAR PTR 0x1234:0x5678 ; 跳转到段 0x1234 中偏移 0x5678 的位置
JMP DWORD PTR
)JMP DWORD PTR [内存地址]
JMP DWORD PTR [SI] ; 跳转到 SI 指向的 32 位段间地址
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:
; 程序结束
**<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
<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
<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
<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
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
LOOP
)**LOOP**
指令时,寄存器 **CX**
的值减 1。如果 **CX**
不为 0,**则跳转到指定的标号处继续执行;如果 CX
为 0,则跳出循环,继续执行下一条指令。LOOP 目标标号
MOV CX, 0100H ; 设置循环次数为 256 次
DELAY:
; 这里可以是一些操作,比如 NOP
LOOP DELAY ; 每次循环结束时 CX 减 1,不为 0 则跳转到 DELAY
在这个示例中,程序会在 DELAY
标号处循环 256 次,然后继续执行 LOOP DELAY
之后的代码。
LOOPE/LOOPZ
)LOOPE
(或 LOOPZ
)指令时,寄存器 CX
的值减 1。如果 <font style="color:#DF2A3F;">CX</font>
不为 0 并且零标志位 <font style="color:#DF2A3F;">ZF</font>
为 1,则跳转到指定的标号处继续执行;否则跳出循环,继续执行下一条指令。LOOPE 目标标号 ; 或者 LOOPZ 目标标号
CMP AX, BX ; 比较 AX 和 BX
MOV CX, 5 ; 设置循环次数为 5 次
L1:
; 如果 AX = BX (ZF = 1),则执行以下代码
LOOPE L1 ; 如果 CX 不为 0 且 ZF = 1,跳转到 L1
在这个示例中,LOOPE L1
会在 CX
不为 0 且 ZF
为 1 的情况下跳转到 L1
继续循环。否则,将跳出循环。
LOOPNE/LOOPNZ
)LOOPNE
(或 LOOPNZ
)指令时,寄存器 CX
的值减 1。如果 **<font style="color:#DF2A3F;">CX</font>**
不为 0 并且零标志位 **<font style="color:#DF2A3F;">ZF</font>**
为 0,则跳转到指定的标号处继续执行;否则跳出循环,继续执行下一条指令。LOOPNE 目标标号 ; 或者 LOOPNZ 目标标号
CMP AX, BX ; 比较 AX 和 BX
MOV CX, 5 ; 设置循环次数为 5 次
L2:
; 如果 AX ≠ BX (ZF = 0),则执行以下代码
LOOPNE L2 ; 如果 CX 不为 0 且 ZF = 0,跳转到 L2
在这个示例中,LOOPNE L2
会在 CX
不为 0 且 ZF
为 0 的情况下跳转到 L2
继续循环。否则,将跳出循环。
LOOP
指令简单地基于 CX
的值进行循环控制。LOOPE
/LOOPZ
在循环时还考虑 ZF
是否为 1(表示相等或为零的情况)。LOOPNE
/LOOPNZ
在循环时考虑 ZF
是否为 0(表示不相等或不为零的情况)。在汇编语言中,CALL
指令用于调用一个子程序(也叫过程或函数)。调用子程序时,程序的执行会跳转到子程序的起始位置,并在子程序执行完成后返回到调用CALL
指令的下一条指令继续执行。
CALL
指令的工作原理:CALL
指令被执行时,当前指令的下一条指令地址(即返回地址)会被压入堆栈,以便在子程序执行完成后能够返回。CALL
指定的标号处(即子程序的起始地址),开始执行子程序的代码。RET
(返回)指令。RET
指令时,返回地址会从堆栈中弹出,程序控制权会返回到主程序的 CALL
指令之后的指令继续执行。CALL 标号
MAIN:
; 一些主程序代码
CALL SUBROUTINE ; 调用子程序 SUBROUTINE
; 子程序执行完毕后,程序会回到这里继续执行
...
SUBROUTINE:
; 子程序的代码
RET ; 返回到调用点
CALL SUBROUTINE
使得程序跳转到 SUBROUTINE
标号处执行子程序的代码。SUBROUTINE
执行完 RET
指令时,程序返回到 CALL SUBROUTINE
之后的代码,继续执行主程序。CALL
指令用于实现子程序的调用,使得代码模块化、便于复用。CALL
指令配合 RET
指令使用,确保程序在执行完子程序后能够正确返回到调用点继续执行。在汇编语言中,RET
指令用于从子程序(或函数、过程)返回到调用该子程序的主程序位置。它和 CALL
指令相配合使用,以保证在执行完子程序后,程序能够回到主程序继续执行。
RET
指令的工作原理:RET
指令被执行时,处理器会从堆栈中弹出先前 CALL
指令压入的返回地址。CALL
指令所在位置的下一条指令,继续执行主程序的代码。RET
MAIN:
; 一些主程序代码
CALL SUBROUTINE ; 调用子程序 SUBROUTINE
; 子程序执行完毕后,程序会回到这里继续执行
...
SUBROUTINE:
; 子程序的代码
RET ; 返回到调用点
CALL SUBROUTINE
指令调用了一个名为 SUBROUTINE
的子程序。RET
指令时,程序从堆栈中弹出返回地址,并跳回到 CALL SUBROUTINE
指令的下一条指令处,继续执行主程序。RET
指令用于结束子程序的执行,并将程序控制权返回给主程序。RET
指令,程序将无法正确返回到主程序,可能会导致程序异常或崩溃。RET
指令确保子程序执行完毕后,程序能够返回到正确的主程序位置继续执行,是实现程序流程控制的重要指令之一。