我听说在x86上确定执行一条指令的确切时间是不可能的,因为像流水线这样的事情会使过程变得非常复杂。有没有办法降低这些机制的效率,以便能够预测指令运行时间?像movfuscator这样的混淆工具在这里会有帮助吗?
发布于 2015-12-28 17:18:46
如果较慢的执行速度是可以接受的,您可以尝试将保持在自修改代码处理模式。我不确定它的可预测性有多大。它是如此缓慢,以至于没有人费心去衡量性能特征。(相关的性能计数器是MACHINE_NUKES.SMC,它可以让您了解它对OOO管道的作用。)
偶尔加入一些or [rip+32], 0之类的东西。x86保证可以检测到跳转后的自修改代码,所以在跳转之前对跳转目标执行无操作或操作,这可能是确保您对即将运行的代码执行读-修改-写操作的好方法。
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循环高速缓存运行小循环时。
发布于 2015-12-28 04:52:54
降低了这些机制的效率
也许我误解了您的意思,但流水线是出于性能原因,而不是为了混淆执行时间的预测。
还有其他因素,比如缓存(正在读取的数据是否需要从内存中获取,或者它是否已经在l1/l2/l3缓存中?)
关于能够预测执行时间,我认为不可能预测单个指令的执行时间,但实时操作系统可能会让你感兴趣-它将执行时间的上限设置在较小的粒度级别:
https://stackoverflow.com/questions/34484670
复制相似问题