【汇编语言】状态标志符(CF/OF/SF/ZF)在运算(ADD/SUB/ADC/SBB)过程中的响应变化

目录

      • 各类运算时状态标志的响应变化
        • 标志符在各种`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运算下的响应情况
  • 无符号数和有符号数都正常
    0000   0011 + 0000   0100 0000   0111 \begin{array}{r} 0000\ 0011 \\ +0000\ 0100 \\ \hline 0000\ 0111 \end{array} 0000 0011+0000 01000000 0111
    无符号数: 3 + 4 = 7 3+4=7 3+4=7,这里显然未产生进位,因此CF = 0
    有符号数: ( + 3 ) + ( + 4 ) = ( + 7 ) (+3)+(+4)=(+7) (+3)+(+4)=(+7),这里两个正数相加,结果也为正数,未产生溢出OF = 0

  • 无符号数有溢出
    0000   0011 + 1111   1111 1   0000   0010 \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

  • 有符号数有溢出
    0000   0011 + 0111   1110 1000   0001 \begin{array}{r} 0000\ 0011 \\ +0111\ 1110 \\ \hline 1000\ 0001 \end{array} 0000 0011+0111 11101000 0001
    无符号数: 3 + 126 = 129 3+126=129 3+126=129,未产生进位,CF = 0
    有符号数: ( + 3 ) + ( + 126 ) = ( − 127 ) (+3)+(+126)=(-127) (+3)+(+126)=(127),两个正数相加后结果却为负数(加数的符号位与结果的符号位相异),显然出现了溢出,溢出OF = 1

  • 无符号数和有符号数都溢出
    1000   0001 + 1000   0010 1   0000   0011 \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运算下的响应情况
  • 无符号数和有符号数都溢出
    1   0111   0010 − 1001   0011 1101   1111 \begin{array}{r} {\color{Red} 1} \ 0111\ 0010\\ -1001\ 0011\\ \hline 1101\ 1111 \end{array} 1 0111 00101001 00111101 1111
    无符号数: 114 − 147 = 223 114-147=223 114147=223,由于被减数小于减数,不够减,这时计算机允许被减数向高位借位,因为不存在实际的高位,就体现在CF标志位,当减法运算中需要解位时,将CF标志位置1,故CF = 1,此时说明无符号数运算的溢出
    有符号数: ( + 114 ) − ( − 109 ) = ( − 33 ) (+114)-(-109)=(-33) (+114)(109)=(33),被减数是正数,减数是负数,正数减负数结果应该为正数,而运算结果却为负数,说明发生了溢出,OF = 1

  • 无符号数有溢出
    1   0110   0011 − 0111   1101 1110   0110 \begin{array}{r} {\color{Red} 1} \ 0110\ 0011\\ -0111\ 1101\\ \hline 1110\ 0110 \end{array} 1 0110 00110111 11011110 0110
    无符号数: 99 − 125 = 230 99-125=230 99125=230,同第一个情况,需要借位,故CF = 1
    有符号数: ( + 99 ) − ( + 125 ) = ( − 26 ) (+99)-(+125)=(-26) (+99)(+125)=(26)两个同号数相减,无论结果是正数或负数,都不会发生溢出(与加法相反,因为两同号数相减可看作为两异号数相加),故OF = 0

    同号两数相减,OF总为0

  • 有符号数有溢出
    1010   0110 − 0011   0110 0111   0000 \begin{array}{r} 1010\ 0110\\ -0011\ 0110\\ \hline 0111\ 0000 \end{array} 1010 01100011 01100111 0000
    无符号数: 166 − 54 = 112 166-54=112 16654=112,被减数大于减数,无需借位,故CF = 0
    有符号数: ( − 90 ) − ( + 54 ) = ( + 112 ) (-90)-(+54)=(+112) (90)(+54)=(+112),负数减正数结果应该为负数,而结果却为正数,发生了溢出,OF = 1

  • 无符号数和有符号数都正常
    0010   0110 − 0001   0010 0001   0100 \begin{array}{r} 0010\ 0110\\ -0001\ 0010\\ \hline 0001\ 0100 \end{array} 0010 01100001 00100001 0100
    无符号数: 38 − 18 = 20 38-18=20 3818=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 ;高位字加法
  1. ADD AX, CX

    A X :   8000 H +   C X :   9000 H A X = 1   1000 H \begin{array}{r} AX:\ 8000H \\ +\ CX:\ 9000H\\ \hline AX={\color{Red} 1} \ 1000H \end{array} AX: 8000H+ CX: 9000HAX=1 1000H
    AX寄存器值为 1000 H 1000H 1000H,产生进位CF = 1

  2. ADC DX, BX
    D X :   2000 H +   B X :   4000 H +   C F : 1 B D X = 6001 H \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寄存器值为 6001 H 6001H 6001H
    2000   8000 H + 4000   9000 H = 6001   1000 H 2000\ 8000H+4000\ 9000H=6001\ 1000H 2000 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 ;高位字减法
  1. SUB AX, CX
    A X :   1   8000 H −   C X : 9000 H A X = F 000 H \begin{array}{r} AX:\ {\color{Red} 1} \ 8000H \\ -\ CX:\quad 9000H\\ \hline AX=F000H \end{array} AX: 1 8000H CX:9000HAX=F000H
    AX寄存器值为 F 000 H F000H F000H,产生借位CF = 1

  2. SBB DX, BX

    D X :   2001 H −   B X :   2000 H −   C F : 1 B D X = 0000 H \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寄存器值为 0000 H 0000H 0000H
    2001   8000 H − 2000   9000 H = 0000   F 000 H 2001\ 8000H-2000\ 9000H=0000\ F000H 2001 8000H2000 9000H=0000 F000H

才疏学浅,盼君指点

你可能感兴趣的:(汇编语言,asm)