Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Loops 循环针工具的通用模式_Loops_Assembly_Loop Unrolling - Fatal编程技术网

Loops 循环针工具的通用模式

Loops 循环针工具的通用模式,loops,assembly,loop-unrolling,Loops,Assembly,Loop Unrolling,我试图找到一个通用模式,以便能够运行pintool程序,因此它总是会告诉我索引在哪里,或者是什么,以及循环指向哪个值 例如,下面是某个循环的组装: 40c374: 48 8b 55 e8 mov -0x18(%rbp),%rdx 40c378: 8b 45 fc mov -0x4(%rbp),%eax 40c37b: 48 98 cltq 40c37d: 0

我试图找到一个通用模式,以便能够运行pintool程序,因此它总是会告诉我
索引在哪里,或者是什么,以及循环指向哪个值

例如,下面是某个循环的组装:

 40c374:    48 8b 55 e8             mov    -0x18(%rbp),%rdx
  40c378:   8b 45 fc                mov    -0x4(%rbp),%eax
  40c37b:   48 98                   cltq   
  40c37d:   0f b6 84 02 80 00 00    movzbl 0x80(%rdx,%rax,1),%eax
  40c384:   00 
  40c385:   84 c0                   test   %al,%al
  40c387:   74 2a                   je     40c3b3 <makeMaps_e+0x5b>
  40c389:   48 8b 45 e8             mov    -0x18(%rbp),%rax
  40c38d:   8b 40 7c                mov    0x7c(%rax),%eax
  40c390:   89 c1                   mov    %eax,%ecx
  40c392:   48 8b 55 e8             mov    -0x18(%rbp),%rdx
  40c396:   8b 45 fc                mov    -0x4(%rbp),%eax
  40c399:   48 98                   cltq   
  40c39b:   88 8c 02 80 01 00 00    mov    %cl,0x180(%rdx,%rax,1)
  40c3a2:   48 8b 45 e8             mov    -0x18(%rbp),%rax
  40c3a6:   8b 40 7c                mov    0x7c(%rax),%eax
  40c3a9:   8d 50 01                lea    0x1(%rax),%edx
  40c3ac:   48 8b 45 e8             mov    -0x18(%rbp),%rax
  40c3b0:   89 50 7c                mov    %edx,0x7c(%rax)
  40c3b3:   83 45 fc 01             addl   $0x1,-0x4(%rbp)
  40c3b7:   81 7d fc ff 00 00 00    cmpl   $0xff,-0x4(%rbp)
  40c3be:   7e b4                   jle    40c374 <makeMaps_e+0x1c>
40c374:48 8b 55 e8 mov-0x18(%rbp),%rdx
40c378:8b 45 fc mov-0x4(%rbp),%eax
40c37b:48 98 cltq
40c37d:0f b6 84 02 80 00 movzbl 0x80(%rdx,%rax,1),%eax
40c384:00
40c385:84 c0测试%al,%al
40c387:74 2a je 40c3b3
40c389:48 8b 45 e8 mov-0x18(%rbp),%rax
40c38d:8b 40 7c mov 0x7c(%rax),%eax
40c390:89 c1 mov%eax,%ecx
40c392:48 8b 55 e8 mov-0x18(%rbp),%rdx
40c396:8b 45 fc mov-0x4(%rbp),%eax
40c399:48 98 cltq
40c39b:88 8c 02 80 01 00 mov%cl,0x180(%rdx,%rax,1)
40c3a2:48 8b 45 e8 mov-0x18(%rbp),%rax
40c3a6:8b 40 7c mov 0x7c(%rax),%eax
40c3a9:8d 50 01 lea 0x1(%rax),%edx
40c3ac:48 8b 45 e8 mov-0x18(%rbp),%rax
40c3b0:89 50 7c移动%edx,0x7c(%rax)
40c3b3:83 45 fc 01地址$0x1,-0x4(%rbp)
40c3b7:81 7d fc ff 00 cmpl$0xff,-0x4(%rbp)
40c3be:7e b4 jle 40c374
现在我注意到,
检查CMD
并不总是
CMP

有没有办法找出
索引
值和总迭代次数

有没有办法找出索引值和总迭代次数

没有

一些循环可能具有非索引逻辑,例如以非平凡的方式推进两个+组件键,例如链表遍历(您必须实际遍历树才能知道总计数),其中主要终止条件是
(leaf_ptr==nullptr)
,另外,一些循环可能有几个不同的终止条件(
break;
),所以您会选择哪一个作为迭代次数?最大值,还是在实际运行中触发循环退出的较早值


对于经典的
For(i=…)
循环,您可以在代码中手动找到它,但是“索引”几乎可以隐藏在任何东西中,没有通用模式。有些循环从例如<代码> -> 10代码>代码> > 1代码>代码(C++源为<代码> >(i=0;i as @ pED7G),并非所有循环都有在第一次迭代运行之前已知的行程计数。 但是对于循环,它们通常只在循环中使用一个条件分支(通常在底部)进行编译。类似的启发式方法可能会检测到它们

  • 找到循环分支

    如果循环中有多个条件分支,其中一个离开循环而不返回,或者跳过计数器增量,那么这不是一个简单的循环

    如果可以验证循环体中的嵌套循环或条件没有修改正在查看的(外部)循环的循环计数器,则它们不是问题

  • 查找它所依赖的寄存器。例如,
    cmp,end\u指针/jne
    dec eax/jnz

    e、 g.从循环分支向后工作到第一个标志设置指令。(如果编译器正在为宏融合进行优化,那么它们将是背靠背的,但不幸的是,这并不总是在通用调整中启用。)编译器通常避免部分标志欺骗(如
    sub-ecx,1
    /
    dec-eax
    /
    jnc
    ),但如果您想更加安全,请确保标志设置指令实际设置了分支读取的标志

  • 检查只有一个寄存器在循环中被实际修改

  • 检查修改后的寄存器(循环计数器)在每次迭代中仅修改常量
给定循环计数器的起始值和与之比较的结束值,您可以计算行程计数。如果这些检查中的任何一个失败,根据这个启发式,它不是一个“简单循环”


如果你想让它在未优化的代码上工作,你就必须通过存储/重新加载到内存来跟踪循环计数器。即使是优化编译器有时也会发出多条与循环计数器相关的指令,比如
lea ecx,[rdi+1]
然后使用ecx一段时间,然后使用
mov edi,ecx
。通常这看起来像是错过了优化(循环中有更多指令,以使编译器想要的东西在循环之外)但是它确实发生了。

这就是我目前正在尝试做的。然而,查找它所依赖的寄存器有点困难,因为有时编译器会执行一定数量的
MOV
命令。所以我试图通过从下到上扫描来捕获它。@sijaanhallak:循环分支将取决于标志。查找指令n设置这些标志,是的,从循环分支向后操作到第一个标志设置指令。然后查看该指令使用的寄存器。