在16位汇编语言(如x86汇编)中,比较指令用于比较两个操作数的大小,通常用于条件跳转、循环控制等逻辑操作,比较指令(如CMP)会根据操作数的比较结果设置标志寄存器中的相关标志位
比较指令影响的标志位:
ZF(Zero Flag):如果结果为零,则设置ZF;否则清除ZF。 SF(Sign Flag):如果结果为负(最高位为1),则设置SF;否则清除SF。 OF(Overflow Flag):如果有符号运算中溢出,则设置OF;否则清除OF。 CF(Carry Flag):如果无符号运算中有借位,则设置CF;否则清除CF。 AF(Auxiliary Carry Flag):如果在从第3位到第4位的运算中有借位,则设置AF;否则清除AF。 PF(Parity Flag):如果结果的最低有效字节中1的个数为偶数,则设置PF;否则清除PF。
在本文中我们会使用到的标志位ZF
、SF
、OF
和CF
。
CMP指令的语法
CMP destination, source
destination:可以是寄存器或内存位置。
source:可以是寄存器、内存位置或立即数。
CMP指令与标志位的关系
CMP
指令执行destination - source
的隐含减法操作,影响标志位如下:
1. destination == source(相等) ZF = 1:结果为零,表示相等。 CF = 0:无借位,表示无进位。 SF = 0:结果非负。 OF = 0:无溢出。 2. destination < source ZF = 0:结果不为零,表示不相等。 CF = 1:有借位,表示无符号小于。 SF = 1:结果为负。 OF = 0:无溢出。 3. destination > source ZF = 0:结果不为零,表示不相等。 CF = 0:无借位,表示无符号大于。 SF = 0:结果非负。 OF = 0:无溢出。 4. destination <= source 标志位条件: ZF = 1 || CF = 1 5. destination >= source 标志位条件: CF = 0
跳转指令 (JCC)
在16位x86汇编语言中,跳转指令(Jump Instruction)用于控制程序的执行流程,决定程序在何处继续执行。跳转指令通常依赖于标志寄存器(Flags Register)的标志位。根据标志位的设置情况,程序可以有条件地跳转到指定的代码位置,从而实现条件判断、循环等功能。
无条件跳转指令
JMP:无条件跳转指令总是跳转到目标地址。
jmp label:无条件跳转到标签 label
。
JMP target
target:
; 在这里继续执行
示例
-
初始化数据段寄存器DS,使其指向数据段。
-
无条件跳转到
jmpTest
标签,跳过了打印szBuffer
的代码。 -
在
jmpTest
标签处,设置并调用DOS中断21h的09h功能,显示字符串szJMPBuffer
的内容(即JMPTest
)。 -
程序读取一个字符,然后正常终止并返回DOS。
assume cs:code,ds:data
data segment ;定义数据段
szBuffer db 0dh,0ah,'HelloWorld$' ;定义字符串szBuffer
szJMPBuffer db 0dh,0ah,'JMPTest$' ;定义字符串szJMPBuffer
data ends
code segment
start:
mov ax,data
mov ds,ax
jmp jmpTest ;跳转到标签
mov ah,09h
lea dx,szbuffer
int 21h
jmpTest: ;标签
mov ah,09h
mov dx,offset szJMPBuffer
int 21h
mov ah,07h ;获取输入
int 21h
mov ax,4c00h
int 21h
code ends
end start
jmp jmpTest
:无条件跳转到jmpTest
标签;这个跳转导致下面的代码(打印szBuffer
的代码)被跳过,不会执行。
jmpTest:
:标签,用于跳转目标。
此时程序只会输出szJMPBuffer
的值,并等待用户输入一个字符;
有条件跳转指令
有条件跳转指令根据标志寄存器的状态决定是否跳转。常见的条件跳转指令有:
①JE / JZ(Jump if Equal / Jump if Zero):当ZF = 1时跳转;用于相等比较结果。
示例:
assume cs:code,ds:data
data segment
szBuffer db 0dh,0ah,'HelloWorld$'
szJMPBuffer db 0dh,0ah,'JETest$'
data ends
code segment
start:
mov ax,data
mov ds,ax
mov ax,3
mov bx,3
cmp ax,bx ;比较AX和BX的值(实际上是执行ax - bx并根据结果设置标志位)。
je JETEST ;如果比较结果相等(ZF=1),则跳转到标签JETEST。
mov ah,09h
lea dx,szbuffer
int 21h
JETEST:
mov ah,09h
mov dx,offset szJMPBuffer
int 21h
mov ah,07h
int 21h
mov ax,4c00h
int 21h
code ends
end start
mov ax, 3
:将立即数3加载到AX寄存器中。
mov bx, 3
:将立即数3加载到BX寄存器中。
cmp ax, bx
:比较AX和BX的值(实际上是执行ax - bx
并根据结果设置标志位)。
je JETEST
:如果比较结果相等(ZF=1),则跳转到标签JETEST
。在这种情况下,由于AX和BX都等于3,ZF被设置,程序将跳转到JETEST
标签。
JETEST:
:标签,用于跳转目标。
最后运行的结果为:
②JNE / JNZ(Jump if Not Equal / Jump if Not Zero):当ZF = 0时跳转。用于不相等比较结果。
CMP AX, BX
JNE not_equal
③JG / JNLE(Jump if Greater / Jump if Not Less or Equal):当ZF = 0且SF = OF时跳转。用于有符号比较中大于的情况。
CMP AX, BX
JG greater
④JGE / JNL(Jump if Greater or Equal / Jump if Not Less):当SF = OF时跳转。用于有符号比较中大于或等于的情况。
CMP AX, BX
JGE greater_or_equal
⑤JL / JNGE(Jump if Less / Jump if Not Greater or Equal):当SF ≠ OF时跳转。用于有符号比较中小于的情况。
CMP AX, BX
JL less
⑥JLE / JNG(Jump if Less or Equal / Jump if Not Greater):当ZF = 1或SF ≠ OF时跳转。用于有符号比较中小于或等于的情况。
CMP AX, BX
JLE less_or_equal