1. ZF标志位
这一节我们将来学习一下标志寄存器的ZF(Zero Flag)零标志位。
对于ZF标志位,当运算结果为0的时候,那么ZF=1,当运算结果不为0的时候,ZF=0。
例如下面这段汇编指令:
mov ax,10
mov dx,10
sub ax,dx
但sub指令一旦运行,就会修改寄存器里面的值,当ax和dx进行减法运算的结果为0时,那么ZF标志位就会被置为1。有些时候,我们需要判断一些两个数相减是不是等于0,可我们又不希望影响了寄存器里面的值,这个时候,我们可以使用cmp指令代替sub指令。
cmp指令(compare),cmp指令用法如下:
cmp ax,dx
cmp和sub都是进行减法运算,但cmp只影响标志寄存器;而sub不仅会影响标志寄存器,还会影响被减数所在的寄存器或者内存。因此,当需要判断两个数字是不是相等,就可以使用cmp指令。
当然我们也可以使用cmp指令判断被加数是不是大于加数,只需要观察CF标志位就可以了。
2. JB和JNB
JB指令(英文:jump when below)可以简单理解为是一个跳转指令,当CF标志位为1的时候才会跳转。
而JNAE指令(英文:jump when not above or equal)和JB指令所做的事情几乎是一模一样的,也就是说你既可以使用JB指令,也可以使用JNAE指令。
JNB指令(英文:jump when not below)也是用于跳转的,不过JNB指令只在CF标志位为0的时候才跳转,JAE指令(英文:jump when above or equal)和JNB指令是完成一模一样的事情。
单独使用JB和JNB指令并没有太大的意义,通常都是和cmp指令一起使用,它们一组合,就会产生化腐朽为神奇的效果。我们知道CMP运算之后会影响CF的值,然后JB或者JNB指令会根据CF决定跳转代码。
有了这些指令,就可以让我们的程序具有一定的“智能和思考”。比如设计一个程序功能:输入一个年龄,如果这个年龄是18岁以上(包括18)岁,就在屏幕上显示“Adult”,如果这个年龄小于18岁,在屏幕上显示“Minor”
汇编代码如下:
;文件说明:005.asm
;说明:JB指令使用
mov ax,0xB800
mov es,ax ;指定显示段
mov ax,0x07c0
mov ds,ax ;指定数据段
mov si,0 ;初始化数据段 偏移寄存器(源地址)
mov di,0 ;初始化显示段 偏移寄存器(目的地址)
jmp near code
Age:
db 16 ;指定年龄,你也可以自行指定年龄数
Adult:
db 'Adult'
Minor:
db 'Minor'
code:
mov al,byte[ds:Age]
cmp al,18 ;如果比18小,根据CF标志位变化,使用JB指令跳转到指定位置
JB PrintMinor
PrintAdult: ;打印成年
mov cx,Minor-Adult ;确定要打印的字节数
mov si,Adult
jmp PrintLoop
PrintMinor: ;打印未成年
mov cx,code-Minor ;确定要打印的字节数
mov si,Minor
PrintLoop:
mov al,[ds:si]
mov byte [es:di],al
inc di
mov byte [es:di],0x07
inc si
inc di
loop PrintLoop
end:
jmp 0x07C0:end
times 510-($-$$) db 0x00
db 0x55,0xAA
指定年龄为16,执行结果如下:
指定年龄为20,执行结果如下:
JE指令和JZ指令:
JE指令和JZ指令所做的事情都是一样的,用于跳转的,即当ZF标志位为1时就会跳转。JNE指令和JNZ指令则是当ZF标志位为0时才会跳转。无论是JE指令还是JNE指令,通常都是和CMP指令一起使用的,其用法和JB指令,JNB指令是类似的。