第十一章 标志寄存器
注意!:指令集中,add,sub,mul,div,inc,or,and等逻辑或算术运算影响标志寄存器,其他的mov,push,pop等指令对标志寄存器没有影响。
11.1 ZF标志
判断指令执行之后,结果是否为0,为0,ZF=1,不为0,ZF=0。
11.2 PF标志
判断指令执行之后,结果1的个数是否为偶数,偶数--PF=1,奇数--PF=0
11.3 SF标志
判断指令执行之后,结果是否为负,负数--SF=1,非负--SF=0
注意:无符号数,SF没有意义。
检测点11.1
ZF | PF | SF |
1 | 1 | 0 |
1 | 1 | 0 |
1 | 1 | 0 |
1 | 1 | 0 |
0 | 0 | 0 |
0 | 1 | 0 |
0 | 1 | 0 |
assume cs:code code segment start: sub al,al mov al,1 push ax pop bx add al,bl add al,10 mul al mov ax,4c0h int 21h code ends end start
11.4 CF标志
判断是否有向更高位的进位值,有--CF=1,无--CF=0
11.5 OF标志
判断溢出,操作值都是有符号数
判断是否溢出,溢出--OF=1,没有溢出--OF=0
溢出判断方法:
1.
异号相加,同号相减,不会溢出
异号相减,同号相加,可能溢出
2.对于两个操作值(8位
若都在范围内(-128-127),直接加减,判断是否溢出(不在范围内),实际得到的值为,无符号操作数加减,去掉进位,取补码;
若有不在范围内的,先(按有符号数)取补码,再进行加减,得到的结果判断是否溢出,实际得到的值为,无符号操作数加减,去掉进位,取补码。
例子:
mov al,0F0H add al,088H
;0F0H=1111 0000b 088H=1000 1000b ;(0F0H)补=1001 0000b=-16 (088H)补=1111 1000b=-120 ;判断溢出:(-16)+(-120)=-136<-128-----溢出,OP=1
;进位:0F0H+088H=0001 0111 1000b----进位,CF=1 ;实际值:(0F0H+088H)去掉进位,取补码=0111 1000b=120
mov al,98 add al,99 ;判断溢出:98+99=197>127----溢出,OP=1
;进位:197=1100 0101b----无进位,CF=0
;实际值:(197)补=1011 1011b=-59
mov al,0F0H add al,78H ;(0F0H)补=-16 ;判断溢出:(-16)+120=104<127----未溢出,OP=0 ;判断进位:0F0H+078H=0001 0110 1000b----进位,CF=1
检测点 11.2
操作 | CF | OF | SF | ZF | PF | 原因 |
sub,al,al | 0 | 0 | 0 | 1 | 1 |
无符号al=0 有符号al=0 |
mov al,10H | 0 | 0 | 0 | 1 | 1 |
mov指令不改变标志寄存器值 无符号al=10H=0001 0000b 有符号al=10H=0001 0000b |
add al,90H | 0 | 0 | 1 | 0 | 1 |
无符号al=0AH 有符号al=10H + (90H)补=异号相加 |
mov al,80H | 0 | 0 | 1 | 0 | 1 |
mov指令不改变标志寄存器值 无符号al=80H 有符号al=-128 |
add al,80H | 1 | 1 | 0 | 1 | 1 |
无符号= 100H=0001 0000 0000=0 有符号=-128+(-128)=-256<-128 |
mov al,0FCH | 1 | 1 | 0 | 1 | 1 |
mov指令不改变标志寄存器值 无符号:al=0FCH 有符号:al=-4 |
add al,05H | 1 | 0 | 0 | 0 | 0 |
无符号:al=101H 有符号:-4+5=1<127 |
mov al,7DH | 1 | 0 | 0 | 0 | 0 |
mov指令不改变标志寄存器值 无符号:al=7DH 有符号:125 |
add al,0BH | 0 | 1 | 1 | 0 | 1 |
无符号:al=88H 有符号:al=125+11=136>127 |
11.6 adc指令
格式:adc obj1,obj2
功能:obj1=obj1+obj2+CF
可以实现进位计算
assume cs:code code segment mov ax,2 mov bx,1 sub bx,ax;bx=ffffh,CF=1 adc ax,1;ax=2+1+1=4 mov ax,4c00h int 21h code ends end
adc进行进位计算步骤:
- 低位加低位
- 高位加高位,再加上低位相加的进位
计算 1EF000H+201000H,结果放在ax(高16位),bx(低16位)中
assume cs:code code segment mov ax,1EH mov bx,1000H add bx,0F000H adc ax,20H mov ax,4c00h int 21h code ends end
计算1E F000 1000H + 20 1000 1EF0H,结果放在ax(最高位),bx(次高位),cx(低位)中
assume cs:code code segment mov ax,1EH mov bx,0F000H mov cx,1000H add cx,1EF0H adc bx,1000H adc ax,20H mov ax,4c00h int 21h code ends end
编写一个子程序,对两个128位数据进行相加。
128位=16字节=8字
思路:分别用一个16位寄存器指向这两个数据的低16位,相加之后,结果保存到第一个数中,跳到高位继续相加(加上进位),循环到最高位结束相加。
assume cs:code,ds:data data segment dd 12345678h,11021121h,21415161h,71819202h,11223242h,42627282h,83031323h,13536383h data ends code segment start: mov ax,data mov ds,ax mov si,0 mov di,10h call add128 mov ax,4c00h int 21h add128: push ax push cx push si push di sub ax,ax mov cx,8 main: mov ax,[si] adc ax,[di] mov [si],ax add si,2 add di,2 loop main ok: pop di pop si pop cx pop ax ret code ends end start
11.7 sbb指令
sbb和adc相反,进行的是,obj1=obj1-obj2-CF
11.8 cmp指令
cmp指令相当于减法指令sub,但并不保存结果,它只对标志寄存器产生影响。
assume cs:code code segment mov ax,8 mov bx,3 cmp ax,bx mov ax,4c00h int 21h code ends end
CMP对于CF(sign flag),不能通过CF为0或1,判断运算应该得到的结果的正负,通过前面溢出,我们知道运算应该得到结果和实际结果有可能异号。因此我们应该通过,两个数值进行cmp操作后的CF和OF,来判断两个数值的大小关系,和应该得到结果的正负。
以cmp ah,bh为例
SF | OF | 结论 |
1 | 0 | ah<bh |
1 | 1 |
ah>bh 如果因为溢出,导致实际结果为负,那么逻辑上真正结果应该为正 |
0 | 1 |
ah<bh 如果因为溢出,导致实际结果为正,那么逻辑上真正结果应该为负 |
0 | 0 | ah>bh |