汇编语言 CMP指令

Posted ʚVVcatɞ

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了汇编语言 CMP指令相关的知识,希望对你有一定的参考价值。

CMP(比较)指令执行从目的操作数中减去源操作数的隐含减法操作,并且不修改任何操作数。
指令格式:

CMP 目的操作数, 源操作数

标志位 当实际的减法发生时,CMP指令按照计算结果修改溢出、符号、零、进位、辅助进位和奇偶标志位。如果比较的是两个无符号数,则零标志位和进位标志位表示的两个操作数之间的关系如下表所示:

CMP结果ZFCF
目的操作数 < 源操作数01
目的操作数 > 源操作数00
目的操作数 = 源操作数10

如果比较的是两个有符号数,则符号标志位、零标志位和溢出标志位表示的两个操作数之间的关系如下表所示:

CMP结果标志位
目的操作数 < 源操作数SF ≠ OF
目的操作数 > 源操作数SF = OF
目的操作数 = 源操作数ZF = 1

CMP指令是创建条件逻辑结构的重要工具。当在条件跳转指令中使用CMP时,汇编语言的执行结果就和IF语句一样。
以下是目的操作数 < 源操作数的举例:

			;	ZF      CF
mov ax, 5
cmp ax, 10	;	0       1

在这里插入图片描述
以下是目的操作数 = 源操作数的举例:

                        ;	ZF      CF
			mov ax, 1000
			mov cx, 1000
			cmp cx, ax  ;   1       0

在这里插入图片描述

以下是目的操作数 > 源操作数的举例:

			   ;ZF      CF
mov ax, 105
cmp ax, 0      ;0       0

在这里插入图片描述
使用CMP指令统计data 段中数值为8的字节个数,用ax保存统计结果。

; 1.编程 统计data 段中数值为8的字节个数,用ax保存统计结果
assume cs:code, ds:data, ss:stack

data segment
		db 8, 11, 8, 1, 8, 5, 63, 38
data ends

stack segment stack
		db 128 dup(0)
stack ends

code segment
		start: mov ax, stack
				mov ss,ax
				mov sp, 128
				
				call init_reg
				
				call get_eight
				
				mov ax, 4C00H
				int 21H
				
;============================================
get_eight:			
				mov si,0
				mov cx, 8
				mov ax, 0
				
getEight:		cmp byte ptr ds:[si], 8
				jne nextNumber
				inc ax
nextNumber:		inc si
				loop getEight
				
				ret
;===============================================
init_reg:		
				mov bx, data
				mov ds, bx
				ret
				
code ends

end start		

在这里插入图片描述
使用 CMP指令 统计data 段中数值大于8的字节个数,用ax保存统计结果

; 2.编程 统计data 段中数值大于8的字节个数,用ax保存统计结果
assume cs:code, ds:data, ss:stack

data segment
		db 8, 11, 8, 12, 8, 5, 63, 38
data ends

stack segment stack
		db 128 dup(0)
stack ends

code segment
		start: mov ax, stack
				mov ss,ax
				mov sp, 128
				
				call init_reg
				
				call get_eight
				
				mov ax, 4C00H
				int 21H
				
;============================================
get_eight:			
				mov si,0
				mov cx, 8
				mov ax, 0
				
getEight:		cmp byte ptr ds:[si], 8
				jna nextNumber    ; ja >   na <=
				inc ax
nextNumber:		inc si
				loop getEight
				
				ret
;===============================================
init_reg:		
				mov bx, data
				mov ds, bx
				ret
				
code ends

end start

在这里插入图片描述

CMP ax, bx修改标志位符号描述
ax = bxZF = 1相等
ax != bxZF = 0不相等
ax < bxCF = 1小于
ax >= bxCF = 0大于等于
ax > bxCF = 0 并且 ZF = 0大于
ax <= bxCF = 1 或者 ZF = 1小于等于

基于有符号的举例:

mov al, 1
mov bl, 2
cmp al, bl  →  推理出来 al < bl
sub al, bl  →  影响标志位        1 - 2 = -1    SF 符号标志位置1
mov al, 22H →    34    34 - (-96) = 140    -128 ~ 127
mov bl, A0H      -96
sub al, bl  →   OF标志位   和 SF标志位     溢出标志位置1    符号标志位置1
mov al, 8AH    -118 - 112   =  - 230  溢出   1A 正数
mov bl, 70H
cmp al, bl           OF = 1  SF  = 0    溢出标志位置1   符号标志位置0

总结:基于有符号比较

设 cmp al, bl
如果 SF = 1  OF = 0
那么 al < bl

如果SF = 1 OF =1
那么 al > bl

如果 SF = 0 OF = 1     
因为 SF = 0
不等式应该为 al - bl > 0    al > bl        
当OF = 1 成立时,那么
al < bl

如果SF = 0 OF = 0    
那么 al - bl > 0 
得到 al > bl

如果因为溢出导致了实际结果为负,那么逻辑上真正的结果必然为正。

如果因为溢出导致了实际结果为正,那么逻辑上真正的结果必然为负。

基于无符号数比较的跳转

助记符说明
JB小于跳转
JNB不小于跳转
JNBE不小于或等于跳转
JA大于跳转
JNA不大于跳转
JNAE不大于或等于跳转

基于相等性的跳转

助记符说明
JE相等跳转
JNE不相等跳转
JCXZCX = 0 跳转
JECXZECX = 0 跳转
JRCXZRCX = 0 跳转(64模式)

基于有符号数比较的跳转

助记符说明
JG大于跳转
JL小于跳转
JNLE不小于或等于跳转
JNGE不大于活等于跳转
JGE大于或等于跳转
JLE小于或等于跳转
JNL不小于跳转
JNG不大于跳转

基于进位和零标志位的跳转

助记符说明
JC进位跳转(进位标志位置1)
JNC无进位跳转(进位标志位清零)
JZ为零跳转(零标志位置1)
JNZ非零跳转(零标志位清零)

以上是关于汇编语言 CMP指令的主要内容,如果未能解决你的问题,请参考以下文章

《汇编语言(第三版)》cmp指令

汇编 - CMP 后的 JZ 指令

Android 逆向x86 汇编 ( cmp 比较指令 | test 比较指令 )

Android 逆向x86 汇编 ( cmp 比较指令 | test 比较指令 )

汇编指令之CMP, TEST指令

汇编:cmp指令和寻址