汇编语言:进位标志与溢出标志

时间:2020-12-18 01:21:00


1、

对于非符号数来说,不存在溢出的问题,它的进位就相当于符号数中的溢出.
而对于符号数来说,不存在进位的问题.两个正数相加(或一个正数减一个负数)得到负数,或是两个负数相加得到正数,就是溢出了.一个正数和一个负数相加不可能溢出


OF:溢出标志; CF:进位标志
x1 = 01100000>0, x2 = 01110000>0
x1+x2 = 1101000 < 0,  结果错误有溢出 OF=1, 不产生进位================有溢出、无进位

x1=00111100 , x2 = 11110010
x1+x2 = (1)00101110, 结果正确,不会溢出(正加负)OF=0, 有进位(1)CF=1,====================无溢出、有进位
ps:x1, x2 为补码形式



2、

       最近开一段逆向汇编代码,在一处if 判断语句处用到了NEG+SBB ,虽然这两个汇编的意思能理解,但是当时没理解为什么这么写,后来google之,知道了原理;详解:

      NEG指令是求补码,补码即操作数连同符号位一起求反+1,如果操作数是0的话CF标志位是0,如果不为0,CF标志位是1;      SBB是借位减法操作,SBB dest,src;  (dest)-(src)-CF;      例子:

__asm

{

MOV EAX,1 ;EAX =1

NEG EAX ;EAX =11111111,CF = 1

SBB EAX,EAX ;EAX = -1,CF =1;

INC EAX ;EAX = 0;

}


__asm

{

MOV EAX,0 ;EAX = 0

NEG EAX ;EAX = 0000001,CF = 0

SBB EAX,EAX ;EAX = 0

INC EAX ;EAX = 1

}


最终EAX的结果只有0或者1,所以可以表示代码如下:

if(flag == 0)

return TRUE;

else

return FALSE;

cpu 这样做的原因是算术运算取代了逻辑运算,缩短了运行时间;

===================================================


neg eax  
sbb eax,eax  
and al,0fc;ofc是-4  
add eax,5  
解释:如果eax为0,neg eax之后cf=0;那么sbb eax,eax之后eax就为0,al自然也是0,那么and al,ofc之后al还是0,eax也是0,再接着add eax,5之后eax就是5
如果eax不是0,neg eax 之后cf=1,那么sbb eax,eax之后eax就是-1,-1的二进制就是:0xFFFFFFFF,那么al就是0xFF,所以and al,0fc之后al中的值就是0fc,eax就是0xFFFFFFFC,也就是-4,那么add eax,5之后eax就是1.


综上:这段代码的作用就是当eax为0时,把eax改为5,当eax为非0时,eax改为1(这段代码可以用来优化c语言中的“0为假,非零即为真”的if语句).而这段代码没有用到条件分支就实现了条件分支的作用,可以用来优化代码。




3、

NEG 的操作是:0-操作数 没错。
并且使得CF=1(但是对0求补除外)这是汇编的规定。
而且对-128,-32768,-2147483648等数求补时,OF=1,其余情况OF=0,这也是汇编的规定。

mov eax, 1
neg eax
//neg指令后,eax 值为 0xFFFFFFFF,同时EFL标识寄存器中CF=1

mov eax, -1
neg eax
//neg指令后,eax 值为 0x00000001,同时EFL标识寄存器中CF=1

mov eax, 0
neg eax
//neg指令后,eax 值为 0x00000000,同时EFL标识寄存器中CF=0