zoukankan      html  css  js  c++  java
  • vc编译器对 除法的优化

    基本知识,7/2 和 6/2 在计算机中的商都为3.C语言的除法不等同于数学意义中的除法。

    C语言的除法。采用向零取整的方法。

    -______________0_______________+

    只有在除数为常量的情况下。编译器才会出现优化。

    1、除数为正数,2的幂的除法

    #include "stdafx.h"
    
    int main(int argc, char* argv[])
    {
      int iNum = argc;
      printf("%d
    ", iNum / 2);
      printf("%d
    ", iNum / 4);
      return 0;
    }

    对应Release版本的反汇编如下:

    push    esi
    mov     esi, dword ptr [esp+8]
    mov     eax, esi
    cdq
    sub     eax, edx
    sar     eax, 1
    push    eax
    push    test.00407030                    ;  ASCII "%d",CR,LF
    call    test.00401040
    mov     eax, esi
    add     esp, 8
    cdq
    and     edx, 3
    add     eax, edx
    sar     eax, 2
    push    eax
    push    test.00407030                    ;  ASCII "%d",CR,LF
    call    test.00401040
    add     esp, 8
    xor     eax, eax
    pop     esi
    retn

    是不是感觉很奇怪,怎么没有了除法指令。查阅CPU手册。除法的指令周期数。大得吓人。具体值得根据cpu型号。翻阅 手册。

    所以。编译器想尽办法。就是为了避免产生除法。提高效率。

    mov     esi, dword ptr [esp+8]
    mov     eax, esi
    cdq
    sub     eax, edx
    sar     eax, 1

    cdq 是把符号位扩展到 edx. 然后做加法。我们知道。对于被除数为正的情况,其值不变。除以2的幂。等于做 sar右移。

    对于被除数为负的情况。那么由于sar右移。等同于向下取整。由于C语言是向零取整。所以。必须想办法下整转上整。就满足了C语言的向零取整。

    于是公式来了。 a为被除数,n为2的幂.     (a + 2^n - 1)/2^n

    对于 iNum / 2 那就是等于  (iNum + 2 - 1)/2 。常量折叠。等于(iNum + 1)/2。除以2等于sar右移一位。

    那么就完美解决了除以2且无分歧的优化。指令的总周期。相对于div指令要减少很多。

    在按照公式推导 iNum /4 的情况。(iNum + 2^2 - 1) / 2^2 。常量折叠。等于(iNum + 3) / 4。除以4等于sar右移两位。

    对应的汇编代码如下。

    mov     eax, esi
    cdq
    and     edx, 3
    add     eax, edx
    sar     eax, 2

    推荐本书籍:《C++反汇编与逆向分析技术揭秘》。

    国内第一家从事软件逆向工程师培训的机构。http://www.51asm.com 强烈推荐!

  • 相关阅读:
    架构 框架 设计模式 --备用
    机器视觉项目开发之---织物疵点检测机器视觉系统 软件测试平台
    多媒体开发之--- live555 vs2010/vs2013下编译,使用,测试
    多媒体开发之--- h264 图像、帧、片、NALU
    多媒体开发之---H264—MP4格式及在MP4文件中提取H264的SPS、PPS及码流
    多媒体开发之---h264格式slice_header
    图像处理之基础---傅立叶c实现
    图像处理之基础---小波提取特征
    图像处理之基础---图像的特征简介
    嵌入式开发之工具---log file
  • 原文地址:https://www.cnblogs.com/ziolo/p/3511488.html
Copyright © 2011-2022 走看看