• <转>VC编译的除法的一段汇编代码解释


    int main(int argc, char* argv[])
    {
          int i;
          scanf("%d", &i);
          int j = i / 2;
          printf("%d", j);
    return 0;
    }

    编译后:

    10:         int j = i / 2;
    00401039     mov           eax,dword ptr [ebp-4]
    0040103C     cdq
    0040103D     sub           eax,edx
    0040103F     sar           eax,1
    00401041     mov           dword ptr [ebp-8],eax

    即:M / 2 为

    mov           eax,M
    cdq
    sub           eax,edx
    sar           eax,1

    这是为什么呢?思考了一段时间后,我给出这样的回答,不知道够不够严谨

    M与-M在计算机中的表示是互为补码的

    即 [-M]=[M]补

    因此 ,[M]/2分2个情况考虑
    1,M为正数,正数的除法就是算术右移一位
       mov eax , M
       sar eax,1    //右移1位,即除以2

    2,M为负数,则[M]/2= [ [-M]/2 ]补   = [-[[M]补/2] ]补

    M为负数,所以,上面的计算过程是:
    M取反加1,算术右移1位,再取反加1

    设M为1字节
    M取反加1可以表示成   (FF-M+1)

    因此,上面的计算过程转化为
    FF - ( (FF-M+1)/2 ) +1 = FF-(FF/2) + (M+1)/2  

    这里的 /2意思为向右带符号移一位,而FF 算术右移1位还是FF
    所以可以简化为

    (M+1)/2   

    注意,这里的M是负数

    所以:
    mov eax, M
    sub eax,-1   //减-1就是+1
    sar eax,1   //右移1位,除以2

    然后解释一下 CDQ指令就可以了
    当EAX >=0 ,CDQ结果   EDX=0
    当EAX < 0 ,CDQ结果   EDX=-1

    因此,M/2可以写成
    mov eax, M
    cdq            //扩展符号位,到EDX
    sub eax,edx    //EAX>0 ,则EAX - 0 ;EAX<0 ,则EAX - (-1)
    sar eax,1      //右移2位

    本人新博客网址为:http://www.hizds.com
    本博客注有“转”字样的为转载文章,其余为本人原创文章,转载请务必注明出处或保存此段。c++/lua/windows逆向交流群:69148232
  • 相关阅读:
    iOS构建流畅的交互界面--卡顿产生的原因
    iOS-tableViewCell重用机制带来的问题及解决
    完全背包
    poj1384
    RunLoop的使用--AFNetworking的网络线程实现+tableView延迟加载图片+App崩溃后立即重启
    poj 3624
    01背包
    poj1416
    java中 File文件常用操作方法的汇总
    线程中涉及到的知识点总结
  • 原文地址:https://www.cnblogs.com/zhangdongsheng/p/2559074.html
Copyright © 2020-2023  润新知