学逆向论坛

找回密码
立即注册

只需一步,快速开始

发新帖

2万

积分

41

好友

1171

主题
发表于 2020-9-9 21:21:47 | 查看: 10334| 回复: 2
目录
  • 代码还原反汇编之除法除数为非2的幂
  •                  系列文章
  •          一丶数学知识补充
  •                  1.1 简介
  •                  1.2 分数
  •                          1.2.1分数加法
  •                          1.2.1分数乘法
  •          二丶除法优化之有符号非2的幂优化
  •                  2.1高级代码与反汇编
  •                  2.2 除法非2的幂还原
  •                  2.3 除数为非2的幂的优化与原理
  •                  2.4 总结除法还原公式
  •          三丶除法优化之无符号非2的幂优化
  •                  3.1 无符号非2的幂除数为正代码反汇编还原
  •                  3.2 无符号非2的幂除数为负数反汇编代码还原
  •                  3.3 特殊汇编
  •          四丶为什么学习除法优化
  •                  4.1 为什么学习除法优化
  •          五丶高级Vs编译器与linux下的gcc优化
  •                  5.1 vs2019 x86 有符号非2的幂优化
  •                  5.2 vs2019 x64有符号非2的幂优化
  •                  5.3 linux gcc x86 有符号非2的幂
  •                  5.4 其它同理自己建立项目研究
代码还原反汇编之除法除数为非2的幂系列文章  反汇编技术之熟悉IDA工具
  反汇编逆向技术之寻找Main入口点
  反汇编代码还原之优化方式
  反汇编代码还原之加减乘
  反汇编代码还原之除法为2的幂
一丶数学知识补充1.1 简介  ​    除法在非2的幂优化上,采用的是除法转变为乘法 的形式. 在学习这方面知识的时候我们先了解下简单的数学知识
  也有助于我们能看懂公式
1.2 分数1.2.1分数加法
  •   分数加法
      相同分母加法 分子想加 分母不变 例如下

    [原创]#30天写作挑战#反汇编代码还原之除数为非2的幂

    [原创]#30天写作挑战#反汇编代码还原之除数为非2的幂

  不同分母想加 如果是不同分母想加你就要进行寻找最小公分母
  公分母指的是. 当两个或者以上的分数有相同的分母 那么他们便是公分母 注意这里是公分母.而不是最小公分母 最小公分母指的是两个分数以上,最小的公分母
  •   最小公分母的寻找
      最小公分母我们可以列出 分母的倍数 如果有两个分数那么都列出分母的倍数.找出相同的倍数.然后让其等价即可.
      例如:

    [原创]#30天写作挑战#反汇编代码还原之除数为非2的幂

    [原创]#30天写作挑战#反汇编代码还原之除数为非2的幂
      列出3的倍数: 3 6 9 12 15 .....
      列出6的倍数: 6 12 18 24 ....
      我们发现最小公倍数都是6. 所以我们的分子分母都*2转为为相同分母然后进行想加即可

    [原创]#30天写作挑战#反汇编代码还原之除数为非2的幂

    [原创]#30天写作挑战#反汇编代码还原之除数为非2的幂

1.2.1分数乘法
  •   分数乘法
    **分数*分数 是分子 * 分子 分母 * 分母**  

  如下:
  ​   

[原创]#30天写作挑战#反汇编代码还原之除数为非2的幂

[原创]#30天写作挑战#反汇编代码还原之除数为非2的幂

  口诀: 乘分数 没难度 上乘上 下乘下 再约分
  •   整数相乘
      如果一个整数 * 一个分数.那么这个分数就可以看做是分子,而分母就是1
      例子:

    [原创]#30天写作挑战#反汇编代码还原之除数为非2的幂

    [原创]#30天写作挑战#反汇编代码还原之除数为非2的幂
      至于约分.可以寻找最小公因数.跟公倍数相反.公倍数是找出相乘 公因数就是找出可以分子/分母的数. 都去除同一个数
二丶除法优化之有符号非2的幂优化2.1高级代码与反汇编
int main(int argc, char* argv[])  {
  /*
  除法
  */
  int NumberOne = 0;
  int NumberTwo = 0;
  scanf("%d",&NumberOne);
  scanf("%d",&NumberTwo);
  int Count1 = NumberOne / 3;
  int Count2 = NumberTwo / 5;
  int Count3 = NumberTwo / 6;
  int Count4 = NumberTwo / 9;
  printf("%d%d%d%d%d",Count4,Count3,Count2,Count1);
  system("pause");
  return 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                 xor     eax, eax
  .text:00401005                 mov     [esp+8+var_8], eax
  .text:00401009                 mov     [esp+8+var_4], eax
  .text:0040100D                 lea     eax, [esp+8+var_8]
  .text:00401011                 push    eax
  .text:00401012                 push    offset aD       ; "%d"
  .text:00401017                 call    _scanf
  .text:0040101C                 lea     ecx, [esp+10h+var_4]
  .text:00401020                 push    ecx
  .text:00401021                 push    offset aD       ; "%d"
  .text:00401026                 call    _scanf
  //第一段
  .text:0040102B                 mov     ecx, [esp+18h+var_8]
  .text:0040102F                 mov     eax, 55555556h
  .text:00401034                 imul    ecx
  .text:0040103A                 mov     eax, edx
  .text:0040103C                 shr     eax, 1Fh
  .text:0040103F                 add     edx, eax
  //第二段
  .text:00401036                 mov     ecx, [esp+18h+var_4]
  .text:00401041                 mov     eax, 66666667h
  .text:00401047                 imul    ecx
  .text:00401049                 sar     edx, 1
  .text:0040104B                 mov     eax, edx
  .text:0040104D                 shr     eax, 1Fh
  .text:00401050                 add     edx, eax
  .text:00401057                 push    edx                //这里原先是流水线优化给提到上边来了
  //第三段
  .text:00401052                 mov     eax, 2AAAAAABh
  .text:00401058                 imul    ecx
  .text:0040105A                 mov     eax, edx
  .text:0040105C                 shr     eax, 1Fh
  .text:0040105F                 add     edx, eax
  .text:00401066                 push    edx                //同上流水线优化
  //第四段
  .text:00401061                 mov     eax, 38E38E39h
  .text:00401067                 imul    ecx
  .text:00401069                 sar     edx, 1
  .text:0040106B                 mov     ecx, edx
  .text:0040106D                 shr     ecx, 1Fh
  .text:00401070                 add     edx, ecx
  .text:00401072                 push    edx
  .text:00401073                 push    offset aDDDDD   ; "%d%d%d%d%d"
  .text:00401078                 call    _printf
  .text:0040107D                 push    offset aPause   ; "pause"
  .text:00401082                 call    _system
  .text:00401087                 xor     eax, eax
  .text:00401089                 add     esp, 30h
  .text:0040108C                 retn
  .text:0040108C _main           endp
  

2.2 除法非2的幂还原  ​    乍一看上面汇编代码.除法怎么变为了这样.为什么又有乘法又有除法.还有调整等. 那么这里就着重讲解一下.
  如果想要直接还原.那么我们把代码定式提取出来 直接进行还原
  •   代码定式
    mov     ecx, 被除数  mov     eax, M值
      imul    ecx
      sar     edx, n
      mov     eax, edx
      shr     eax, 1Fh
      add     edx, eax
      push    edx
      

      根据汇编我们只需要看三个点即可. 并且得出三个点的公式得原理

    [原创]#30天写作挑战#反汇编代码还原之除数为非2的幂

    [原创]#30天写作挑战#反汇编代码还原之除数为非2的幂
      其中M是编译器计算出来了. ecx是被除数. 这里sar n值.直接操作的是edx. 这里其实是除法转变为了乘法 而如果除法转变为乘法 那么在32位年代下.两个数相乘 32的值是不会放下的. 所以我们这里其实使用的是 edx,eax 来代表乘法的结果 然后我们直接操作了乘积的高位 这里右移1 等价于是 除以

    [原创]#30天写作挑战#反汇编代码还原之除数为非2的幂

    [原创]#30天写作挑战#反汇编代码还原之除数为非2的幂

  那么我们还原的时候直接记住死公式就可以.  

[原创]#30天写作挑战#反汇编代码还原之除数为非2的幂

[原创]#30天写作挑战#反汇编代码还原之除数为非2的幂

  直接统计n的取值. 然后用 2的32次方 + n即可. 因为乘积的低位时代表2^32次方.这里直接是对乘积高位做操作.所以我们需要加上低位的32次方的值
  例子还原
  .text:0040102B                 mov     ecx, [esp+18h+var_8]  .text:0040102F                 mov     eax, 55555556h
  .text:00401034                 imul    ecx
  .text:0040103A                 mov     eax, edx                //这里直接使用的是edx.而没有对edx做修改.所以我们的n值就是0
  .text:0040103C                 shr     eax, 1Fh
  .text:0040103F                 add     edx, eax
  

  我们套用公式

[原创]#30天写作挑战#反汇编代码还原之除数为非2的幂

[原创]#30天写作挑战#反汇编代码还原之除数为非2的幂
  2.99直接向上取整 = 3. 所以这里我们就寻得被除数为3
2.3 除数为非2的幂的优化与原理  首先先看我们的汇编
  .text:00401061                 mov     eax, 38E38E39h  .text:00401067                 imul    ecx
  .text:00401069                 sar     edx, 1
  .text:0040106B                 mov     ecx, edx
  .text:0040106D                 shr     ecx, 1Fh
  .text:00401070                 add     edx, ecx
  .text:00401072                 push    edx
  

  这里我们汇编分为两部分.上边是可以直接套用公式还原. 而下方其实是获取符号位.调整一下符号位.
  shr 逻辑右移. 最高位以0填充. 右移31(1F)位 取得符号位 然后这里有一个加法.其实这个加法也是套路.跟我们之前讲解的无分支优化差不多. 如果结果是正数. 那么 add edx,eax 就是加0 等于什么都不干. 如果是结果是负数 那么我们就需要除法的商做调整.做加1调整.
  •   除法转化为乘法的原理
      如果想要了解为什么非2的幂代码会变成上面的代码.那么我们就要理解下原理
      设 a = 被除数  b = 除数(是一个常量值)
      那么就会有以下公式

    [原创]#30天写作挑战#反汇编代码还原之除数为非2的幂

    [原创]#30天写作挑战#反汇编代码还原之除数为非2的幂
      这个就是我们上面所了解的分数相关知识.
      看最后的公式

    [原创]#30天写作挑战#反汇编代码还原之除数为非2的幂

    [原创]#30天写作挑战#反汇编代码还原之除数为非2的幂
      其中 2n/b这个是可以在编译期中计算出来的. VC++6.0 或者VS2019 在编译 期间n的取值是大于32的.所以是可以算出来的.
      所以我们的公式可以变为如下 在这里我们把编译器可以计算出来的值记做C. 那么可以得出以下公式

    [原创]#30天写作挑战#反汇编代码还原之除数为非2的幂

    [原创]#30天写作挑战#反汇编代码还原之除数为非2的幂
      最终简化为就是(a * c) >> n 而反过头来看我们的汇编代码
    .text:00401061                 mov     eax, 38E38E39h  .text:00401067                 imul    ecx
      .text:00401069                 sar     edx, 1
      

      列出公式
      ecx = 被除数
      eax  = M  等价于 2n/b的值.
      ecx eax / 2^33   这条公式就正好对应着我们除法转变为乘法的原理 和我们上面的公式一样.  (a c) >> n
      所以我们解方程即可.  2^n / b = M值.  那么 2^n / M  = b  b就是我们的要求的除数. 所以得出我们的除数
      除法还原公式为:
2.4 总结除法还原公式
  •   除法的还原公式

    [原创]#30天写作挑战#反汇编代码还原之除数为非2的幂

    [原创]#30天写作挑战#反汇编代码还原之除数为非2的幂
      这里的C其实就是2^n/b 在汇编中我们也设为M.所以也可以写为如下

    [原创]#30天写作挑战#反汇编代码还原之除数为非2的幂

    [原创]#30天写作挑战#反汇编代码还原之除数为非2的幂
  •   除法转变为乘法的公式

    [原创]#30天写作挑战#反汇编代码还原之除数为非2的幂

    [原创]#30天写作挑战#反汇编代码还原之除数为非2的幂
      转变为如下

    [原创]#30天写作挑战#反汇编代码还原之除数为非2的幂

    [原创]#30天写作挑战#反汇编代码还原之除数为非2的幂
      继续转变

    [原创]#30天写作挑战#反汇编代码还原之除数为非2的幂

    [原创]#30天写作挑战#反汇编代码还原之除数为非2的幂
      最终转变

    [原创]#30天写作挑战#反汇编代码还原之除数为非2的幂

    [原创]#30天写作挑战#反汇编代码还原之除数为非2的幂

  对于上面我们记住代码定式也可以进行还原.当然熟悉除法转变为乘法的原理更好.
  高级代码看其特征我们发现其实是一样的. 都可以使用 除法转乘法的公式来进行还原
  除法还原公式其实就是解方程了.解开就可以得到被除数
三丶除法优化之无符号非2的幂优化  高级代码
int main(int argc, char* argv[])  {
  /*
  除法
  */
  unsigned int NumberOne = 0;
  unsigned int NumberTwo = 0;
  scanf("%u",&NumberOne);
  scanf("%u",&NumberTwo);
  unsigned int Count1 = NumberOne / 3;
  unsigned int Count2 = NumberTwo / 5;
  unsigned int Count3 = NumberTwo / 6;
  unsigned int Count4 = NumberTwo / 9;
  printf("%d%d%d%d%d",Count4,Count3,Count2,Count1);
  system("pause");
  return 0;
  }
  

  汇编代码
.text:00401005                 mov     [esp+8+var_8], eax  .text:00401009                 mov     [esp+8+var_4], eax
  .text:0040102B                 mov     eax, 2863311531
  .text:00401030                 mov     ecx, [esp+18h+var_4]
  .text:00401034                 mul     [esp+18h+var_8]
  .text:00401038                 shr     edx, 1
  .text:0040103A                 mov     eax, 3435973837
  .text:0040103F                 push    edx
  .text:00401040                 mul     ecx
  .text:00401042                 shr     edx, 2
  .text:00401045                 mov     eax, 0AAAAAAABh
  .text:0040104A                 push    edx
  .text:0040104B                 mul     ecx
  .text:0040104D                 shr     edx, 2
  .text:00401050                 mov     eax, 38E38E39h
  .text:00401055                 push    edx
  .text:00401056                 mul     ecx
  .text:00401058                 shr     edx, 1
  .text:0040105A                 push    edx
  

3.1 无符号非2的幂除数为正代码反汇编还原  看如上代码.根据除法转为乘法公式 (a * b) >> n .我们可以求出
  2^n / b = M  2^n/M = b(除数常量)
  这里只不过是换成了无符号而已.
  还原公式还是同上
  如:
.text:0040102B                 mov     eax, 2863311531  .text:00401030                 mov     ecx, [esp+18h+var_4]
  .text:00401034                 mul     [esp+18h+var_8]
  .text:00401038                 shr     edx, 1
  

  取N 值 = 1 取M值 = 2863311531(注意这里IDA我按了下H转为10进制来查看.这样方便我们用科学计算器来进行运算)
  操作的是edx.所以
被除数 = 2^33  除数 = M
  求除数公式 =  2^n/M = b
  代入公式
  2^33 / 2863311531 = 2.999999999 向上取整 = 3 所以得出这里的除数为3. ecx = var4
  所以这里反汇编为高级代码为 var_4 / 3
  

3.2 无符号非2的幂除数为负数反汇编代码还原  高级代码如下
int main(int argc, char* argv[])  {
  /*
  除法
  */
  unsigned int NumberOne = 0;
  unsigned int NumberTwo = 0;
  scanf("%u",&NumberOne);
  scanf("%u",&NumberTwo);
  unsigned int Count1 = NumberOne / -3;
  unsigned int Count2 = NumberTwo / -5;
  unsigned int Count3 = NumberTwo / -6;
  unsigned int Count4 = NumberTwo / -9;
  printf("%d%d%d%d%d",Count4,Count3,Count2,Count1);
  system("pause");
  return 0;
  }
  

  核心代码反汇编 代码段
.text:00401005                 mov     [esp+8+var_8], eax  .text:00401009                 mov     [esp+8+var_4], eax
  /-3
  .text:0040102B                 mov     eax, 40000001h
  .text:00401030                 mov     ecx, [esp+18h+var_4]
  .text:00401034                 mul     [esp+18h+var_8]
  .text:00401038                 shr     edx, 1Eh
  .text:00401040                 push    edx
  /-5
  .text:0040103B                 mov     eax, 80000003h
  .text:00401041                 mul     ecx
  .text:00401043                 shr     edx, 1Fh
  .text:0040104B                 push    edx
  /-6
  .text:00401046                 mov     eax, 7
  .text:0040104C                 mul     ecx
  .text:0040104E                 mov     eax, ecx
  .text:00401050                 sub     eax, edx
  .text:00401052                 shr     eax, 1
  .text:00401054                 add     eax, edx
  .text:00401056                 shr     eax, 1Fh
  .text:00401059                 push    eax
  /-9
  .text:0040105A                 mov     eax, 80000005h
  .text:0040105F                 mul     ecx
  .text:00401061                 shr     edx, 1Fh
  .text:00401064                 push    edx
  

  •   代码定式
      根据上面反汇编代码.我们看到三个地方 有我们的 疑似 (a * c) >> n的代码
      也就是除法转变为乘法的公式
      我们随便取出一处代入公式进行还原
      设 M = 40000001h   =10进制的 1073741825
      设 n = 1E                    = 10进制的 30
      那么代入我们的还原公式为:

    [原创]#30天写作挑战#反汇编代码还原之除数为非2的幂

    [原创]#30天写作挑战#反汇编代码还原之除数为非2的幂

  以计算器的科学计算计算出的数值是4294967292(10进制)
  那么我们将这个数复制到以程序员计算的计算器中.(复制到Dec 10进制输入) 可以看到是一个负数

[原创]#30天写作挑战#反汇编代码还原之除数为非2的幂

[原创]#30天写作挑战#反汇编代码还原之除数为非2的幂
  注意输入的时候以QWORD输入.然后再点击一下变成DWORD则可以看到表达为-4

[原创]#30天写作挑战#反汇编代码还原之除数为非2的幂

[原创]#30天写作挑战#反汇编代码还原之除数为非2的幂
  此时直接对其NOT取反则可以得到原始的被除数. 但是这个被除数常量是负数

[原创]#30天写作挑战#反汇编代码还原之除数为非2的幂

[原创]#30天写作挑战#反汇编代码还原之除数为非2的幂
  你也可以让此值做+1调整 变为4294967293 那么就得出了数直接就是-3 可以很明确的知道我们的被除数是-3
3.3 特殊汇编  看到上面有一段代码.我们特别不理解 为什么/-6汇编变了
  这些后面有专题转么讲解特殊的怎么还原
  现在可以看一下我算的
  2^64 / 4,294,967,302 = 0x100000006  最高位为符号位 代表这是个负数也就是-6
  如果根据定式还原得出的结果为 0xFFFFFFF9 然后对其取反得到6
  但是也有代码定式
mov regA,[ebp - xxx]  mov reg,M
  mul regA
  sub regA,edx
  shr regA,n
  add regA,edx
  shr regA,(n-1)
  

  观看代码定式可以得出
  乘减移加移
  这种先使用定式还原

[原创]#30天写作挑战#反汇编代码还原之除数为非2的幂

[原创]#30天写作挑战#反汇编代码还原之除数为非2的幂
  这里取出两个n值. 1+31 = 32所以n值为32
  代入公式得
  2^64 / 4,294,967,303 = 0XFFFFFFF9
  关于特殊汇编在下一篇应该会详细讲解.
四丶为什么学习除法优化4.1 为什么学习除法优化  ​    还是那句话为什么学习除法优化. 好就以我们上面的例子为例.那么使用IDA F5查看

[原创]#30天写作挑战#反汇编代码还原之除数为非2的幂

[原创]#30天写作挑战#反汇编代码还原之除数为非2的幂
  请问看到这种代码你怕了吗. 直接反汇编可以得出这一段代码我是干啥.用IDA反汇编就会得出 右移等等.在我们看来就是硬汇编
  也就是硬着头皮还原的.所以说这就是我们学习的意义所在 当然F5还是很强大的.但是我们学会了能更好的帮助我们进行反汇编,更好的通过反汇编从而还原为高级代码
五丶高级Vs编译器与linux下的gcc优化  其实还是老生常谈.拿高版本与低版本做个对比.看看优化方式是否发生了改变.
5.1 vs2019 x86 有符号非2的幂优化  高级代码
int main(int argc, char* argv[])  {
  /*
  除法
  */
  int NumberOne = 0;
  int NumberTwo = 0;
  scanf("%d",&NumberOne);
  scanf("%d",&NumberTwo);
  int Count1 = NumberOne / 3;
  int Count2 = NumberTwo / 5;
  int Count3 = NumberTwo / 6;
  int Count4 = NumberTwo / 9;
  printf("%d%d%d%d%d",Count4,Count3,Count2,Count1);
  system("pause");
  return 0;
  }
  

  汇编
.text:00401080                 push    ebp  .text:00401081                 mov     ebp, esp
  .text:00401083                 sub     esp, 8
  .text:00401086                 lea     eax, [ebp+var_4]
  .text:00401089                 mov     [ebp+var_4], 0
  .text:00401090                 push    eax
  .text:00401091                 push    offset unk_41ECDC
  .text:00401096                 mov     [ebp+var_8], 0
  .text:0040109D                 call    sub_401050
  .text:004010A2                 lea     eax, [ebp+var_8]
  .text:004010A5                 push    eax
  .text:004010A6                 push    offset unk_41ECDC
  .text:004010AB                 call    sub_401050
  .text:004010B0                 mov     ecx, [ebp+var_8]
  .text:004010B3                 mov     eax, 55555556h
  .text:004010B8                 imul    [ebp+var_4]
  .text:004010BB                 mov     eax, edx
  .text:004010BD                 shr     eax, 1Fh
  .text:004010C0                 add     eax, edx
  .text:004010C2                 push    eax
  .text:004010C3                 mov     eax, 66666667h
  .text:004010C8                 imul    ecx
  .text:004010CA                 sar     edx, 1
  .text:004010CC                 mov     eax, edx
  .text:004010CE                 shr     eax, 1Fh
  .text:004010D1                 add     eax, edx
  .text:004010D3                 push    eax
  .text:004010D4                 mov     eax, 2AAAAAABh
  .text:004010D9                 imul    ecx
  .text:004010DB                 mov     eax, edx
  .text:004010DD                 shr     eax, 1Fh
  .text:004010E0                 add     eax, edx
  .text:004010E2                 push    eax
  .text:004010E3                 mov     eax, 38E38E39h
  .text:004010E8                 imul    ecx
  .text:004010EA                 sar     edx, 1
  .text:004010EC                 mov     eax, edx
  .text:004010EE                 shr     eax, 1Fh
  .text:004010F1                 add     eax, edx
  .text:004010F3                 push    eax
  .text:004010F4                 push    offset aDDDDD   ; "%d%d%d%d%d"
  .text:004010F9                 call    sub_401020
  .text:004010FE                 push    offset aPause   ; "pause"
  .text:00401103                 call    sub_4048E7
  .text:00401108                 add     esp, 28h
  .text:0040110B                 xor     eax, eax
  .text:0040110D                 mov     esp, ebp
  .text:0040110F                 pop     ebp
  

  这里流水线优化等也不去掉了.可以发现跟VC6.0无任何区别
5.2 vs2019 x64有符号非2的幂优化  高级代码
int main(int argc, char* argv[])  {
  /*
  除法
  */
  __int64 NumberOne = 0;
  __int64 NumberTwo = 0;
  scanf("%I64d", &NumberOne);
  scanf("%I64d", &NumberTwo);
  __int64 Count1 = NumberOne / 3;
  __int64 Count2 = NumberTwo / 5;
  __int64 Count3 = NumberTwo / 6;
  __int64 Count4 = NumberTwo / 9;
  printf("%I64d%I64d%lld%lld", Count4, Count3, Count2, Count1);
  system("pause");
  return 0;
  }
  

  反汇编
text:00000001400010D0                 sub     rsp, 38h  .text:00000001400010D4                 xor     eax, eax
  .text:00000001400010D6                 lea     rdx, [rsp+38h+arg_10]
  .text:00000001400010DB                 lea     rcx, aI64d      ; "%I64d"
  .text:00000001400010E2                 mov     [rsp+38h+arg_10], rax
  .text:00000001400010E7                 mov     [rsp+38h+arg_18], rax
  .text:00000001400010EC                 call    sub_140001080
  .text:00000001400010F1                 lea     rdx, [rsp+38h+arg_18]
  .text:00000001400010F6                 lea     rcx, aI64d      ; "%I64d"
  .text:00000001400010FD                 call    sub_140001080
  .text:0000000140001102                 mov     rcx, [rsp+38h+arg_18]
  .text:0000000140001107                 mov     rax, 5555555555555556h
  .text:0000000140001111                 imul    [rsp+38h+arg_10]
  .text:0000000140001116                 mov     rax, 6666666666666667h
  .text:0000000140001120                 mov     r10, rdx
  .text:0000000140001123                 shr     r10, 3Fh
  .text:0000000140001127                 add     r10, rdx
  .text:000000014000112A                 imul    rcx
  .text:000000014000112D                 mov     [rsp+38h+var_18], r10
  .text:0000000140001132                 mov     r9, rdx
  .text:0000000140001135                 sar     r9, 1
  .text:0000000140001138                 mov     rax, r9
  .text:000000014000113B                 shr     rax, 3Fh
  .text:000000014000113F                 add     r9, rax
  .text:0000000140001142                 mov     rax, 2AAAAAAAAAAAAAABh
  .text:000000014000114C                 imul    rcx
  .text:000000014000114F                 mov     rax, 1C71C71C71C71C72h
  .text:0000000140001159                 mov     r8, rdx
  .text:000000014000115C                 shr     r8, 3Fh
  .text:0000000140001160                 add     r8, rdx
  .text:0000000140001163                 imul    rcx
  .text:0000000140001166                 lea     rcx, aI64dI64dLldLld ; "%I64d%I64d%lld%lld"
  .text:000000014000116D                 mov     rax, rdx
  .text:0000000140001170                 shr     rax, 3Fh
  .text:0000000140001174                 add     rdx, rax
  .text:0000000140001177                 call    sub_140001020
  .text:000000014000117C                 lea     rcx, aPause     ; "pause"
  .text:0000000140001183                 call    sub_1400045C4
  .text:0000000140001188                 xor     eax, eax
  .text:000000014000118A                 add     rsp, 38h
  .text:000000014000118E                 retn
  

  观看反汇编其实跟x86一致
  这里还是去掉流水线优化 提取核心代码位置进行反汇编
.text:0000000140001107                 mov     rax, 5555555555555556h  .text:0000000140001111                 imul    [rsp+38h+arg_10]
  .text:0000000140001120                 mov     r10, rdx
  .text:0000000140001123                 shr     r10, 3Fh
  .text:0000000140001127                 add     r10, rdx
  

  M数值变大.还是代入公式即可. 这里使用的mov r10,rdx 说明直接使用的rdx. rdx是一个64位数. 所以 2^64 / M = 2.9999999 向上取整 = 3
5.3 linux gcc x86 有符号非2的幂  高级代码
#include<stdio.h>  int main()
  {
  int NumberOne = 0;
  int NumberTwo = 0;
  scanf("%d", &NumberOne);
  scanf("%d", &NumberTwo);
  int Count1 = NumberOne / 3;
  int Count2 = NumberTwo / 5;
  int Count3 = NumberTwo / 6;
  int Count4 = NumberTwo / 9;
  printf("%d%d%d%d", Count4, Count3, Count2, Count1);
  scanf("%d", &Count4);
  scanf("%d", &Count3);
  scanf("%d", &Count2);
  scanf("%d", &Count1);
  printf("%d%d%d%d", Count4, Count3, Count2, Count1);
  return 0;
  }
  

  如果你是64位系统.那么你使用gcc命令如下
gcc xxx.c -o2 -m32  

  编译出来即可. 其实下面反汇编跟x86 vc++6.0 vs2019 一样.可以不用看了.
  反汇编
.text:080484BB ; int __cdecl main(int argc, const char **argv, const char **envp)  .text:080484BB                 public main
  .text:080484BB main            proc near               ; DATA XREF: _start+17↑o
  .text:080484BB
  .text:080484BB var_24          = dword ptr -24h
  .text:080484BB var_20          = dword ptr -20h
  .text:080484BB var_1C          = dword ptr -1Ch
  .text:080484BB var_18          = dword ptr -18h
  .text:080484BB var_14          = dword ptr -14h
  .text:080484BB var_10          = dword ptr -10h
  .text:080484BB var_C           = dword ptr -0Ch
  .text:080484BB argc            = dword ptr  8
  .text:080484BB argv            = dword ptr  0Ch
  .text:080484BB envp            = dword ptr  10h
  .text:080484BB
  .text:080484BB ; __unwind {
  .text:080484BB                 lea     ecx, [esp+4]
  .text:080484BF                 and     esp, 0FFFFFFF0h
  .text:080484C2                 push    dword ptr [ecx-4]
  .text:080484C5                 push    ebp
  .text:080484C6                 mov     ebp, esp
  .text:080484C8                 push    ebx
  .text:080484C9                 push    ecx
  .text:080484CA                 sub     esp, 20h
  .text:080484CD                 mov     eax, large gs:14h
  .text:080484D3                 mov     [ebp+var_C], eax
  .text:080484D6                 xor     eax, eax
  .text:080484D8                 mov     [ebp+var_24], 0
  .text:080484DF                 mov     [ebp+var_20], 0
  .text:080484E6                 sub     esp, 8
  .text:080484E9                 lea     eax, [ebp+var_24]
  .text:080484EC                 push    eax
  .text:080484ED                 push    offset unk_80486B0
  .text:080484F2                 call    ___isoc99_scanf
  .text:080484F7                 add     esp, 10h
  .text:080484FA                 sub     esp, 8
  .text:080484FD                 lea     eax, [ebp+var_20]
  .text:08048500                 push    eax
  .text:08048501                 push    offset unk_80486B0
  .text:08048506                 call    ___isoc99_scanf
  .text:0804850B                 add     esp, 10h
  .text:0804850E                 mov     ecx, [ebp+var_24]
  .text:08048511                 mov     edx, 55555556h
  .text:08048516                 mov     eax, ecx
  .text:08048518                 imul    edx
  .text:0804851A                 mov     eax, ecx
  .text:0804851C                 sar     eax, 1Fh
  .text:0804851F                 sub     edx, eax
  .text:08048521                 mov     eax, edx
  .text:08048523                 mov     [ebp+var_1C], eax
  .text:08048526                 mov     ecx, [ebp+var_20]
  .text:08048529                 mov     edx, 66666667h
  .text:0804852E                 mov     eax, ecx
  .text:08048530                 imul    edx
  .text:08048532                 sar     edx, 1
  .text:08048534                 mov     eax, ecx
  .text:08048536                 sar     eax, 1Fh
  .text:08048539                 sub     edx, eax
  .text:0804853B                 mov     eax, edx
  .text:0804853D                 mov     [ebp+var_18], eax
  .text:08048540                 mov     ecx, [ebp+var_20]
  .text:08048543                 mov     edx, 2AAAAAABh
  .text:08048548                 mov     eax, ecx
  .text:0804854A                 imul    edx
  .text:0804854C                 mov     eax, ecx
  .text:0804854E                 sar     eax, 1Fh
  .text:08048551                 sub     edx, eax
  .text:08048553                 mov     eax, edx
  .text:08048555                 mov     [ebp+var_14], eax
  .text:08048558                 mov     ecx, [ebp+var_20]
  .text:0804855B                 mov     edx, 38E38E39h
  .text:08048560                 mov     eax, ecx
  .text:08048562                 imul    edx
  .text:08048564                 sar     edx, 1
  .text:08048566                 mov     eax, ecx
  .text:08048568                 sar     eax, 1Fh
  .text:0804856B                 sub     edx, eax
  .text:0804856D                 mov     eax, edx
  

5.4 其它同理自己建立项目研究  自己建立项目研究.高手复习 新手学习 谢谢观看


温馨提示:
1.如果您喜欢这篇帖子,请给作者点赞评分,点赞会增加帖子的热度,评分会给作者加学币。(评分不会扣掉您的积分,系统每天都会重置您的评分额度)。
2.回复帖子不仅是对作者的认可,还可以获得学币奖励,请尊重他人的劳动成果,拒绝做伸手党!
3.发广告、灌水回复等违规行为一经发现直接禁言,如果本帖内容涉嫌违规,请点击论坛底部的举报反馈按钮,也可以在【投诉建议】板块发帖举报。
论坛交流群:672619046

    发表于 2020-9-17 09:26:57
    收藏一下,晚上再看

      发表于 2020-9-17 10:00:31
      1.2那些写错了哦,相加不是想加

      小黑屋|手机版|站务邮箱|学逆向论坛 ( 粤ICP备2021023307号 )|网站地图

      GMT+8, 2024-12-28 00:33 , Processed in 0.206904 second(s), 51 queries .

      Powered by Discuz! X3.4

      Copyright © 2001-2021, Tencent Cloud.

      快速回复 返回顶部 返回列表