我听说在x86上确定执行指令所需的确切时间是不可能的,因为像流水线这样的事情会使进程变得非常复杂。有没有办法让这些机制不那么有效,以便能够预测指令运行时间?像movfuscator这样的模糊处理工具会有帮助吗?
答案 0 :(得分:1)
如果多执行速度较慢,则可以尝试将CPU保持在自修改代码处理模式。我不确定它有多可预测。它太慢了,没有人愿意测量性能特征。 (相关的性能计数器是MACHINE_NUKES.SMC
,它可以让您了解它对OOO管道的作用。)
偶尔混合or [rip+32], 0
或其他东西。 x86保证在跳转后检测自修改代码,因此在跳转之前在跳转目标上执行no-op OR为零可能是确保您执行读取 - 修改 - 写入操作的好方法即将运行的代码。
M / o / Vfuscator可以使执行更具可预测性。你永远不会有分支错误预测,因为一切都是用
之类的东西完成的mov [Ri], 0
mov [Rj], 1
mov Rk, [Ri] ; Rk = 1 if Ri==Rj
然而,缓存未命中和前端瓶颈仍然会使执行变得很不稳定。
其他混淆技术,例如跳入指令的中间(经过仔细选择以解码为不同但有效的指令)是一种完全不同的混淆技术。它不应该对指令时序的性能或可变性产生太大影响。所以这个问题并不是很合理:在询问这个问题时,将不同的混淆技术混为一谈是没有意义的。
现代无序机器的理论吞吐量/延迟数量并不难。在实践中,总会有额外的因素减慢速度。例如Intel Skylake in theory can do 2 loads and one store per clock, but Agner Fog reports that only 40%-60% of that is usually achieved in real code。一直加载/存储相同地址的人工测试仍然不能达到100%的理论速度,因为总有微架构的绊脚石。
另请参阅Significant FMA performance anomaly experienced in the Intel Broadwell processor此问题。
但是,在一些简单的循环中,您可以看到非常一致的性能:在Micro fusion and addressing modes中,我的测试循环给出了高度可重复的计数(对于许多执行)。尽管如此,即使您可以准确地测量它,我也不会为第一次执行某些代码而重复性。当缓存很热时,事情更容易预测,尤其是从uop循环缓存运行一个小循环时。
答案 1 :(得分:0)
使这些机制效率降低
也许我误解了你,但流水线是出于性能原因而做的,而不是混淆预测执行时间。
还有其他因素,例如缓存(读取的数据是需要从内存中获取还是已经在l1 / l2 / l3缓存中?)
关于能够预测执行时间,我不相信可以根据个别指令预测这一点,但实时操作系统可能会让您感兴趣 - 它会在执行时间上设置上限。细粒度级别: