x86 不能没有寄存器做很多事情,所以我不认为你可以摆脱寄存器“寻址模式”。一些非常不同的架构可能不使用寄存器,而只有堆栈或内存、内存指令。 IDK 他们如何实现指针;也许这样的架构可以做到memory[memory](C 数组表示法)。
可能不需要立即计算。您可以使用多个寄存器构造任何值。从零开始(xor eax, eax),inc 得到 1,左移到你想要的任何位置,inc 设置低位,左移等等。所以它需要最糟糕的2*popcount(N) 指令将N 放入寄存器。请注意,即时移位计数将不可用,因此重复移位一个的明显方法(shl eax,是的,移位一个单独的编码,或者只使用add eax, eax)将取决于在最高设置位的位置。所以log2(N) + popcount(N) 是显而易见的转变和公司。
绝对(你称之为直接)内存寻址不是最有用的寻址模式。我们可以通过使用一系列指令(见上文)构造地址并使用[register] 来模拟它。如果我们想减少,我们想放弃它。正如 Jester 所指出的,将绝对寻址作为我们唯一的形式使用起来会非常不方便(或者可能是不可能的?)。
索引显然可用于性能,而不是必需:您可以使用单独的指令进行移位和添加。
置换也只是为了性能,所以我们可以去掉它们并强制代码手动添加任何置换。请参阅紧接段落了解如何操作。
我相信 x86 仍然可以使用 just register 和 [register] 寻址模式任意编程。
使用register、[register]和immediate,性能应该不会比完整的x86差多少。
如果对内存的隐式访问不算作寻址模式,你当然可以用lodsd 和stosd 模拟[register],但你将无法进行原子读-修改-写操作.不过,这感觉像是作弊。
还有堆栈 (push/pop):我不知道堆栈+寄存器机器是否是图灵完备的,但它肯定不是通常意义上的可编程。当然,如果你修改e/rsp,你可以再次模拟[register],但操作数大小的选择比lodsb/w/d/q/stosb/w/d/q少。
如果包含 16 个 ymm 寄存器,x86 有相当多的空间可以在寄存器中存储东西。虽然我想不出一种在不使用内存或立即操作数(vextractf128)的情况下在整数寄存器和 ymm 的高 128b 之间移动数据的方法,但实际上你有 16 个 16B 向量寄存器插槽用于存储堆栈以外的本地状态。尽管如此,它的大小还是有限的,这可能意味着 32 位 386 ISA 中的 8 个 GP 寄存器与 64 位 AVX2 ISA 中的所有整数/mmx/ymm 寄存器与机器是否图灵完备无关,只有 push/pop , 寄存器,并且除了通过 push/pop 之外没有修改堆栈指针。