繁体   English   中英

计算所需的最小寻址模式数是多少?

[英]What is the minimum number of addressing modes necessary for computation?

在x86汇编程序中,假设你有

  • 用于分配号码的立即寻址模式
  • 寄存器的寄存器寻址模式
  • 内存地址的直接寻址模式

为什么需要索引和基指针寻址模式 据我所知,每个都可以用循环代替。

间接模式似乎也没有太大用处,因为您可以简单地使用直接模式来引用内存地址。 首先访问寄存器的目的是什么,然后包含指向存储器地址的指针?

简而言之,哪些寻址方式确实是必要的?

虽然理论上“寻址模式”可用于指代操作数类型,但由于它不涉及地址,因此有点令人困惑。 英特尔手册使用“寻址模式”来指代内存寻址,我将使用此定义。

在汇编中,操作数可以是:

  • 直接的价值
  • 一个寄存器
  • 内存中的值(这里的操作数是地址)

在x86架构中,“寻址模式”仅适用于最后一种类型的操作数:存储器操作数(地址),并且指的是可用于计算地址的方法。 寻址模式可以在单个可配置寻址模式中汇总:

address = REG_base + REG_index*n + offset

REG_baseREG_indexnoffset都是可配置的,并且都可以省略(但显然至少需要一个)。

address = offset称为立即,直接或绝对寻址。
address = REG_base称为寄存器间接寻址。
address = REG_base + REG_index称为base plus index寻址。
同样,您可以添加偏移量( offset )和比例( n )。

严格来说,您只需要一种模式即可完成所有操作:注册间接寻址( address = REG )。 这样,如果需要访问内存,可以在寄存器中计算所需的任何地址,并使用它来进行访问。 它也可以通过使用内存替换直接寄存器操作数,并通过使用算术构造值来立即操作数。 但是,对于实际的指令集,您仍然可以立即有效地加载地址操作数,如果您不想要仅指针寄存器,则需要注册操作数。

除了间接寄存器之外的所有其他寻址模式都是为了方便起见,它们确实非常方便:

  • 如果您只需访问内存中的固定变量,立即寻址将为您保存一个寄存器。
  • Base + offset对于访问对象成员非常有用:您可以将基址保存在寄存器中,并访问具有固定偏移量的单个成员。 无需中间计算或注册以保存成员地址。
  • 类似地,索引寻址用于访问数组:您只需更改索引寄存器即可访问数组中的任何值。
  • 使用缩放,您可以访问多字节变量(ex: int )数组,而无需额外的寄存器或计算。
  • 所有内容的组合可用于访问对象中的数组成员,仍然保留基指针以便可能访问对象中的其他成员。

这些寻址模式不需要CPU的大量计算:只需要添加和移位。 考虑到x86可以在每个周期进行乘法,这些操作很简单,但仍然非常方便。

没有寄存器,x86不能做太多,所以我认为你不能摆脱寄存器“寻址模式”。 一些非常不同的架构可能不使用寄存器,只有堆栈或内存,内存指令。 IDK如何实现指针; 也许这样的架构可以做memory[memory] (C数组表示法)。

是不是需要立即进行计算成为可能 您可以使用多个寄存器构造任何值。 以零(开始xor eax, eax ), inc就拿到1,左移它给你想要的任何位置, inc要设置低位,左移等,所以它需要在最糟糕的2*popcount(N)指令将N放入寄存器。 请注意,即时移位计数将不可用,因此重复移位一个显而易见的方法( shl eax ,是的,有一个单独的编码,一个一个,或只是使用add eax, eax )将取决于在最高设置位的位置。 所以log2(N) + popcount(N)表示明显的shift和inc。

绝对(你所谓的直接)内存寻址不是最有用的寻址模式。 我们可以通过使用一系列指令构造地址(见上文)和使用[register]来模拟它。 如果我们试图削减,我们想放弃它。 正如杰斯特所指出的那样,保持绝对地址作为我们唯一的形式将是非常不方便(或者可能不可能?)使用。

索引显然可用于性能,而不是必需:您可以使用单独的指令进行移位和添加。

位移也仅用于性能,因此我们可以摆脱它们并强制代码手动添加任何位移。 请参阅立即段落了解具体方法。


我相信86仍然被任意编程, 只需 register[register]寻址模式。

使用register[register]immediate ,性能应该比完整的x86差很多。


如果对内存的隐式访问不算作寻址模式,您当然可以使用lodsdstosd模拟[register] ,但是您将无法进行原子读 - 修改 - 写操作。 但这感觉就像是作弊。

还有堆栈( push/pop ):我不知道堆栈+寄存器机器是否是Turing-complete,但它通常不是通常意义上的可编程。 当然,如果你修改e/rsp ,你可以再次模拟[register] ,但操作数大小的选择少于lodsb/w/d/q / stosb/w/d/q

如果包含16个ymm寄存器,x86有足够的空间存储寄存器。 虽然我想不出一种在整数寄存器和ymm的高128b之间移动数据的方法,而不使用任何内存或立即操作数(对于vextractf128 ),所以在实践中你有更多像16个16B向量寄存器槽用于存储本地堆栈以外的状态。 尽管如此,它的大小有限,这可能意味着32位386 ISA中的8个GP寄存器与64位AVX2 ISA中的所有整数/ mmx / ymm寄存器无关,这与机器是否只有推/弹的图像完全无关,寄存器,除了通过push / pop之外没有修改堆栈指针。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM