条件码:
- ① OF(Overflow Flag)溢出标志,溢出时为1,否则置0.标明一个溢出了的计算,如:结构和目标不匹配.
- ② SF(Sign Flag)符号标志,结果为负时置1,否则置0.
- ③ ZF(Zero Flag)零标志,运算结果为0时置1,否则置0.
- ④ CF(Carry Flag)进位标志,进位时置1,否则置0.注意:Carry标志中存放计算后最右的位.
- ⑤ AF(Auxiliary carry Flag)辅助进位标志,记录运算时第3位(半个字节)产生的进位置。有进位时1,否则置0.
- ⑥ PF(Parity Flag)奇偶标志.结果操作数中1的个数为偶数时置1,否则置0.
控制标志位:
- ⑦ DF(Direction Flag)方向标志,在串处理指令中控制信息的方向。
- ⑧ IF(Interrupt Flag)中断标志。
- ⑨ TF(Trap Flag)陷井标志。
11.1 ZF 标志( 0 标志位 )
11.2 PF 标志( 奇偶 标志位 )
11.3 SF 标志 ( 结果正负标志。0 表示 正,1 表示 负 )
https://blog.csdn.net/zhangjiuding/article/details/79133961
写出下面每条指令执行后,ZF、PF、SF等标志位的值。
ZF标志:是否为0
PF标志:结果中是否有偶数个为 1 的 bit位。
SF标志:结果是否为负,仅有符号运算有用。
提示:传送指令不影响标志位。至于为什么是这样,我估计是因为更改标志位会费时间,CPU的资源很宝贵,而且转移指令的标志位并没有什么实际意义
- sub al,al 结果为0,有0个为1的bit位,非负。
- mov al,1 传送指令不影响标志位。
- push ax 传送指令不影响标志位。
- pop bx 传送指令不影响标志位。
- add al,bl 结果为00000010B,结果不为0,有1个为1的bit位,非负。
- add al,10 结果为00001100B,结果不为0,有2个为1的bit位,非负。
- mul al 结果为10010000B,结果不为0,有2个为1的bit位,非负。
11.4 CF 标志 ( 进位 标志位 )
11.5 OF 标志 ( 溢出 标志位 )
11. 6 adc 指令
11.7 sbb 指令
11.8 cmp 指令
11.9 检测比较结果的条件转移指令
11.10 DF 标志 和 串传送指令
11.11 pushf 和 popf
题目:下面的程序执行后,ax的值是多少?
assume cs:codesg
datasg segmentdb 16 dup(0)
datasg ends
codesg segmentstart:mov ax,0push axpopfmov ax,0fff0hadd ax,0010hpushfpop axand al,11000101band ah,00001000bmov ax,4c00hint 21hcodesg endsend start
这题是对第十一章标志寄存器的更好理解。
先上个图:
本题关键在于 OF 标志的判断。另一个关键点是 and 0000 0100 1100 0101 起到了屏蔽未学习位的作用!
一步一步来分析:
mov ax,0 将ax置0
push ax ax 入栈
popf 将栈中的数据弹出到psw(标志寄存器)中
此时 psw 中数据为:0000 0000 0000 0000b
mov ax, 0fff0h
add ax, 0010h
这两句的作用是(ax) = fff0h + 0010h,显然,psw中的数据会发生改变,问题是:如何改变呢?
CF: 假设这里是无符号运算,则1111 1111 1111 0000b(fff0h) + 0000 0000 0001 0000b(0010h) = 1 0000 0000 0000 0000b,已经发生了进位,所以CF = 1
PF: 结果保存在ax中,ax=0000h,’1’的个数是0,是偶数,所以PF标志=1
AF: AF没学,先不管,假设它是个不确定值,AF = ?
ZF: 结果是0,显然ZF = 1
SF: 结果是0,不是负数,所以SF = 1
TF: TF没学,先不管,假设它是个不确定值,AF = ?
IF: IF没学,先不管,假设它是个不确定值,AF = ?
DF: DF为方向标志位,add指令不会影响DF,前面已经将psw置0,所以DF = 0
OF: OF(溢出标志位)对初学者来说是最难的了,OF记录了有符号数运算结果是否溢出。那么,如何判断是否溢出呢?
假设是有符合运算,fff0h(1111 1111 1111 0000b)对应的原码是1000 0000 0001 000b(即十进制-16),这是如何算出来的?很简单:先看符号位1,说明是个负数,然后所有位取反再加1(即0000 0000
0001 0000b)得绝对值,前面确定是负数,所以符号位应该是1,则原码为1000 0000 0001 000b,同样,0010h的源码(正数的补码和原码相同)是0000 0000 0001 0000b(即十进制的16),
显然,结果是0,一个正数一个负数相加,结果肯定不会溢出!!!下面给出一个tip,用来快速判断运算是否溢出:
tip: 正加正得负,负加负得正,肯定溢出
一正一负相加肯定不会溢出
(进行正加正,负加负运算时,可以全部转为十进制来看,如果得到正加正得正,负加负得负,则需看他们结果是否在可表示范围内)
通过说明的tip,立刻可以判断出未溢出,所以OF = 0;
所以:运行完上面两条语句后,psw值为: 0000 00?? 010? 0101b
pushf 将psw的值入栈
pop ax 此时ax即: 0000 00?? 010? 0101b
and al,11000101b
and ah,00001000b
and 的是按位与,运算法则是:有0则0,我们写对齐来看
0000 00?? 010? 0101b
0000 1000 1100 0101b
显然 and 以后 ax = 0000 0000 0100 0101b = 45h
11.12 标志寄存器在 debug 中的表示
实验 11: 编写子程序
示例代码:
assume cs:codesgdatasg segmentdb "Beginner's All-purpose Symbolic Instruction Code.",0
datasg endscodesg segment
begin:mov ax,datasgmov ds,axmov si,0call lettercmov ax,4c00hint 21hletterc: ;子程序部分[开始]push si
s0: mov al,[si]cmp al,0je exitsubcmp al,61h ; 61h为'a'的ASCII码jb nextcmp al,7ah ; 7ah为'z'的ASCII码ja nextand al,11011111B ;或使用sub al,20hmov [si],al
next: inc sijmp short s0
exitsub:pop siret ;子程序部分[结束]
codesg ends
end begin; 提示:
; 1.相当于将字符串中的每个字符在闭区间['a','z']内进行比较;
; 2.欲显示相关字符串,可调用实验10中的"显示子程序"(属第十章内容),在调用时注意相关参数的传递。