❤️💕💕汇编语言目前仍在发挥着不可替代的作用,在效率上无可替代,在底层,学习linux内核,计算机外围设备和驱动,都离不开汇编。Myblog:http://nsddd.top
[TOC]
cmp是比较指令,cmp的功能相当于减法指令,只是不保存结果。cmp指令执行后,将对标志寄存器产生影响。其他相关指令通过识别这些被影响的标志寄存器位来得知比较结果。
cmp 指令格式:
cmp 操作对象1, 操作对象2
功能:
操作对象1 - 操作对象2
计算操作对象1 - 操作对象2但并不保存结果,仅仅根据计算结果对标志寄存器进行设置。
比如:
cmp ax, ax
指令做(ax)-(ax)的运算,结果为0,但并不再ax中保存,仅影响flag的相关各位。指令执行后:zf = 1,pf = 1, sf = 0,cf = 0,of = 0。
下面的指令:
mov ax, 8
mov bx, 3
cmp ax, bx
执行后:(ax)= 8,zf = 0,(pf)= 1,sf = 0, cf = 0, of = 0。
cmp ax, bx
如果(ax)=(bx)则(ax)-(bx)= 0,所以:zf = 1;
如果(ax)!=(bx)则 (ax)-(bx)!= 0,所以:zf != 1;
如果(ax)<(bx)则(ax)-(bx)将产生借位,所以:cf = 1;
如果(ax)>=(bx)则(ax)-(bx)将不会产生借位,所以:cf = 0;
如果(ax)>(bx)则(ax)-(bx)即不借位,结果又不为零,所以:cf = 0,zf = 0;
如果(ax)<=(bx)则(ax)-(bx)即可能借位,结果可能为0,所以:cf = 1,zf = 1;
通过做减法运算,影响标志寄存器,标志寄存器的相关位记录了比较的结果。
zf = 1,说明(ax)=(bx)
zf = 0,说明(ax)!=(bx)
cf = 1,说明(ax)<(bx)
cf = 0,说明(ax)>=(bx)
cf = 0 并且 zf = 0,说明(ax)>(bx)
cf = 1 或 zf = 1,说明(ax)<=(bx)
cmp ah, bh
如果(ah)=(bh)则(ah)-(bh)= 0,所以 zf = 1;
如果(ah)!=(bh)则(ah)-(bh)!= 0,所以 zf = 0;
根据cmp指令执行后zf的值,就可以知道两个数据是否相等。
当结果发生了溢出cmp指令单纯的关注sf的值是不能得出正确的正负结果的。
1)如果 sf = 1,而 of = 0
of = 0,说明没有溢出,逻辑上真正结果的正负 = 实际结果的正负。
sf = 1,实际结果为负,所以逻辑上真正的结果为负,所以(ah)<(bh)。
2)如果 sf = 1,而 of = 1
of = 1,说明有溢出,逻辑上真正结果的正负 != 实际结果的正负。
因sf = 1,实际结果为负。
如果因为溢出导致实际结果为负,那么逻辑上真正的结果必然为正。
sf = 1,of = 1,说明了(ah)>(bh)。
3)如果 sf = 0,而 of = 1
of = 1,说明有溢出,逻辑上真正结果的正负 != 实际结果的正负。
sf = 0,说明实际结果为正。
如果因为溢出导致实际结果为正,那么逻辑上真正的结果必然为负。
sf = 0,of = 1,说明了(ah)<(bh)
4)如果 sf = 0,of = 0
of = 0,说明没有溢出,逻辑上真正结果的正负 = 实际结果的正负。
sf = 0,实际结果为正,所以逻辑上真正的结果为正,所以(ah)>(bh)。
“转移”指的是它能够修改IP,而“条件”指的是它可以根据某种条件,决定是否修改IP。
这些条件转移指令通常都和cmp相配合使用。
因为cmp指令可以同时进行两种比较,无符号数和有符号数比较,所以根据cmp指令的比较结果进行转移的指令也分为两种:
1)根据无符号数的比较结果进行转移的条件转移指令(检测zf、cf的值)
2)根据有符号数的比较结果进行转移的条件转移指令(检测zf、cf 和 of 的值)
无符号转移指令:
指令 含义 检测的相关标志位
je 等于则转移 zf = 1
jne 不等于则转移 zf = 0
jb 低于则转移 cf = 1
jnb 不低于则转移 cf = 0
ja 高于则转移 zf = 0 且 zf = 0
jna 不高于则转移 zf = 1 或 cf = 1
例:实现(ah)=(bh)则(ah)=(ah)+(ah),否则(ah)=(ah)+(bh)
cmp ah, bh
je s ;zf == 1 转移
add ah, bh
jmp short ok
s: add ah, ah
ok: :
:
je检测的是zf位置,不管je前面是什么指令,只要CPU执行je指令时,zf = 1,那么就会发生转移。
如:
mov ax, 0
add ax, 0
je s
inc ax
s: inc ax
例:统计data段中数值为8的字节的个数,用ax保存统计结果
assume cs:code, ds:data
data segment
db 8, 11, 8, 1, 8, 5, 63, 38
data ends
code segment
start: mov ax, data
mov ds, ax
mov ax, 0
mov cx, 8
mov bx, 0
s: map pyte bty ds:[bx], 8
jne s0
inc ax
s0: inc bx
loop s
mov ax, 4C00H
int 21H
code ends
end start
同:
assume cs:code, ds:data
data segment
db 8, 11, 8, 1, 8, 5, 63, 38
data ends
code segment
start: mov ax, data
mov ds, ax
mov ax, 0
mov cx, 8
mov bx, 0
s: map pyte bty ds:[bx], 8
je s0
jmp short next
s0: inc ax
next: inc bx
loop s
mov ax, 4C00H
int 21H
code ends
end start
例:计算data段中数值大于8的字节的个数,用ax保存统计结果。
assume cs:code, ds:data
data segment
db 8, 11, 8, 1, 8, 5, 63, 38
data ends
code segment
start: mov ax, data
mov ds, ax
mov ax, 0
mov cx, 8
mov bx, 0
s: map pyte bty ds:[bx], 8
jna s0
inc ax
s0: inc bx
loop s
mov ax, 4C00H
int 21H
code ends
end start
例:计算data段中数值小于8的字节的个数,用ax保存统计结果。
assume cs:code, ds:data
data segment
db 8, 11, 8, 1, 8, 5, 63, 38
data ends
code segment
start: mov ax, data
mov ds, ax
mov ax, 0
mov cx, 8
mov bx, 0
s: map pyte bty ds:[bx], 8
jnb s0
inc ax
s0: inc bx
loop s
mov ax, 4C00H
int 21H
code ends
end start
例:统计F000:0处32个字节中,大小在[32,128]的数据的个数。
mov ax, of000
mov ds, ax
mov bx, 0
mov dx, 0
mov cx, 32
s: mov al, ds:[bx]
cmp al, 32
jb s0
cmp al, 128
ja s0
inc dx
s0: inc bx
loop s
例:统计F000:0处32个字节中,大小在(32,128)的数据的个数。
mov ax, of000
mov ds, ax
mov bx, 0
mov dx, 0
mov cx, 32
s: mov al, ds:[bx]
cmp al, 32
jna s0
cmp al, 128
jnb s0
inc dx
s0: inc bx
loop s