目录
- 各类运算时状态标志的响应变化
- 标志符在各种`ADD`运算下的响应情况
- 标志符在各种`SUB`运算下的响应情况
- 借助标志符实现多位数之间运算
- `ADC`(add with carry)带进位加法指令
- `SBB`(subtract with borrow)带借位减法指令
各类运算时状态标志的响应变化
标志符 | 具体含义 |
---|---|
CF(Carry Flag) | 进位标志CF主要用来反映运算是否产生进位或借位。如果运算结果的最高位产生了一个进位或借位,那么,其值为1,否则其值为0。 |
OF(Overflow Flag) | 溢出标志OF用于反映有符号数加减运算所得结果是否溢出。如果运算结果超过当前运算位数所能表示的范围,则称为溢出,OF的值为1,否则,OF的值为0 |
SF(Sign Flag) | 符号标志SF用来反映运算结果的符号位,它与运算结果的最高位相同。在微机系统中,有符号数采用补码表示法,所以,SF也就反映运算结果的正负号。运算结果为正数时,SF的值为0,否则其值为1 |
ZF(Zero Flag) | 零标志ZF用来反映运算结果是否为0。如果运算结果为0,则其值为1,否则其值为0。在判断运算结果是否为0时,可使用此标志位 |
在做操作数的运算时,计算机并不知道操作数是无符号数还是有符号数。因此计算机将两种情况都考虑到了,其中CF标志符用于反映无符号数的进位与借位情况,而OF则反映有符号数的溢出情况
无符号数:其值总是非负的,二进制中没有符号位,全用于表示值的大小。例如,8位的无符号数可表示的范围为 0(0000 0000) ~ 255(1111 1111)
有符号数:其值有正负之分,二进制中的最高位为符号位(0表示正,1表示负),其余位则用于表示值的大小。计算机阅读某个数将其视为有符号数时,总是将其看作是补码(非负数补码为其本身,负数补码为其源码取反再加1)的形式,例如,0000 0011 + 1111 1111 加法运算看作有符号数时,即为 (+3)+(-1)=(+2),8位的有符号数表示的范围为 -128(1000 0000(补码)) ~ +127(0111 1111)
标志符在各种ADD
运算下的响应情况
-
无符号数和有符号数都正常
00000011+0000010000000111\begin{array}{r} 0000\ 0011 \\ +0000\ 0100 \\ \hline 0000\ 0111 \end{array}0000 0011+0000 01000000 0111
无符号数:3+4=73+4=73+4=7,这里显然未产生进位,因此CF = 0
有符号数:(+3)+(+4)=(+7)(+3)+(+4)=(+7)(+3)+(+4)=(+7),这里两个正数相加,结果也为正数,未产生溢出OF = 0 -
无符号数有溢出
00000011+11111111100000010\begin{array}{r} 0000\ 0011 \\ +1111\ 1111 \\ \hline {\color{Red} 1} \ 0000\ 0010 \end{array}0000 0011+1111 11111 0000 0010
无符号数:3+255=2(258)3+255=2(258)3+255=2(258),这里结果为2是因为8位数的运算结果也只保留8位,显然产生了进位即为结果最高位红色的1,因此CF = 1
有符号数:(+3)+(−1)=(+2)(+3)+(-1)=(+2)(+3)+(−1)=(+2),这里第二个数表示为(−1)(-1)(−1)是因为上面提到的“计算机总是将有符号数看作补码”,而两个异号(符号位相异)的有符号数相加的结果总是在可表示范围内(同样只看8位结果,不将进位作为结果的一部分,而一个正数加一个负数,其结果若为正,必然不会大于该正数;结果为负,必然不会小于该负数),因此OF = 0异号两数相加,OF总为0
-
有符号数有溢出
00000011+0111111010000001\begin{array}{r} 0000\ 0011 \\ +0111\ 1110 \\ \hline 1000\ 0001 \end{array}0000 0011+0111 11101000 0001
无符号数:3+126=1293+126=1293+126=129,未产生进位,CF = 0
有符号数:(+3)+(+126)=(−127)(+3)+(+126)=(-127)(+3)+(+126)=(−127),两个正数相加后结果却为负数(加数的符号位与结果的符号位相异),显然出现了溢出,溢出OF = 1 -
无符号数和有符号数都溢出
10000001+10000010100000011\begin{array}{r} 1000\ 0001 \\ +1000\ 0010 \\ \hline {\color{Red} 1} \ 0000\ 0011 \end{array}1000 0001+1000 00101 0000 0011
无符号数:129+130=3(259)129+130=3(259)129+130=3(259),同第二个情况产生了进位,CF = 1
有符号数:(−127)+(−126)=(+3)(-127)+(-126)=(+3)(−127)+(−126)=(+3),同第三个情况结果与加数的符号相异,故发生溢出,OF = 1
SF标志位即为结果最高位的值,用来反映有符号数运算结果的正负性,四个情况依次为:0 0 1 0
ZF标志反映结果是否为0,四个情况结果均不为0, 故ZF均为0
标志符在各种SUB
运算下的响应情况
-
无符号数和有符号数都溢出
101110010−1001001111011111\begin{array}{r} {\color{Red} 1} \ 0111\ 0010\\ -1001\ 0011\\ \hline 1101\ 1111 \end{array}1 0111 0010−1001 00111101 1111
无符号数:114−147=223114-147=223114−147=223,由于被减数小于减数,不够减,这时计算机允许被减数向高位借位,因为不存在实际的高位,就体现在CF标志位,当减法运算中需要解位时,将CF标志位置1,故CF = 1,此时说明无符号数运算的溢出
有符号数:(+114)−(−109)=(−33)(+114)-(-109)=(-33)(+114)−(−109)=(−33),被减数是正数,减数是负数,正数减负数结果应该为正数,而运算结果却为负数,说明发生了溢出,OF = 1 -
无符号数有溢出
101100011−0111110111100110\begin{array}{r} {\color{Red} 1} \ 0110\ 0011\\ -0111\ 1101\\ \hline 1110\ 0110 \end{array}1 0110 0011−0111 11011110 0110
无符号数:99−125=23099-125=23099−125=230,同第一个情况,需要借位,故CF = 1
有符号数:(+99)−(+125)=(−26)(+99)-(+125)=(-26)(+99)−(+125)=(−26),两个同号数相减,无论结果是正数或负数,都不会发生溢出(与加法相反,因为两同号数相减可看作为两异号数相加),故OF = 0同号两数相减,OF总为0
-
有符号数有溢出
10100110−0011011001110000\begin{array}{r} 1010\ 0110\\ -0011\ 0110\\ \hline 0111\ 0000 \end{array}1010 0110−0011 01100111 0000
无符号数:166−54=112166-54=112166−54=112,被减数大于减数,无需借位,故CF = 0
有符号数:(−90)−(+54)=(+112)(-90)-(+54)=(+112)(−90)−(+54)=(+112),负数减正数结果应该为负数,而结果却为正数,发生了溢出,OF = 1 -
无符号数和有符号数都正常
00100110−0001001000010100\begin{array}{r} 0010\ 0110\\ -0001\ 0010\\ \hline 0001\ 0100 \end{array}0010 0110−0001 00100001 0100
无符号数:38−18=2038-18=2038−18=20,被减数大于减数,无需借位,故CF = 0
有符号数:(+38)−(+18)=(+20)(+38)-(+18)=(+20)(+38)−(+18)=(+20),同号数相减,故OF = 0
借助标志符实现多位数之间运算
ADC
(add with carry)带进位加法指令
不是attack damage carry
格式:ADC DST, SRC
操作:(DST) ← (DST)+(SRC)+(CF)
其中上式中的CF为运算前CF标志位的值
用16位指令实现32位的双精度数的加法运算。设数A存放在目的操作数寄存器DX和AX,其中DX存放高位字;数B存放在寄存器BX和CX,其中BX存放高位字
;DX=2000H, AX=8000H, A=2000 8000H
;BX=4000H, CX=9000H, B=4000 9000H
ADD AX, CX ;低位字加法
ADC DX, BX ;高位字加法
-
ADD AX, CX
AX:8000H+CX:9000HAX=11000H\begin{array}{r} AX:\ 8000H \\ +\ CX:\ 9000H\\ \hline AX={\color{Red} 1} \ 1000H \end{array}AX: 8000H+ CX: 9000HAX=1 1000H
AX寄存器值为1000H1000H1000H,产生进位CF = 1 -
ADC DX, BX
DX:2000H+BX:4000H+CF:1BDX=6001H\begin{array}{r} DX:\ 2000H\\ +\ BX:\ 4000H\\ +\ CF:\qquad {\color{Red} 1} B\\ \hline DX=6001H \end{array}DX: 2000H+ BX: 4000H+ CF:1BDX=6001H
将CF值额外加上,即相当于加上了低位产生的进位,保证了结果的正确性,DX寄存器值为6001H6001H6001H
即20008000H+40009000H=60011000H2000\ 8000H+4000\ 9000H=6001\ 1000H2000 8000H+4000 9000H=6001 1000H
SBB
(subtract with borrow)带借位减法指令
格式:SBB DST, SRC
操作:(DST) ← (DST)-(SRC)-(CF)
其中上式中的CF为运算前CF标志位的值
用16位指令实现32位的双精度数的减法运算。设数A存放在目的操作数寄存器DX和AX,其中DX存放高位字;数B存放在寄存器BX和CX,其中BX存放高位字
;DX=2001H, AX=8000H, A=2001 8000H
;BX=2000H, CX=9000H, B=2000 9000H
SUB AX, CX ;低位字减法
SBB DX, BX ;高位字减法
-
SUB AX, CX
AX:18000H−CX:9000HAX=F000H\begin{array}{r} AX:\ {\color{Red} 1} \ 8000H \\ -\ CX:\quad 9000H\\ \hline AX=F000H \end{array}AX: 1 8000H− CX:9000HAX=F000H
AX寄存器值为F000HF000HF000H,产生借位CF = 1 -
SBB DX, BX
DX:2001H−BX:2000H−CF:1BDX=0000H\begin{array}{r} DX:\ 2001H\\ -\ BX:\ 2000H\\ -\ CF:\qquad {\color{Red} 1} B\\ \hline DX=0000H \end{array}DX: 2001H− BX: 2000H− CF:1BDX=0000H
将CF值额外减去,即相当于减去了低位向高位借走的1,保证了结果的正确性,DX寄存器值为0000H0000H0000H
即20018000H−20009000H=0000F000H2001\ 8000H-2000\ 9000H=0000\ F000H2001 8000H−2000 9000H=0000 F000H
才疏学浅,盼君指点