反汇编代码还原之加减乘

加法

加法对应的汇编add指令。如果是加1有可能就会使用inc指令
而加法也特别简单。配合上优化方式.可以很好还原的

//加法
int NumberOne = 0;
int NumberTwo = 10;
//scanf是防止优化
scanf("%d",&NumberOne);
scanf("%d",&NumberTwo);
//变量加变量
int Count = NumberOne+NunmberTwo;
//常量加常量
int Count1 = 1+2;
//变量加常量
int Count2 = NumberOne+2;
int Count3 = NumberTwo+3;
printf("%d%d%d",Count1,Count2,Count3);
//防止优化编译器优化是很强的,虽然我们取地址了但是后续没有改变值就会给我们优化掉。所以这里防止优化,但是防止优化也要能骗过编译器,比如我们可以在下面的反汇编看到。我们的count变量有的已经全部优化掉了。
scanf("%d",&Count1);
scanf("%d",&Count2);
scanf("%d",&Count3);
 printf("%d%d%d",&Count1,&Count2,&Count3);
 system("pause");
 return 0 ;

反汇编代码

1000 ; int __cdecl main(int argc, const char **argv, const char **envp)
.text:00401000 _main           proc near               ; CODE XREF: start+AF↓p
.text:00401000
.text:00401000 var_10          = dword ptr -10h
.text:00401000 var_C           = dword ptr -0Ch
.text:00401000 var_8           = dword ptr -8
.text:00401000 var_4           = dword ptr -4
.text:00401000 argc            = dword ptr  4
.text:00401000 argv            = dword ptr  8
.text:00401000 envp            = dword ptr  0Ch
.text:00401000 arg_C           = byte ptr  10h
.text:00401000
.text:00401000                 sub     esp, 10h
.text:00401003                 lea     eax, [esp+0]
.text:00401007                 mov     [esp+10h+var_10], 0Ah
.text:0040100F                 push    eax
.text:00401010                 push    offset aD       ; "%d"
.text:00401015                 call    _scanf
.text:0040101A                 lea     ecx, [esp+8]
.text:0040101E                 push    ecx
.text:0040101F                 push    offset aD       ; "%d"
.text:00401024                 call    _scanf
.text:00401029                 mov     edx, [esp+10h]
.text:0040102D                 push    13
.text:0040102F                 mov     [esp+24h+var_4], 3
.text:00401037                 mov     [esp+24h+var_C], 13
.text:0040103F                 lea     eax, [edx+2]
.text:00401042                 push    eax
.text:00401043                 push    3
.text:00401045                 push    offset aD       ; "%d"
.text:0040104A                 mov     [esp+30h+var_8], eax
.text:0040104E                 call    _printf
.text:00401053                 lea     eax, [esp+30h+var_4]
.text:00401057                 push    eax
.text:00401058                 push    offset aD       ; "%d"
.text:0040105D                 call    _scanf
.text:00401062                 lea     ecx, [esp+38h+var_8]
.text:00401066                 push    ecx
.text:00401067                 push    offset aD       ; "%d"
.text:0040106C                 call    _scanf
.text:00401071                 lea     edx, [esp+40h+var_C]
.text:00401075                 push    edx
.text:00401076                 push    offset aD       ; "%d"
.text:0040107B                 call    _scanf
.text:00401080                 lea     eax, [esp+48h+var_C]
.text:00401084                 lea     ecx, [esp+48h+var_8]
.text:00401088                 push    eax
.text:00401089                 lea     edx, [esp+4Ch+var_4]
.text:0040108D                 push    ecx
.text:0040108E                 push    edx
.text:0040108F                 push    offset aDDD     ; "%d%d%d"
.text:00401094                 call    _printf
.text:00401099                 add     esp, 48h
.text:0040109C                 push    offset aPause   ; "pause"
.text:004010A1                 call    _system
.text:004010A6                 xor     eax, eax
.text:004010A8                 add     esp, 14h
.text:004010AB                 retn
.text:004010AB _main           endp

加法中的流水线优化

.text:00401000                 sub     esp, 10h
.text:00401003                 lea     eax, [esp+0]
.text:00401007                 mov     [esp+10h+var_10], 0Ah
.text:0040100F                 push    eax
.text:00401010                 push    offset aD       ; "%d"
.text:00401015                 call    _scanf

这一段代码我们明显能看出是有流水线优化
正常排序后的汇编代码应该如下

.text:00401000                 sub esp,10h
.text:00401007                 mov [esp+10+var_10],0Ah

.text:00401003                 lea  eax,[esp+0]
.text:0040100F                 push eax
.text:00401010                 push offset aD ;   "%d"
.text:00401015                 call _scanf

这里的赋值指令所以直接使用了mov了。单独拿出这一段是想告诉大家。第一篇是基础但是你学习反汇编的前提。如果以后有除法,乘法等。
他们都有单独的优化。在配合流水线优化,往往就让你发觉很难,导致无法入门。

加法的lea指令优化

看下核心汇编代码。去掉scanf等

.text:00401007    mov [esp+10h+var_10],0Ah
.text:00101029    mov edx,[esp+20h+var_10]
.text:0040103F    lea eax,[edx+2]

我们使用scanf去掉优化后。我们的高级代码

int Count2 = NumberOne+2;

直接变成了lea指令lea指令在这里并不取地址的指令。而是计算的指令。计算的是 edx+2结果在返回给eax
这是加法的一种优化方式。lea指令优化
所以在我们还原的时候可以还原如下

eax =edx+2  edx=var_10   var_10 =0A  
继续变化
edx=0XA
eax=edx+2
继续变化eax=10+2

此时我们就反推出了加法原型。方法:从下往上。按照上下文进行还原。这种方法 也类似与WG找数据 从下往上找。

加法中用到了常量折叠 常量传播

看高级代码

int Count1 =  1+2;

这就代码直接被编译器优化3符合常量折叠

int Count3=Number+3;

高级代码中的NumberTwo因为我们并没有对其取地址。而后续也没有对其进行修改。所以进行常量传播+常量折叠变成代码中的12

.text:0040402f   mov [esp+24h+var_4],3
.text:004010037  mov [esp+24hvar_c],13
高版本中的汇编
.text:00401080 sub_401080      proc near               ; CODE XREF: start-8D↓p
.text:00401080
.text:00401080 var_10          = dword ptr -10h
.text:00401080 var_C           = dword ptr -0Ch
.text:00401080 var_8           = dword ptr -8
.text:00401080 var_4           = dword ptr -4
.text:00401080
.text:00401080                 push    ebp
.text:00401081                 mov     ebp, esp
.text:00401083                 sub     esp, 10h
.text:00401086                 lea     eax, [ebp+var_4]
.text:00401089                 mov     [ebp+var_4], 0Ah
.text:00401090                 push    eax
.text:00401091                 push    offset unk_41ECDC
.text:00401096                 call    sub_401050
.text:0040109B                 lea     eax, [ebp+var_4]
.text:0040109E                 push    eax
.text:0040109F                 push    offset unk_41ECDC
.text:004010A4                 call    sub_401050
.text:004010A9                 mov     eax, [ebp+var_4]
.text:004010AC                 add     eax, 2
.text:004010AF                 mov     [ebp+var_10], 3
.text:004010B6                 push    0Dh
.text:004010B8                 push    eax
.text:004010B9                 push    3
.text:004010BB                 push    offset unk_41ECDC
.text:004010C0                 mov     [ebp+var_C], eax
.text:004010C3                 mov     [ebp+var_8], 0Dh
.text:004010CA                 call    sub_401020
.text:004010CF                 lea     eax, [ebp+var_10]
.text:004010D2                 push    eax
.text:004010D3                 push    offset unk_41ECDC
.text:004010D8                 call    sub_401050
.text:004010DD                 lea     eax, [ebp+var_C]
.text:004010E0                 push    eax
.text:004010E1                 push    offset unk_41ECDC
.text:004010E6                 call    sub_401050
.text:004010EB                 lea     eax, [ebp+var_8]
.text:004010EE                 push    eax
.text:004010EF                 push    offset unk_41ECDC
.text:004010F4                 call    sub_401050
.text:004010F9                 lea     eax, [ebp+var_8]
.text:004010FC                 push    eax
.text:004010FD                 lea     eax, [ebp+var_C]
.text:00401100                 push    eax
.text:00401101                 lea     eax, [ebp+var_10]
.text:00401104                 push    eax
.text:00401105                 push    offset aDDD     ; "%d%d%d"
.text:0040110A                 call    sub_401020
.text:0040110F                 add     esp, 48h
.text:00401112                 push    offset aPause   ; "pause"
.text:00401117                 call    sub_4048F7
.text:0040111C                 add     esp, 4
.text:0040111F                 xor     eax, eax
.text:00401121                 mov     esp, ebp
.text:00401123                 pop     ebp
.text:00401124                 retn
.text:00401124 sub_401080      endp

高版本代码变多。函数使用了EBP寻址 vc6.0使用了esp寻址
在VC6.0使用了lea指令优化。在vs2019中使用了add+mov的方式进行优化
例如:

int a =10;
int b =a+1;
printf("%d",b);
//在汇编中反汇编后,你可能直接变成了如下
printf("%d",11);

减法

减法的高级代码与反汇编

减法 对应指令sub 如果是自减那么对应的指令可能就是dec指令
计算机只会做加法,而不会做减法。所以对减法的优化就是变为加法
高级代码

int main(int argc, char* argv[])
{
    /*
    减法
    */
    int NumberOne = argc;
    int NumberTwo = argc;
 
 
    int Count  = NumberOne - NumberTwo;
 
    int Count1 = NumberOne - 2;
    int Count2 = NumberOne - 5;
    int Count3 = NumberTwo - NumberOne;
 
    printf("%d%d%d",Count1,Count2,Count3);
 
    //防止优化
    scanf("%d",&Count1);
    scanf("%d",&Count2);
    scanf("%d",&Count3);
 
    printf("%d%d%d",&Count1,&Count2,&Count3);
    system("pause");
 
    return 0;
}

vc6.0反汇编

text:00401000 ; int __cdecl main(int argc, const char **argv, const char **envp)
.text:00401000 _main           proc near               ; CODE XREF: start+AF↓p
.text:00401000
.text:00401000 var_8           = dword ptr -8
.text:00401000 var_4           = dword ptr -4
.text:00401000 argc            = dword ptr  4
.text:00401000 argv            = dword ptr  8
.text:00401000 envp            = dword ptr  0Ch
.text:00401000
.text:00401000                 sub     esp, 8
.text:00401003                 mov     eax, [esp+8+argc]
.text:00401007                 xor     edx, edx
.text:00401009                 push    edx
.text:0040100A                 mov     [esp+0Ch+argc], edx
.text:0040100E                 lea     ecx, [eax-2]
.text:00401011                 add     eax, 0FFFFFFFBh
.text:00401014                 push    eax
.text:00401015                 push    ecx
.text:00401016                 push    offset aD       ; "%d"
.text:0040101B                 mov     [esp+18h+var_4], ecx
.text:0040101F                 mov     [esp+18h+var_8], eax
.text:00401023                 call    _printf
.text:00401028                 lea     eax, [esp+18h+var_4]
.text:0040102C                 push    eax
.text:0040102D                 push    offset aD       ; "%d"
.text:00401032                 call    _scanf
.text:00401037                 lea     ecx, [esp+20h+var_8]
.text:0040103B                 push    ecx
.text:0040103C                 push    offset aD       ; "%d"
.text:00401041                 call    _scanf
.text:00401046                 lea     edx, [esp+28h+argc]
.text:0040104A                 push    edx
.text:0040104B                 push    offset aD       ; "%d"
.text:00401050                 call    _scanf
.text:00401055                 lea     eax, [esp+30h+argc]
.text:00401059                 lea     ecx, [esp+30h+var_8]
.text:0040105D                 push    eax
.text:0040105E                 lea     edx, [esp+34h+var_4]
.text:00401062                 push    ecx
.text:00401063                 push    edx
.text:00401064                 push    offset aDDD     ; "%d%d%d"
.text:00401069                 call    _printf
.text:0040106E                 push    offset aPause   ; "pause"
.text:00401073                 call    _system
.text:00401078                 xor     eax, eax
.text:0040107A                 add     esp, 44h
.text:0040107D                 retn
.text:0040107D _main           endp

核心代码

text:00401000                 sub     esp, 8
.text:00401003                 mov     eax, [esp+8+argc]       eax = argc
 
.text:00401007                 xor     edx, edx
.text:00401009                 push    edx
.text:0040100A                 mov     [esp+0Ch+argc], edx  argc = 0
 
.text:0040100E                 lea     ecx, [eax-2]  ecx= arc-2
.text:00401011                 add     eax, 0FFFFFFFBh  eax =eax+
.text:00401014                 push    eax
.text:00401015                 push    ecx
.text:00401016                 push    offset aD       ; "%d"
.text:0040101B                 mov     [esp+18h+var_4], ecx
.text:0040101F                 mov     [esp+18h+var_8], eax

第一种方式跟加法一样 使用lea进行计算第二种方式使用了add指令加了一个很大的数0FFFFFFFFBh
其实这个地方就是对减法的优化很大的数是补码

基础知识
  1. 原码: 以二进制来说原码是以符号位加上其绝对值来表示的一个数。也就是用二进制的第一位表示符号位其余位表示真值[11111111,01111111]-127~127的值

  2. 反码:正数的反码就是自己本身,负数的反码是符号位不变其余各位取反

  3. 补码:正数的补码就是自己本身,负数的补码就是在其原码的基础上,符号位不变,其余个位取反最后加1 负数=反码+1
    其实负数就变成了补码了补码的变化就是负数取法+1那么还原也是
    Not(0FFFFFFFBh)+1就会得出真实的值。
    如果add操作数使用了负数的表现形式。那么就可以还原为减法。因为执行的操作时减法而不是加法。

乘法的x86x64优化以及反汇编

乘法的可优化选项与汇编

乘法 对应指令 IMUL以及对应指令Mul分别时有符号乘法以及无符号乘法两个数都是变量的时候。且不满足前面所讲的变量去除优化选项那么是无法进行优化的。乘法对于2的幂是可以进行优化的。会使用指令较短的周期进行优化
高级代码

int main(int argc, char* argv[])
{
    /*
    乘法
    */
    int NumberOne = argc;
    int NumberTwo = argc;
 
    scanf("%d",&NumberOne);
    scanf("%d",&NumberTwo);
 
 
    int Count1 = NumberOne * NumberTwo;  //不满足变量去除则就会使用原生除法指令优化
 
    int Count2 = NumberOne * 4;
 
    int Count3 = NumberTwo * 15;
 
    int Count4 = NumberOne + 4 * 3;      //混合运算
 
    int Count5 = NumberTwo * 7 + 5;      //混合运算
 
 
 
    printf("%d%d%d%d%d",Count1,Count2,Count3,Count4,Count5);
    system("pause");
 
    return 0;

VC6.0对应汇编

.text:00401000 ; int __cdecl main(int argc, const char **argv, const char **envp)
.text:00401000 _main           proc near               ; CODE XREF: start+AF↓p
.text:00401000
.text:00401000 var_4           = dword ptr -4
.text:00401000 argc            = dword ptr  4
.text:00401000 argv            = dword ptr  8
.text:00401000 envp            = dword ptr  0Ch
.text:00401000
.text:00401000                 push    ecx
.text:00401001                 mov     eax, [esp+4+argc]
.text:00401005                 mov     [esp+4+var_4], eax
.text:00401009                 mov     [esp+4+argc], eax
.text:0040100D                 lea     eax, [esp+4+var_4]
.text:00401011                 push    eax
.text:00401012                 push    offset aD       ; "%d"
.text:00401017                 call    _scanf
.text:0040101C                 lea     ecx, [esp+0Ch+argc]
.text:00401020                 push    ecx
.text:00401021                 push    offset aD       ; "%d"
.text:00401026                 call    _scanf
.text:0040102B                 mov     eax, [esp+14h+argc]
.text:0040102F                 mov     ecx, [esp+14h+var_4]
.text:00401033                 lea     edx, ds:0[eax*8]
.text:0040103A                 sub     edx, eax
.text:0040103C                 add     edx, 5
.text:0040103F                 push    edx
.text:00401040                 lea     edx, [ecx+12]
.text:00401043                 push    edx
.text:00401044                 lea     edx, [eax+eax*2]
.text:00401047                 imul    eax, ecx
.text:0040104A                 lea     edx, [edx+edx*4]
.text:0040104D                 push    edx
.text:0040104E                 lea     edx, ds:0[ecx*4]
.text:00401055                 push    edx
.text:00401056                 push    eax
.text:00401057                 push    offset aDDDDD   ; "%d%d%d%d%d"
.text:0040105C                 call    _printf
.text:00401061                 push    offset aPause   ; "pause"
.text:00401066                 call    _system
.text:0040106B                 xor     eax, eax
.text:0040106D                 add     esp, 30h
.text:00401070                 retn
.text:00401070 _main           endp

vc6.0采用esp来访问局部变量

vs2019x86对应汇编

.text:00401080 sub_401080      proc near               ; CODE XREF: start-8D↓p
.text:00401080
.text:00401080 var_4           = dword ptr -4
.text:00401080 arg_0           = dword ptr  8
.text:00401080
.text:00401080                 push    ebp
.text:00401081                 mov     ebp, esp
.text:00401083                 push    ecx
.text:00401084                 mov     eax, [ebp+arg_0]
.text:00401087                 mov     [ebp+var_4], eax
.text:0040108A                 mov     [ebp+arg_0], eax
.text:0040108D                 lea     eax, [ebp+var_4]
.text:00401090                 push    eax
.text:00401091                 push    offset unk_41ECDC
.text:00401096                 call    sub_401050
.text:0040109B                 lea     eax, [ebp+arg_0]
.text:0040109E                 push    eax
.text:0040109F                 push    offset unk_41ECDC
.text:004010A4                 call    sub_401050
.text:004010A9                 mov     edx, [ebp+arg_0]
.text:004010AC                 mov     ecx, [ebp+var_4]
.text:004010AF                 lea     eax, ds:0[edx*8]
.text:004010B6                 sub     eax, edx
.text:004010B8                 add     eax, 5
.text:004010BB                 push    eax
.text:004010BC                 lea     eax, [ecx+0Ch]
.text:004010BF                 push    eax
.text:004010C0                 mov     eax, edx
.text:004010C2                 shl     eax, 4
.text:004010C5                 sub     eax, edx
.text:004010C7                 imul    edx, ecx
.text:004010CA                 push    eax
.text:004010CB                 lea     eax, ds:0[ecx*4]
.text:004010D2                 push    eax
.text:004010D3                 push    edx
.text:004010D4                 push    offset aDDDDD   ; "%d%d%d%d%d"
.text:004010D9                 call    sub_401020
.text:004010DE                 push    offset aPause   ; "pause"
.text:004010E3                 call    sub_4048C7
.text:004010E8                 add     esp, 2Ch
.text:004010EB                 xor     eax, eax
.text:004010ED                 mov     esp, ebp
.text:004010EF                 pop     ebp
.text:004010F0                 retn
.text:004010F0 sub_401080      endp

vs2019x86对应汇编 采用ebp来访问局部变量
vs2019x64对应汇编

.text:00000001400010D0 sub_1400010D0   proc near               ; CODE XREF: sub_140001268+107↓p
.text:00000001400010D0                                         ; DATA XREF: .pdata:000000014002700C↓o ...
.text:00000001400010D0
.text:00000001400010D0 var_18          = dword ptr -18h
.text:00000001400010D0 var_10          = dword ptr -10h
.text:00000001400010D0 arg_0           = dword ptr  8
.text:00000001400010D0 arg_10          = dword ptr  18h
.text:00000001400010D0
.text:00000001400010D0                 sub     rsp, 38h
.text:00000001400010D4                 mov     [rsp+38h+arg_10], ecx
.text:00000001400010D8                 lea     rdx, [rsp+38h+arg_10]
.text:00000001400010DD                 mov     [rsp+38h+arg_0], ecx
.text:00000001400010E1                 lea     rcx, unk_140022760
.text:00000001400010E8                 call    sub_140001080
.text:00000001400010ED                 lea     rdx, [rsp+38h+arg_0]
.text:00000001400010F2                 lea     rcx, unk_140022760
.text:00000001400010F9                 call    sub_140001080
.text:00000001400010FE                 mov     edx, [rsp+38h+arg_0]
.text:0000000140001102                 mov     eax, [rsp+38h+arg_10]
.text:0000000140001106                 imul    r10d, edx, 7
.text:000000014000110A                 imul    r9d, edx, 0Fh
.text:000000014000110E                 imul    edx, eax
.text:0000000140001111                 lea     ecx, [rax+0Ch]
.text:0000000140001114                 lea     r8d, ds:0[rax*4]
.text:000000014000111C                 add     r10d, 5
.text:0000000140001120                 mov     [rsp+38h+var_10], r10d
.text:0000000140001125                 mov     [rsp+38h+var_18], ecx
.text:0000000140001129                 lea     rcx, aDDDDD     ; "%d%d%d%d%d"
.text:0000000140001130                 call    sub_140001020
.text:0000000140001135                 lea     rcx, aPause     ; "pause"
.text:000000014000113C                 call    sub_140004584
.text:0000000140001141                 xor     eax, eax
.text:0000000140001143                 add     rsp, 38h
.text:0000000140001147                 retn
.text:0000000140001147 sub_1400010D0   endp

Vc6.0乘法核心代码反汇编x86

核心汇编对应

.text:0040102B                 mov     eax, [esp+14h+argc]  变量赋值
.text:0040102F                 mov     ecx, [esp+14h+var_4]
 
.text:00401033                 lea     edx, ds:0[eax*8]        lea指令计算
.text:0040103A                 sub     edx, eax                减法计算
.text:0040103C                 add     edx, 5                混合运算
 
.text:00401040                 lea     edx, [ecx+12]
.text:00401044                 lea     edx, [eax+eax*2]     3eax
.text:00401047                 imul    eax, ecx
.text:0040104A                 lea     edx, [edx+edx*4]     3eax + 3eax * 4 eax15
.text:0040104E                 lea     edx, ds:0[ecx*4]

高级代码与汇编对应

int NumberOne = argc;
int NumberTwo = argc;
 
.text:0040102B                 mov     eax, [esp+14h+argc]  变量赋值
.text:0040102F                 mov     ecx, [esp+14h+var_4]
 
int Count5 = NumberTwo * 7 + 5;      //混合运算
.text:00401033                 lea     edx, ds:0[eax*8]        lea指令计算
.text:0040103A                 sub     edx, eax                减法计算
.text:0040103C                 add     edx, 5                混合运算
 
int Count4 = NumberOne + 4 * 3;      //混合运算
.text:00401040                 lea     edx, [ecx+12]
 
int Count1 = NumberOne * NumberTwo;
.text:00401047                 imul    eax, ecx
 
int Count3 = NumberTwo * 15;
.text:00401044                 lea     edx, [eax+eax*2]     3eax
.text:0040104A                 lea     edx, [edx+edx*4]     3eax + 3eax * 4
 
int Count2 = NumberOne * 4;
.text:0040104E                 lea     edx, ds:0[ecx*4]

通过上面我们去掉流水线优化.人肉反汇编可以看出. 在乘法优化中. 大部分使用lea指令进行优化.特别是混合运算

lea指令对乘法的优化

首先我们根据上面汇编先讲解下lea指令对乘法的优化
高级代码

int Count3 = Number*15;

对应汇编

.text:00401044                 lea     edx, [eax+eax*2]     3eax
.text:0040104A                 lea     edx, [edx+edx*4]     3eax + 3eax * 4

在这里lea是计算机制而不是取地址第一行汇编我们产生了定式也就是eax* 2+eax等价于3eax
那么第二行汇编又依赖于第一行的输出。那么产生的定式也就是
3eax+3eax+4先算乘法得出3eax+12eax继续计算得出15eax
那么我们就可以还原高级代码为eax15,而eax我们也看到赋值了,也就是argc变量
所以最终代码就是argc
15我们的原来的代码应该是NumberTwo。这里也是被编译器给优化掉了。
所以乘法的优化一定要明白lea指令,包括我们的加法也会使用。一定要认识lea以及自己会换算

lea指令与sub指令的优化

lea指令其实我们已经知道了。sub指令优化

int Count5 = NumberTwo * 7 + 5;
 
.text:00401033                 lea     edx, ds:0[eax*8]        lea指令计算
.text:0040103A                 sub     edx, eax                减法计算
.text:0040103C                 add     edx, 5                混合运算

lea指令我们说了。在括号内是计算一个值。通过汇编我们可以得出的结果是8eax.而这里有使用sub来减去自己本身。等价于8eax - eax = 7eax最后加上5
eax我们知道是argc所以得出的反汇编为7eax+5<==>7argc+5argc+7+5
这里是首先使用lea换算成2的幂来进行优化的。然后减去自己本身。这样也比直接用IMUL或者MUL执行效率高

vs2019乘法核心代码反汇编x86

获取变量到寄存器用于计算
.text:004010A9                 mov     edx, [ebp+arg_0]
.text:004010AC                 mov     ecx, [ebp+var_4]
 
int Count5 = NumberTwo * 7 + 5;      //混合运算
.text:004010AF                 lea     eax, ds:0[edx*8]
.text:004010B6                 sub     eax, edx
.text:004010B8                 add     eax, 5
 
int Count4 = NumberOne + 4 * 3;   
.text:004010BC                 lea     eax, [ecx+0Ch]
 
int Count3 = NumberTwo * 15;
.text:004010C0                 mov     eax, edx
.text:004010C2                 shl     eax, 4
.text:004010C5                 sub     eax, edx
 
int Count1 = NumberOne * NumberTwo;
.text:004010C7                 imul    edx, ecx
 
int Count2 = NumberOne * 4;
.text:004010CB                 lea     eax, ds:0[ecx*4]  

观看反汇编出了NumberTwo *15 有所变化其余的全部同VC6.0一样。所以说在编译器优化上并不是越高级的编译器是最好的

SHL+Sub的指令优化

其实对于2的幂 编译器肯会选择使用以为来进行优化。这里也就出现了。也是先优化为2的幂减去自己本身

int Count3 = NumberTwo * 15;
.text:004010C0                 mov     eax, edx
.text:004010C2                 shl     eax, 4
.text:004010C5                 sub     eax, edx

SHL eax,4 = eax*4 = 16eax
然后使用sub 16eax-eax=15eax 那么就得出计算的值了

posted @ 2022-05-14 16:58  不会笑的孩子  阅读(125)  评论(0编辑  收藏  举报