【发布时间】:2019-10-05 03:43:19
【问题描述】:
我正在尝试理解 rdpmc 指令。因此,我有以下 asm 代码:
segment .text
global _start
_start:
xor eax, eax
mov ebx, 10
.loop:
dec ebx
jnz .loop
mov ecx, 1<<30
; calling rdpmc with ecx = (1<<30) gives number of retired instructions
rdpmc
; but only if you do a bizarre incantation: (Why u do dis Intel?)
shl rdx, 32
or rax, rdx
mov rdi, rax ; return number of instructions retired.
mov eax, 60
syscall
(实现是rdpmc_instructions()的翻译。)
我认为这段代码应该在到达 rdpmc 指令之前执行 2*ebx+3 指令,所以我希望(在这种情况下)我应该得到 23 的返回状态。
如果我在这个二进制文件上运行perf stat -e instruction:u ./a.out,perf 告诉我我已经执行了 30 条指令,看起来差不多。但是如果我执行二进制文件,我会得到 58 或 0 的返回状态,不是确定性的。
我在这里做错了什么?
【问题讨论】:
-
您无法获得 306 的返回状态,因为只有退出值的最低有效 8 位返回给父进程。
-
您是否尝试过计算进入
_start与结束之间的增量?您是否尝试过增加迭代次数以查看结果是否随执行的指令而变化根本? -
代码审查:
for(i=0 ; i<1000; i++)的更好翻译是向循环计数器注册的 mov-immediate。或cmp eax, 1000。使用a dq 100只是混乱;内联小的只读常量。 (如果您仍然想要代码之前的定义,请使用equ)。1<<30的正确翻译是mov ecx, 1<<30,而不是运行时移位。更有效的循环结构是dec ebx / jnz .loop。rdpmc写入 EAX 和 EDX,隐式零扩展到 RAX 和 RDX,您不需要先将它们归零。此外,您也可以忽略 RDX,除非计数可能 > 2^32。 -
另外不要忘记使用
default rel所以[a]使用RIP-relative 寻址模式。 (除非您尝试尝试 rel 和 abs 寻址模式之间的区别)。 -
@PeterCordes:当我在 perf 下运行它时,我得到 27 条指令,这是确定性的,这是正确的。
标签: performance assembly x86 performancecounter intel-pmu