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之,知道了原理;详解:
最终EAX的结果只有0或者1,所以可以表示代码如下:__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
}
cpu 这样做的原因是算术运算取代了逻辑运算,缩短了运行时间;if(flag == 0)
return TRUE;
else
return FALSE;
===================================================
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