分支优化:neg+sbb算术运算代替逻辑跳

今天在分析一个样本的时候,发现一段代码。

1 // .text:100012DF                 sub     esi, 0B7h  // 183
2 // .text:100012E5                 neg     esi
3 // .text:100012E7                 sbb     esi, esi
4 // .text:100012EA                 inc     esi

neg指令影响的标志

如果源操作数是 0,则 CF 标志清除为 0;否则设置为 1。OF、SF、ZF、AF 及 CF 标志根据结果设置。

neg求补指令:相当于按各位取反加1

现在代入三种值来进行验证:

1、esi 等于 183。则有:

    sub esi, 0b7h;  esi == 0;  cf == 0;

    neg  esi;          esi == 0; cf == 0;

    sbb  esi, esi;    esi == 0; cf == 0;

    inc esi;            esi == 1;

最终结果为:1

2、esi 小于 183。则有:

    sub esi, 0b7h;  esi == 负数;  cf == 1;

    neg  esi;          esi == 正数;  cf == 1; 

    sbb  esi, esi;    esi == -1;    cf == 1;  sbb指令带cf(进位、借位)减法.多减去一个1.则为-1

    inc esi;            esi == 0;      cf == 1; 

最终结果为:0

3、esi 大于 183。则有:

    sub esi, 0b7h;  esi == 正数;  cf == 0;

    neg  esi;          esi == 负数;  cf == 1; 

    sbb  esi, esi;    esi == -1;    cf == 1;  sbb指令带cf(进位、借位)减法.多减去一个1.则为-1

    inc esi;            esi == 0;      cf == 1; 

最终结果为:0

那么遇到以上代码。则为vc编译器在02中,对逻辑跳转进行的优化。

直接还原为:

if (esi == 183)

{

   return true;

}

return false;

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

计算机中数码的表示:

定义-》

正数:原码,反码,补码相同。

负数:原码为其对应正数原码最高符号位取反。

   反码为其原码除符号位外都取反。

   补码为其原码除符号位外取反加1。

所以最高位符号位都不变。

补码机:正数补码为其原码,负数为其正数原码取反加1。

NEG指令,相当于0-OPR,并影响进位标志CF.

数学意义上相当于:相当于0-OPR

在计算时实际是以补码形式运算,运算时只有0不影响CF,其它情况都影响CF.为什么,请看以下分析:

(1)假设有数:a=3;

那么:NEG a

分析:a补码为0011,0的补码为0000,所以0000-0011最终会向高位借1所以会有CF=1

(2)假设有数:a=-3;

那么:NEG a

分析:a为负数,补码为1101,所以0000-1101=0011即正数3,所以CF=1

NEG+SBB指令

假设有C语言:
  if(foo() != 0)
  {
    return(FALSE);
  }else{
    return(TURE);
  }
也可以是:
  if(foo() != 0) return(FALSE);
  return TURE;

可以这样汇编(用fasm语法):

  call [foo];调用foo(),返回值在eax中
  neg eax;把操作数按位求反后末位加1, 且if(EAX==0){CF=0}else{CF=1}
  sbb eax,eax; eax-eax-cf ==> (eax)
        ;操作结果:如果foo的返回值不是 0,此时 (eax) = -1
        ;    :如果foo的返回值是 0,此时 (eax) = 0
  inc eax  ; 操作结果:如果foo的返回值不是 0,此时 (eax) = 0
        ;    :如果foo的返回值是 0,此时 (eax) = 1

进一步解释
; if (EAX)=0 则:
; NEG EAX ;等价于: 0 - (EAX) = 0 , 结果: (EAX)=0 ,CF=0
; SBB EAX, EAX ; 等价于 (EAX)-(EAX)-(CF) , 结果为: (EAX)=0
; INC EAX ; ,结果 (EAX)=1

;if EAX!=0 (假设 EAX=5) 则:
; NEG EAX 等价于: 0 - 5 = -5 所以: (EAX)= -5 ,但CF=1
; SBB EAX, EAX 等价于 (EAX)-(EAX)-(CF) 即: (EAX)= -1
; INC EAX 结果 (EAX)=0

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值