[教程]逆向反汇编第九课

条件设置指令的形式是:SETcc r/m8,其中r/m8是表示8位寄存器或单字节内存单元.
条件设置指令根据处理器定义的16种条件cc,测试一些标志位,然后把结果记录到目标操作数中.当条件满足时,目标操作数会被置1,否则置0.这16种条件与条件转移指令jcc中的条件是一样的.
条件设置指令可以用来消除程序中的转移指令.在C语言里,常会见到执行以下功能的语句:
c=(a<B)?C1:C2;
如果允许出现条件分支,编译器会产生如下的代码或者是非常类似的代码:

 

  1. cmpa,b    
  2. moveax,c1    
  3. moveax,c2    
  4. @@:   

 

如果使用条件设置指令,编译器将会产生不包含条件分支的逻辑判断代码:

 

  1. xoreax,eax    
  2. cmpa,b    
  3. setgeal;a>=b,则al置1,否则al置0    
  4. deceax    
  5. addeax, (c1-c2)    
  6. addeax,c2  

 

也可用条件转移传输指令cmov或fcmov去除程序中的转移指令,但是他们仅仅被Pentium Pro以后的处理器支持.实现同样功能的代码入下:

 

  1. moveax,c2    
  2. cmpa,b    
  3. cmov1eax,c1  

 

一些编译器优化时,在不改变原逻辑的情况下,使用数学技巧把源代码中的一些逻辑分支转变成算术操作,消除或减少程序中出现的条件转移指令.可以提高CPU的流水线性能
看一段C的代码:

 

  1. int main()    
  2. {    
  3.      if(FindWindow(NULL,/"计算器/"))    
  4.          return 1;    
  5.      else    
  6.         return 2;    
  7. }   

 

用VC编译连接后,其反汇编代码如下:

 

  1. 00401000/$68 30604000 PUSH 4_5_5.00406030; /Title = /"计算器/"    
  2. 00401005|.6A 00 PUSH 0 ; |Class = 0    
  3. 00401007|.FF15 9C504000 CALL DWORD PTR DS:[<&USER32.FindWindowA>>;    
  4. 0040100D|.F7D8NEG EAX    
  5. 0040100F|.1BC0SBB EAX,EAX    
  6. 00401011|.24 FC AND AL,0FC    
  7. 00401013|.83C0 05 ADD EAX,2    
  8. 00401016//.C3RETN   

 

编译生成的代码没有一句跳转转移指令,却实现原程序的逻辑.代码首先用neg指令检查eax是否为0,结果存放在CF标志位中.sbb指令将目的操作数减去源操作数,再减去减去借位CF(进位),结果送到目的操作数/"sbb eax,eax/"这句的结果由CF决定,当CF为1时,eax为-1,否则为0,用伪码来表示:

 

  1. if(eax)    
  2.     cf=1;    
  3. esle    
  4.     cf=0;    
  5. eax=-cf;   

 

接下来两句指令根据eax的值:FFFFFFFh和0来决定最终结果,当eax是FFFFFFFFh的结果是1;当eax是0时,计算结果为2.

 

  1. 00401011|.24 FC AND AL,0FC    
  2. 00401013|.83C0 05 ADD EAX,2   

 

这类代码比较常见,当知道是条件转移转移指令优化生成的,还原就比较简单了.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值