C++反汇编学习笔记(五)各种算数运算的工作形式(4)

1、  条件表达式(?:)

  表达式1?表达式2:表达式3

  条件表达式的构成应该是先判断再选择。但编译器优化后未必是这样。当表达式1为一个常量时,编译器会在编译期间得到答案,将不会有条件表达式存在。

  转换方案:

    ①   :表达式2和表达式3都是常量且两者的差值为1;

    ②   :其他

  先说3个指令:cmove和cmovle,cmovne,条件传送指令,应该还有类似的指令,暂时没找到这些指令的资料,下面是根据汇编代码逆推的,不知道对不对,望高手指导!

    Cmp ........

    Cmove/cmovle/cmovne reg1,reg2;

    根据前面指令对标志位的影响:

    Cmove:如果zf=0,将reg2的值传送到reg1中

    Cmovle:如果zf!=of或zf=1,则将reg2的值传送到reg1中

    Cmovne:如果zf=0,则将reg2的值传送到reg1中。

  Debug版和release版差别很大,debug为调试方便,使用的依然是条件判断的分支结构。

C++源码

Debug版

Release版

#include <iostream>

using namespace std;

int main()

{

         int a, b;

         cin >> a >> b;

         //①

         cout << (a == 5 ? 5 : 6);

         //②

         cout << (a == 6 ? 3 : 10);

         cout << (a <= 7 ? 2 : 11);

         cout << (a ? 8: b);

 

         system("pause");

         return 0;

}

#include <iostream>

using namespace std;

int main()

{

.............略

         int a, b;

         cin >> a >> b;

...............略

         //①

         cout << (a == 5 ? 5 : 6);

003D5EB6  cmp         dword ptr [a],5 

003D5EBA  jne         main+68h (03D5EC8h) 

003D5EBC  mov         dword ptr [ebp-0E0h],5 

003D5EC6  jmp         main+72h (03D5ED2h) 

003D5EC8  mov         dword ptr [ebp-0E0h],6 

003D5ED2  mov         esi,esp 

003D5ED4  mov         eax,dword ptr [ebp-0E0h] 

003D5EDA  push        eax 

003D5EDB  mov         ecx,dword ptr ds:[3E10A8h] 

   

         cout << (a == 5 ? 5 : 6);

003D5EE1  call        dword ptr ds:[3E1094h] 

003D5EE7  cmp         esi,esp 

003D5EE9  call        __RTC_CheckEsp (03D1339h) 

         //②

         cout << (a == 6 ? 3 : 10);

003D5EEE  cmp         dword ptr [a],6 

003D5EF2  jne         main+0A0h (03D5F00h) 

003D5EF4  mov         dword ptr [ebp-0E0h],3 

003D5EFE  jmp         main+0AAh (03D5F0Ah) 

003D5F00  mov         dword ptr [ebp-0E0h],0Ah 

003D5F0A  mov         esi,esp 

003D5F0C  mov         eax,dword ptr [ebp-0E0h] 

003D5F12  push        eax 

003D5F13  mov         ecx,dword ptr ds:[3E10A8h] 

003D5F19  call        dword ptr ds:[3E1094h] 

003D5F1F  cmp         esi,esp 

003D5F21  call        __RTC_CheckEsp (03D1339h) 

         cout << (a <= 7 ? 2 : 11);

003D5F26  cmp         dword ptr [a],7 

003D5F2A  jg          main+0D8h (03D5F38h) 

003D5F2C  mov         dword ptr [ebp-0E0h],2 

003D5F36  jmp         main+0E2h (03D5F42h) 

003D5F38  mov         dword ptr [ebp-0E0h],0Bh 

003D5F42  mov         esi,esp 

003D5F44  mov         eax,dword ptr [ebp-0E0h] 

003D5F4A  push        eax 

003D5F4B  mov         ecx,dword ptr ds:[3E10A8h] 

003D5F51  call        dword ptr ds:[3E1094h] 

003D5F57  cmp         esi,esp 

003D5F59  call        __RTC_CheckEsp (03D1339h) 

         cout << (a ? 8: b);

003D5F5E  cmp         dword ptr [a],0 

         cout << (a ? 8: b);

003D5F62  je          main+110h (03D5F70h) 

003D5F64  mov         dword ptr [ebp-0E0h],8 

003D5F6E  jmp         main+119h (03D5F79h) 

003D5F70  mov         eax,dword ptr [b] 

003D5F73  mov         dword ptr [ebp-0E0h],eax 

003D5F79  mov         esi,esp 

003D5F7B  mov         ecx,dword ptr [ebp-0E0h] 

003D5F81  push        ecx 

003D5F82  mov         ecx,dword ptr ds:[3E10A8h] 

003D5F88  call        dword ptr ds:[3E1094h] 

003D5F8E  cmp         esi,esp 

003D5F90  call        __RTC_CheckEsp (03D1339h) 

 

         system("pause");

............略

         return 0;

003D5FAC  xor         eax,eax 

}

..........略

#include <iostream>

using namespace std;

int main()

{

012612A0  push        ebp 

012612A1  mov         ebp,esp 

012612A3  sub         esp,0Ch 

012612A6  mov         eax,dword ptr ds:[01264000h] 

012612AB  xor         eax,ebp 

012612AD  mov         dword ptr [ebp-4],eax 

         int a, b;

         cin >> a >> b;

012612B0  mov         ecx,dword ptr ds:[1263038h] 

         int a, b;

         cin >> a >> b;

012612B6  lea         eax,[b] 

012612B9  push        eax 

012612BA  lea         eax,[a] 

012612BD  push        eax 

012612BE  call        dword ptr ds:[1263028h] 

012612C4  mov         ecx,eax 

012612C6  call        dword ptr ds:[1263028h] 

         //①

         cout << (a == 5 ? 5 : 6);

012612CC  mov         ecx,dword ptr ds:[126303Ch] 

012612D2  xor         eax,eax 

012612D4  cmp         dword ptr [a],5 

//如果a==5,则将eax置0,否则将eax置1,然后eax+5,

//最后输出eax+5的结果

012612D8  setne       al 

012612DB  add         eax,5 

012612DE  push        eax 

012612DF  call        dword ptr ds:[1263024h] 

         //②

         cout << (a == 6 ? 3 : 10);

012612E5  cmp         dword ptr [a],6 

012612E9  mov         ecx,3 

012612EE  mov         eax,0Ah 

//根据cmp最ZF位的影响,如果ZF=1,则表示a==6,将ecx(3)传送到eax中进行输出,否则保留eax的值(10)进行输出

012612F3  cmove       eax,ecx 

012612F6  mov         ecx,dword ptr ds:[126303Ch] 

012612FC  push        eax 

012612FD  call        dword ptr ds:[1263024h] 

         cout << (a <= 7 ? 2 : 11);

01261303  cmp         dword ptr [a],7 

01261307  mov         ecx,2 

0126130C  mov         eax,0Bh 

//这里判断的是ZF和OF,如果ZF=1(相等)或ZF!=OF(溢出,即a<7),则将ecx(2)的值传送到eax中进行输出,否则保留eax的值(11)进行输出

01261311  cmovle      eax,ecx 

01261314  mov         ecx,dword ptr ds:[126303Ch] 

0126131A  push        eax 

0126131B  call        dword ptr ds:[1263024h] 

         cout << (a ? 8: b);

01261321  cmp         dword ptr [a],0 

         cout << (a ? 8: b);

01261325  mov         ecx,8 

0126132A  mov         eax,dword ptr [b] 

//整理是判断a的真假,看得是ZF标志位

0126132D  cmovne      eax,ecx 

01261330  mov         ecx,dword ptr ds:[126303Ch] 

01261336  push        eax 

01261337  call        dword ptr ds:[1263024h] 

 

         system("pause");

0126133D  push        126319Ch 

01261342  call        dword ptr ds:[12630C4h] 

         return 0;

}

........略

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。