为什么 mov 图灵完整?

Why is mov turing complete?

我最近发现了这个:https://github.com/xoreaxeaxeax/movfuscator
这似乎取决于 mov 是图灵完备的事实。这是真的吗?为什么?

是的,x86 的 mov 是图灵完备的。我将该标记添加到您的问题中,因为它可能不适用于其他带有名为 mov 指令的 ISA,并且 movfuscator 编译器仅针对 x86。

不是"mov"本身在做计算,是x86寻址模式可以做加法(和位移) .我没有详细研究它是如何工作的,但是 它在很大程度上依赖于查找表 ,以及 mov eax, [base + eax*4] 之类的东西根据 EAX 为 0 加载两个可能值之一或 1.

还要记住 x86 mov has several forms:内存和寄存器之间(加载、存储或 reg<-reg),或直接到内存或寄存器。并具有绝对和寄存器间接寻址方式。

我不认为它依赖于自修改代码,但如果我错了请纠正我。 (如果是这样,我 think/hope movfuscator 至少不会创建除 mov 以外的指令。那是作弊。)


此外,这只是有点真实;你需要一些方法来循环主程序,假设原始源代码不是没有循环的直线 - Movfuscator github 自述文件谈到了这个:

While Dolan's paper required a jmp instruction, the M/o/Vfuscator does not - it uses a faulting mov instruction to achieve the infinite execution loop. If you're worried that this is still "jumping", the same effect could be achieved through pages aliased to the same address, wrapping execution around the upper range of memory, ring 0 exception handling, or simply repeating the mov loop indefinitely. A jmp is currently used to dispatch external functions - if this is a problem, avoid using external functions, or compile libraries with the M/o/Vfuscator as well.

在为 运行 的 mov-only 代码创建用户 space 环境时,我假设它创建了一个 SIGSEGV 处理程序(在 POSIX 操作系统上)从顶部重新开始执行.所以任何故障负载都可以重新启动主循环。

让执行回绕也被认为是一种可能性:

IP 环绕在 16 位模式下可以很好地工作,其中 IP 是 16 位但 CS:IP 形成 20 位线性地址(实模式)或在 16 位保护模式下 64k window 线性地址中的某处 space。也就是说,您可以在地址 space 的 部分 中拥有一个 64k 的指令块,其他 space 部分用于数据。 DS 段可以使用不同的碱基。 (16 位模式中的 32 位寻址模式是可能的,因此您仍然拥有任何寄存器和缩放索引寻址模式的全部功能。)请注意,读取和写入段寄存器的助记符也是 mov.

但是在 EIP 是 32 位的 32 位模式下更难,在 seg+off 计算之后线性地址也是如此。除非有其他技巧,否则回绕只能发生在整个地址 space 上,无论您如何处理分段。这不会为数据留下非代码 space。设置较低的段限制可能会导致代码获取错误,但这不会导致环绕(除非您设置信号处理程序,或者在裸机上设置中断处理程序地址)。

无论哪种方式,即使 x86-64 也只有 64 位指针(理论上;实际上是 48 位或 57 位),所以 space 是有限的,不像真正的图灵带无限胶带的机器。

系统很少通过直接证明其所有图灵可计算函数的能力而被称为图灵完备。 相反,它们通常是 "analogized" 已知的图灵完备的现有系统。

显示mov为TC的paper by Stephen Dolan通过根据mov构建TM系统的模拟来做到这一点。因此,在最坏的情况下,可以向 TC 系统提出的任何问题都可以在 mov 构建的模拟中虚拟化。