接上篇:《C++反汇编与逆向分析技术揭秘》--算术运算和赋值

printf("argc / 4 = %d\n", argc / 4);
printf("argc / 5 = %d\n", argc / 5);
printf("argc / 7 = %d\n", argc / 7);
printf("argc / -4 = %d\n", argc / -4);
printf("argc / -5 = %d\n", argc / -5);
printf("argc / -7 = %d\n", argc / -7);
printf("argc % 3 = %d\n", argc % 3);
printf("argc % 4 = %d\n", argc % 4);
printf("argc % -7 = %d\n", argc % -7);
printf("argc % -8 = %d\n", argc % -8);

  1. 01334B50 <ope | 55 | push ebp | operation.cpp:156
  2. 01334B51 | 8BEC | mov ebp,esp |
  3. 01334B53 | 56 | push esi | esi:__argc
  4. 01334B54 | 57 | push edi |
  5. 01334B55 | 8B7D 08 | mov edi,dword ptr ss:[ebp+0x8] | operation.cpp:162
  6. 01334B58 | 8BC7 | mov eax,edi |除数为2的幂时采用sar,算术右移,相当于向下取整,负数情况下需要调整
  7. 01334B5A | 99 | cdq |
  8. 01334B5B | 83E2 03 | and edx,0x3 |考虑被除数为负数时,要加上(2^n)-1,
  9. 01334B5E | 03C2 | add eax,edx |
  10. 01334B60 | C1F8 02 | sar eax,0x2 |
  11. 01334B63 | 50 | push eax |
  12. 01334B64 | 68 FC933A01 | push operation.13A93FC | 13A93FC:"argc / 4 = %d\n"
  13. 01334B69 | E8 02010000 | call <operation.printf> |
  14. 01334B6E | B8 67666666 | mov eax,0x66666667 |
  15. 01334B73 | F7EF | imul edi |
  16. 01334B75 | D1FA | sar edx,0x1 |
  17. 01334B77 | 8BC2 | mov eax,edx |>>>2**33/0x66666667 =4.99999999825377
  18. 01334B79 | C1E8 1F | shr eax,0x1F |
  19. 01334B7C | 03C2 | add eax,edx |
  20. 01334B7E | 50 | push eax |
  21. 01334B7F | 68 0C943A01 | push operation.13A940C | 13A940C:"argc / 5 = %d\n"
  22. 01334B84 | E8 E7000000 | call <operation.printf> |
  23. 01334B89 | B8 93244992 | mov eax,0x92492493 |
  24. 01334B8E | F7EF | imul edi |
  25. 01334B90 | 03D7 | add edx,edi |
  26. 01334B92 | C1FA 02 | sar edx,0x2 |
  27. 01334B95 | 8BF2 | mov esi,edx | >>> 2**34/0x92492493=6.999999997962732
  28. 01334B97 | C1EE 1F | shr esi,0x1F | esi:__argc
  29. 01334B9A | 03F2 | add esi,edx | esi:__argc
  30. 01334B9C | 56 | push esi | esi:__argc
  31. 01334B9D | 68 1C943A01 | push operation.13A941C | 13A941C:"argc / 7 = %d\n"
  32. 01334BA2 | E8 C9000000 | call <operation.printf> |
  33. 01334BA7 | 8BC7 | mov eax,edi |
  34. 01334BA9 | 99 | cdq |
  35. 01334BAA | 83E2 03 | and edx,0x3 |
  36. 01334BAD | 03C2 | add eax,edx |
  37. 01334BAF | C1F8 02 | sar eax,0x2 |
  38. 01334BB2 | F7D8 | neg eax |//多一步取反
  39. 01334BB4 | 50 | push eax |
  40. 01334BB5 | 68 2C943A01 | push operation.13A942C | 13A942C:"argc / -4 = %d\n"
  41. 01334BBA | E8 B1000000 | call <operation.printf> |
  42. 01334BBF | B8 99999999 | mov eax,0x99999999 |
  43. 01334BC4 | F7EF | imul edi |
  44. 01334BC6 | D1FA | sar edx,0x1 |
  45. 01334BC8 | 8BC2 | mov eax,edx |>>> 2**33/(2**32-0x99999999)=4.99999999825377
  46. 01334BCA | C1E8 1F | shr eax,0x1F |
  47. 01334BCD | 03C2 | add eax,edx |
  48. 01334BCF | 50 | push eax |
  49. 01334BD0 | 68 3C943A01 | push operation.13A943C | 13A943C:"argc / -5 = %d\n"
  50. 01334BD5 | E8 96000000 | call <operation.printf> |
  51. 01334BDA | B8 6DDBB66D | mov eax,0x6DB6DB6D |
  52. 01334BDF | F7EF | imul edi |
  53. 01334BE1 | 2BD7 | sub edx,edi |
  54. 01334BE3 | C1FA 02 | sar edx,0x2 |
  55. 01334BE6 | 8BC2 | mov eax,edx |>>> 2**34/(2**32-0x6db6db6d)=6.999999997962732
  56. 01334BE8 | C1E8 1F | shr eax,0x1F |
  57. 01334BEB | 03C2 | add eax,edx |
  58. 01334BED | 50 | push eax |
  59. 01334BEE | 68 4C943A01 | push operation.13A944C | 13A944C:"argc / -7 = %d\n"
  60. 01334BF3 | E8 78000000 | call <operation.printf> |
  61. 01334BF8 | B8 56555555 | mov eax,0x55555556 |
  62. 01334BFD | 8BCF | mov ecx,edi |
  63. 01334BFF | F7EF | imul edi |
  64. 01334C01 | 8BC2 | mov eax,edx |>>> 2**32/0x55555556=2.999999998603016
  65. 01334C03 | C1E8 1F | shr eax,0x1F |
  66. 01334C06 | 03C2 | add eax,edx |
  67. 01334C08 | 8D0440 | lea eax,dword ptr ds:[eax+eax*2] |
  68. 01334C0B | 2BC8 | sub ecx,eax |
  69. 01334C0D | 51 | push ecx |
  70. 01334C0E | 68 5C943A01 | push operation.13A945C | 13A945C:"argc % 3 = %d\n"
  71. 01334C13 | E8 58000000 | call <operation.printf> |
  72. 01334C18 | 8BC7 | mov eax,edi |
  73. 01334C1A | 25 03000080 | and eax,0x80000003 |对2N次方数取余使用and操作,x%2^N 使用位运算x & (2^N - 1)代替
  74. 01334C1F | 79 05 | jns operation.1334C26 |
  75. 01334C21 | 48 | dec eax |减一
  76. 01334C22 | 83C8 FC | or eax,0xFFFFFFFC |相当于取反
  77. 01334C25 | 40 | inc eax |加一
  78. 01334C26 | 50 | push eax |
  79. 01334C27 | 68 6C943A01 | push operation.13A946C | 13A946C:"argc % 4 = %d\n"
  80. 01334C2C | E8 3F000000 | call <operation.printf> |
  81. 01334C31 | 83C4 40 | add esp,0x40 |
  82. 01334C34 | 8D0CF5 00000000 | lea ecx,dword ptr ds:[esi*8] |
  83. 01334C3B | 2BCE | sub ecx,esi | esi:__argc
  84. 01334C3D | 8BC7 | mov eax,edi |
  85. 01334C3F | 2BC1 | sub eax,ecx |
  86. 01334C41 | 50 | push eax |
  87. 01334C42 | 68 7C943A01 | push operation.13A947C | 13A947C:"argc % -7 = %d\n"
  88. 01334C47 | E8 24000000 | call <operation.printf> |
  89. 01334C4C | 81E7 07000080 | and edi,0x80000007 |
  90. 01334C52 | 79 05 | jns operation.1334C59 |
  91. 01334C54 | 4F | dec edi |减一
  92. 01334C55 | 83CF F8 | or edi,0xFFFFFFF8 |
  93. 01334C58 | 47 | inc edi |
  94. 01334C59 | 57 | push edi |
  95. 01334C5A | 68 8C943A01 | push operation.13A948C | 13A948C:"argc % -8 = %d\n"
  96. 01334C5F | E8 0C000000 | call <operation.printf> |
  97. 01334C64 | 83C4 10 | add esp,0x10 |
  98. 01334C67 | 33C0 | xor eax,eax | operation.cpp:167
  99. 01334C69 | 5F | pop edi |
  100. 01334C6A | 5E | pop esi | esi:__argc
  101. 01334C6B | 5D | pop ebp | operation.cpp:168
  102. 01334C6C | C3 | ret |
  1. 除数为正数时:
  2. 除数为2的幂时
  3. mov eax,edi
  4. cdq
  5. and edx,0x3
  6. add eax,edx
  7. sar eax,0x2 /4
  8.  
  9. 除数不为2的幂时:
  10. magicnumber<=0x7fffffff时:
  11. mov eax,0x66666667 |
  12. imul edi |
  13. sar edx,0x1 |
  14. mov eax,edx |>>>2**33/0x66666667 =4.99999999825377
  15. shr eax,0x1F |
  16. add eax,edx
  17.  
  18. magicnumber>0x7fffffff时:
  19. mov eax,0x92492493 |
  20. imul edi |
  21. add edx,edi |
  22. sar edx,0x2 |
  23. mov esi,edx | >>> 2**34/0x92492493=6.999999997962732
  24. shr esi,0x1F
  25. add esi,edx
  26.  
  27. 除数为负数时:
  28. 除数为2的幂时
  29. mov eax,edi
  30. cdq
  31. and edx,0x3
  32. add eax,edx
  33. sar eax,0x2
  34. neg eax /-4
  35.  
  36. 除数不为2的幂时
  37. magicnumber<=0x7fffffff时:
  38. mov eax,0x6DB6DB6D |
  39. imul edi |
  40. sub edx,edi |
  41. sar edx,0x2 |
  42. mov eax,edx |>>> 2**34/(2**32-0x6db6db6d)=6.999999997962732 -7
  43. shr eax,0x1F |
  44. add eax,edx
  45.  
  46. magicnumber>0x7fffffff时:
  47. mov eax,0x99999999 |
  48. imul edi |
  49. sar edx,0x1 |
  50. mov eax,edx |>>> 2**33/(2**32-0x99999999)=4.99999999825377 -5
  51. shr eax,0x1F |
  52. add eax,edx
  53.  
  54. 模运算
  55. 模数为2的幂时
  56. mov eax,edi |%4
  57. and eax,0x80000003 |对2N次方数取余使用and操作,x%2^N 使用位运算x & (2^N - 1)代替
  58. jns operation.1334C26 |
  59. dec eax |减一
  60. or eax,0xFFFFFFFC |相当于取反
  61. inc eax |加一
  62.  
  63. 模数不为2的幂时
  64. mov eax,0x55555556 |%3
  65. mov ecx,edi |
  66. imul edi |
  67. mov eax,edx |>>> 2**32/0x55555556=2.999999998603016
  68. shr eax,0x1F |
  69. add eax,edx |
  70. lea eax,dword ptr ds:[eax+eax*2] |
  71. sub ecx,eax |
  72. push ecx
  73. 模数为负时实现相同

除数为正数时,使用公式o=2^n/c,将MagicNumber作为c值代入公式求解常量除数o,即可恢复除法原型

特殊情况:

除数为负数时:统计右移的总次数以确定公式中的n值,然后使用公式|o|=(2^n) / (2^32 -c)。,将MagicNumber作为c值代入公式求解常量除数lol,即可恢复除法原型。

模运算:对两个变量取模或者对非2的幂取模,可直接使用div或idiv指令完成,余数在dx或者是edx中。

对2的k次方取余,余数的值只需取得被除数二进制数值中的最后k位的值即可,负数则还需在k位之前补1,

x % 2^N  使用 x & (2^N - 1)代替

对于为什么要这样优化呢?这其中涉及到一些数学知识,有兴趣的可以继续深入研究下去。

其实能够总结出各种优化的特征,遇到时可以还原操作便达到了我们逆向分析的目的。

c++ 反汇编 除法优化的更多相关文章

  1. 编译器是如何实现32位整型的常量整数除法优化的?[C/C++]

    引子 在我之前的一篇文章[ ThoughtWorks代码挑战——FizzBuzzWhizz游戏 通用高速版(C/C++ & C#) ]里曾经提到过编译器在处理除数为常数的除法时,是有优化的,今 ...

  2. 【转】C/C++除法实现方式及负数取模详解

    原帖:http://blog.csdn.net/sonydvd123/article/details/8245057 一.下面的题目你能全做对吗? 1.7/4=? 2.7/(-4)=? 3.7%4=? ...

  3. C/C++除法实现方式及负数取模详解

    一.下面的题目你能全做对吗? 1.7/4=? 2.7/(-4)=? 3.7%4=? 4.7%(-4)=? 5.(-7)/4=? 6.(-7)%4=? 7.(-7)/(unsigned)4=? 答案: ...

  4. 《C++反汇编与逆向分析技术揭秘》--算术运算和赋值

    一.加法 1.Debug下: 14: int nVarOne0 = 1 + 5 - 3 * 6;//编译时计算得到结果 00C0550E C7 45 F8 F4 FF FF FF mov dword ...

  5. RapidJSON 代码剖析(四):优化 Grisu

    我曾经在知乎的一个答案里谈及到 V8 引擎里实现了 Grisu 算法,我先引用该文的内容简单介绍 Grisu.然后,再谈及 RapidJSON 对它做了的几个底层优化. (配图中的<Grisù& ...

  6. C++负数取模

    预习: r=余数 a=被除数 b=除数 c=商 a/b=c........r r=a-(a/b)*b 一.下面的题目你能全做对吗?1.7/4=?2.7/(-4)=?3.7%4=?4.7%(-4)=?5 ...

  7. CSAPP 第二章随笔

    类型转换问题 (1)int -> short 二进制位高位截断,低位保持不变 (2)同类型 unsign -> sign 记住二进制位是不变的 (3)P101页提到的编译器乘法优化问题,一 ...

  8. Day4下午解题报告

    预计分数:30+30+0=60 实际分数:30+30+10=70 稳有个毛线用,,又拿不出成绩来,, T1 https://www.luogu.org/problem/show?pid=T15626 ...

  9. 万万没想到,除了香农计划,Python3.11竟还有这么多性能提升!

    众所周知,Python 3.11 版本带来了较大的性能提升,但是,它具体在哪些方面上得到了优化呢?除了著名的"香农计划"外,它还包含哪些与性能相关的优化呢?本文将带你一探究竟! 作 ...

随机推荐

  1. windows信息收集

      导语:介绍 特权升级总是被归结为适当的枚举.但要完成适当的枚举,你需要知道要检查和查找的内容.这通常需要伴随着经验的丰富而对系统非常熟悉.起初特权升级看起来像是一项艰巨的任务,但过了一段时间,你就 ...

  2. js & document.execCommand

    js & document.execCommand click copy document.execCommand 已废弃 过时的 此功能已过时.尽管它可能在某些浏览器中仍然可以使用,但不建议 ...

  3. CSS margin collapsing All In One

    CSS margin collapsing All In One margin collapsing margin 塌陷 / margin 合并 会出现 margin collapsing 的 3 种 ...

  4. UML online tools

    UML online tools UML https://www.diagrams.net/assets/svg/home-dia1.svg refs https://www.diagrams.net ...

  5. Top 10 JavaScript errors

    Top 10 JavaScript errors javascript errors https://rollbar.com/blog/tags/top-errors https://rollbar. ...

  6. toString()[0]

    toString()[0] https://prepack.io/ x = `A` //"A" x.toString()[0] //"A" x.toString ...

  7. Baccarat凭什么能成为DeFi后时代火爆新趋势?

    在各币种经历涨涨跌跌以后,DeFi后时代已然来临.那么,当前DeFi市场中哪个项目更被市场生态建设者看好呢?毫无疑问,Baccarat会成为最被看好的DeFi项目. Baccarat采用了独特的共识算 ...

  8. Mosquitto

    mosquitto可连接远程服务器及本地服务器. mosquitto可在一个节点内建立一个连接用于收发,也可在一个节点内建立多个连接用于收发.建立一个连接用于收发时,会有初始部分帧的延迟.(可能由于内 ...

  9. MySQL 导入外部数据

    手工为数据库录入数据: 1 -- 使用数据库 2 use test; 3 4 -- 创建fruits数据表 5 create table fruits( 6 f_id char(10) not nul ...

  10. 6. vue组件详解(一)

    主要内容: 1. 组件的基本使用 2. 全局组件和局部组件 3. 父组件和子组件 4. 组件语法糖的写法 5. 组件data关联的写法 6. 父子组件的通信 组件系统是 Vue 的一个重要概念,因为它 ...