英特尔 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,这是一个非常方便的分析程序集输出的工具。
我想计算简单递归斐波那契函数 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,这是一个非常方便的分析程序集输出的工具。