英特尔 PIN 中指令计数背后的规则是什么?

What is the rule behind instruction count in Intel PIN?

我想计算简单递归斐波那契函数 O(2^n) 中的指令。我通过冒泡排序和矩阵乘法成功地做到了这一点,但在这种情况下,指令计数似乎忽略了我的 fibo 函数。这是用于检测的代码:

// Insert a call at the entry point of a routine to increment the call count
RTN_InsertCall(rtn, IPOINT_BEFORE, (AFUNPTR)docount, IARG_PTR, &(rc->_rtnCount), IARG_END);

// For each instruction of the routine
for (INS ins = RTN_InsHead(rtn); INS_Valid(ins); ins = INS_Next(ins))
{
    // Insert a call to docount to increment the instruction counter for this rtn
    INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)docount, IARG_PTR, &(rc->_icount), IARG_END);
}

我开始想知道这个程序和以前的程序有什么区别,我的第一个想法是:这里我没有使用数组。

这是我经过一些手动测试后发现的:

a = 5;        // instruction ignored by PIN and 
              //  pretty much everything not using array
fibo[1] = 1   // instruction counted properly
a = fibo[1]   // instruction ignored by PIN

所以似乎只有计数的指令才写入内存(这就是我的假设)。在我将我的 fibo 函数更改为此后它起作用了:

long fibonacciNumber(int n, long *fiboNumbers)
{
    if (n < 2) {
        fiboNumbers[n] = n;
        return n;
    }

    fiboNumbers[n] = fiboNumbers[n-1] + fiboNumbers[n-2];
    return fibonacciNumber(n - 1, fiboNumbers) + fibonacciNumber(n - 2, fiboNumbers);
}

但我也想计算不是我编写的程序的指令。有没有办法计算所有类型的指令?仅计算此指令是否有任何特殊原因?任何帮助表示赞赏。

//编辑

我使用 Visual Studio 中的反汇编选项来检查它的外观,但对我来说仍然没有任何意义。我找不到为什么只有对数组的赋值被 PIN 解释为指令的原因。

instruction_comparison

这超出了我的所有预期,算作 2 条指令:

even 2 instructions, not one

PIN 与其他低级分析和分析工具一样,测量单个 指令 、"add these two registers" 或 "load a value from that memory address" 等低级命令。程序包含的指令序列通常是通过编译器从高级语言(如 C++)生成的。一行 C++ 代码可能会被转换为一条指令,但一行转换为多条指令甚至零条指令也很常见;并且一行代码的指令可以与其他指令的指令交错。

您的编译器可以为您的源代码输出汇编语言文件,显示为哪些代码行生成了哪些指令。 (对于 GCC 和 Clang,这是通过 -S 标志完成的。)请注意,阅读编译器输出的汇编代码 不是 学习汇编的最佳方式。另外,我会向您指出 godbolt.org,这是一个非常方便的分析程序集输出的工具。