我如何知道汇编指令被击中的次数

时间:2017-09-14 15:27:38

标签: assembly gdb profiling

我目前正在开发一个项目,我在程序集级别修改了一些程序。程序转换非常简单,我只是在代码中的特定位置插入一些屏蔽操作。

我想知道执行屏蔽指令的次数,以准确了解程序转换成本。

目前我正在使用 GDB ,并设置了我的屏蔽指令所在的硬件断点。之后我可以使用 info breakpoints 获取断点的命中数。

然而,GDB速度非常慢,即使经过一夜的计算,通常不到10秒,也无法完成。

我很确定我正在使用硬件断点,我总是设置不到4个(我在带有4个调试寄存器的英特尔处理器上运行)。

我的GDB版本是8.0。

我在考虑使用分析器,我已经快速查看了valgrindgcovgprof,但它似乎并不适合我的需要。

有谁知道任何可以帮助我的工具? 或者有人知道如何加快我对GDB的想法吗?

由于

编辑:我在linux x86-64上运行

3 个答案:

答案 0 :(得分:4)

  

有谁知道任何可以帮助我的工具?

您可以尝试perf annotateperf tutorial中有一个例子:

  

可以使用perf向下钻取到指令级别   注释。为此,您需要使用名称来调用perf annotate   注释的命令。所有带样本的函数都是   反汇编,每条指令的相对百分比为   报告的样本:

perf record ./noploop 5
perf annotate -d ./noploop

------------------------------------------------
 Percent |   Source code & Disassembly of noploop.noggdb
------------------------------------------------
         :
         :
         :
         :   Disassembly of section .text:
         :
         :   08048484 <main>:
    0.00 :    8048484:       55                      push   %ebp
    0.00 :    8048485:       89 e5                   mov    %esp,%ebp
[...]
    0.00 :    8048530:       eb 0b                   jmp    804853d <main+0xb9>
   15.08 :    8048532:       8b 44 24 2c             mov    0x2c(%esp),%eax
    0.00 :    8048536:       83 c0 01                add    $0x1,%eax
   14.52 :    8048539:       89 44 24 2c             mov    %eax,0x2c(%esp)
   14.27 :    804853d:       8b 44 24 2c             mov    0x2c(%esp),%eax
   56.13 :    8048541:       3d ff e0 f5 05          cmp    $0x5f5e0ff,%eax
    0.00 :    8048546:       76 ea                   jbe    8048532 <main+0xae>
[...]
     

第一列报告功能样本的百分比   == noploop()==为该指令捕获。如前所述,您应该仔细解释这些信息。

答案 1 :(得分:2)

每当它遇到其中一个断点时,它必须停止程序并开始在GDB中执行某些操作。所以自然需要永远。

我会使用GDB而不是断点。 我只是手动随机停止它(或者你可以使用计时器)。 每次停止时,您都可以准确地看到它的指令。 如果这样做10或20次,您可以轻松估计每条指令花费的时间(换句话说,指令负责的总时间),并且您可以看到它随着屏蔽的变化。

除非您获得大量样本,否则您不会以这种方式获得非常精确的时间分数,但您获得的内容非常可靠。

然后再次,gprof should also do what you want尽可能多地承认它:)

答案 2 :(得分:1)

gdb与它无关,你必须依赖硬件/芯片提供的东西。首先,你不计算装配指令的次数,因为处理器不直接理解装配,他们理解机器代码,尽管并非所有装配指令都映射到一个机器指令,但你必须根据具体情况进行处理。因此,除了术语之外,你必须依赖硅片。

接下来定义命中,根据设计需要很多时钟周期来处理和执行指令,所以许多指令开始看到管道的早期阶段,直到处理器发现分支正在发生,比如阴影中的指令条件分支。我假设你对那些不感兴趣(断点和停止程序的流程与运行程序不一样,它改变了程序运行的方式,你强迫断点的阴影中的指令被击中至少两次正如他们通常基于术语命中你的意思的定义一样。

断点仅在处理器支持时才起作用,你通常总是在那里放一个未定义的指令,并且如果处理器支持那么它有一个未定义的处理程序(这是通用的,你具体使用的处理器是不相关的,特别是因为它似乎是x86,这意味着此时有许多不同的实现,而x86-64并没有开始描述完整答案所需的详细信息)

某些处理器根本没有提供调试支持,最好是未定义的指令,希望它能正常工作。有些人有很多,其余的有一些在中间,有些提供你要求观看的功能&#34;执行&#34;一个特定的地址和一个柜台。通常答案是断点,恢复和计算多少次是你唯一的选择。当然,这就是为什么,计算一个指令被击中的次数与循环的整体性能没有直接关系,有时如果它是唯一一个触及指令中的内存,但有时会对齐该指令或循环的对齐比机器代码本身更重要的角色...所以想知道你是如何达到你需要计算&#34;点击&#34;根据具体指示。 (你也可以通过分析代码来做到这一点。)