freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

对于加法运算的优化 | GCC
2022-10-26 13:13:34
所属地 江西省

编译器对于加法运算的优化

优化常见的几种方式

常量传播

将编译期间可计算出结果的变量转换为常量,减少变量的使用

#include <iostream>
int main()
{
    int nVar = 1;
    printf("nVar = %d \n",nVar);
}

对于上述代码,如果没有进行优化,那么处理的逻辑为:

WeChat Screenshot_20221012100902.png

会先将该值放入栈中,在 printf要输出它时,再将其拿到 esi中,通过 rsi传给 printf进行输出

进行 O1 优化以后

WeChat Screenshot_20221012101047.png

由于变量 nVar是一个在编译期间可以计算出结构的变量,所以将其替换为常量,直接用 1 来替代,printf要使用时直接传入 1 即可

O2 优化中在对变量的处理一致

WeChat Screenshot_20221012101142.png

常量折叠

在公式中出现多个常量进行计算的情况中,且编译器可以算出结果的情况下,在编译期间直接用计算结果替代

#include <iostream>

int main()
{
    int nNum = 1 + 8 * 7 - 10;
    printf("nNum = %d \n",nNum);

}

对于上述代码,如果没有进行优化,那么处理的逻辑为:

WeChat Screenshot_20221012102428.png

但其实这也进行了一定的优化,没有将常量的计算生成对应的计算指令,而是编译器直接将计算的结果传入栈中,接下来再从栈中拿值

进行 O1 优化以后

WeChat Screenshot_20221012103012.png

此时在上面的基础上,没有将结果放入栈中,由于后面 printf要使用该参数,直接传入 edx,后面通过 rdx直接传入 printf

复写传播

#include <iostream>

int main(int argc)
{
    int nNum = argc;
    printf("nNum = %d \n",nNum);
}

此时我们将 main函数的参数值赋给了 main中的变量 nNum

对于上述代码,如果没有进行优化,那么处理的逻辑为:

WeChat Screenshot_20221012111407.png

可以看到,为了将 edi中的的参数 1 (argc)放入到栈 nNum的位置,进行了很繁琐的操作

进行 O1 优化以后

WeChat Screenshot_20221012111747.png

直接删除掉了 nNum(因为之后没有对 nNum重新赋值) 用存在于 edi中刚刚传入的 argc值直接代替他就完事了

WeChat Screenshot_20221012111131.png
后面调用 printf时,由于其已经被传入了 edi,若直接通过 rdi传给 printf就完事了,非常的简便

具体在代码中的优化

#include <cstdio>
#include <iostream>

int main()
{
    int nVarOne = 0;
    int nVarTwo = 0;

    nVarOne = nVarOne + 1;

    nVarOne = 1 + 2;

    nVarOne = nVarOne + nVarTwo;

    printf("nVarOne = %d \n",nVarOne);

    return 0;
}

对于上述代码,如果没有进行优化,那么处理的逻辑为:

WeChat Screenshot_20221012093319.png

但还是在编译期间提前做了进行了简单的将常量的计算

进行 O1 优化以后

WeChat Screenshot_20221012104338.png

代码结构发生大变,处理的流程为:

  1. 常量替换变量,所以 nVarOne``nVarTwo开始都被直接替换为常量 0

  2. 接下来代码中对 nVarOne做了两次赋值操作,由于第二次赋值操作会覆盖第一次赋值的操作,所以直接去掉第一次赋值,第二次赋值为 3

  3. 再次用常量替换变量,由于 printf会使用到该参数,直接把 3 传入 edx,等待后续通过 rdx传入 printf即可

所以最终反映到汇编指令中,只有一条 mov edx,0x3实属省事啊。。。

# 反编译器原理
本文为 独立观点,未经允许不得转载,授权请联系FreeBuf客服小蜜蜂,微信:freebee2022
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者
文章目录