【问题标题】:Do terms like direct/indirect addressing mode actual exists in the Intel x86 manualsIntel x86 手册中是否存在诸如直接/间接寻址模式之类的术语
【发布时间】:2018-02-25 16:13:20
【问题描述】:

为了提供一点背景知识,我想研究 x86 指令是如何手动编码/解码的。我遇到了ModR/MSIB 字节,似乎理解x86 寻址模式是理解指令编码方案的基础。

因此,我在 Google 上搜索了 x86 寻址模式。搜索返回的大多数博客/视频都是 8086 处理器的寻址模式。通过其中一些,不同的寻址模式是注册、直接、间接、索引、基于等等。但是博客在提及这些寻址模式时使用了不一致的名称。多个不同的源使用多种不同的寻址模式。英特尔手册here 中甚至没有提到不同的术语。例如,我似乎在 Intel 手册中的任何地方都找不到称为 Direct 或 Indirect 的寻址模式。此外,ModRM 字节中的Mod 位是一个 2 位字段,这让我想知道是否可能有超过 4 种寻址模式。

我的问题是,像直接寻址模式、间接寻址模式这样的术语是不是英特尔手册中不再使用但被公众使用的旧术语。如果这些术语在技术上确实存在,我在哪里可以在手册中找到对它们的引用。

【问题讨论】:

  • 这些术语并不是真正以某种方式不复存在的“旧术语”,它们只是有点通用,并不特定于英特尔。英特尔手册不是定义术语的定义,因为很明显,英特尔不是唯一的 CPU 制造商或 ISA 设计者。
  • ModRM 已经扩展了 SIB(Scale, Index, Base)字节(并不断扩展以适应新的寄存器),索引,基于等记录。直接和间接用于某些指令的描述。寄存器寻址模式是 ModRM 字节的模式之一。关键是英特尔不需要命名所有模式,因为一旦它展示了如何对它们进行编码以及它们如何工作,它就不关心你使用什么寻址模式——它只关心你使用的是内存操作数具有特定大小。
  • X86 具有寄存器间接模式,与基址和/或索引(寄存器中的地址或基址)相同。它没有 memory indirect 模式或 multi-level memory indirect mode 在某些(大部分是较旧的)处理器上找到
  • 这些是计算机体系结构书籍作者创造的寻址模式类别的术语。无论您阅读什么,都指的是具有这些类别的 x86 寻址模式。如果您知道这些术语的含义,这将很有用,因为它可以让您开始理解模式。但这只是一个开始。类别很广泛,并且它们的定义重叠(基础与索引就是一个例子)。英特尔(和 AMD)只负责指定模式的工作方式。他们可以随心所欲地给他们打电话。如果全世界都使用相同的术语,那就太好了,但它从未发生过。
  • 通过寻址模式将其分解对于 x86 来说并不是很有用。与 68000 相比,它是一种非常非正交的设计。晶体管预算低、试图与以前的设计保持兼容并优化代码密度是基本驱动因素。

标签: assembly x86 addressing-mode


【解决方案1】:

大多数形式的 x86 寻址模式都没有真正的官方名称。它们都具有[base + index*scale + disp8/disp32] 的形式(或任何 1 或 2 个组件的子集),但 64 位 RIP 相对寻址除外。 Referencing the contents of a memory location. (x86 addressing modes).

英特尔确实在第 1 卷的第 3.7.5 节中正式命名了寻址模式的这些组件。它们还使用寄存器、立即数和内存,但通常不会对不同形式的寻址模式进行大肆宣传。

ModRM 字节中的 Mod 位是一个 2 位字段,这让我想知道是否可能有超过 4 种寻址模式。

Mod 使用 disp0/8/32 选择寄存器与内存。更多模式有“转义”代码

  • [rbp] 没有位移的模式意味着有一个没有基础的 disp32。 (这就是为什么你会在反汇编中看到[rbp+0][rbp] 的最佳编码是 base=rbp,disp8 为 0。(请注意,[rbp] 在它是帧指针时没有用。)
  • 将是 base=rsp 的 ModR/M 编码意味着有一个 SIB 字节。
  • 索引=RSP 的 SIB 编码意味着没有索引。 (鉴于前面的规则,这使得编码[rsp] 成为可能,而不是不太有用的[rsp+rsp]。)

在用英语写汇编语言时,很自然地会使用含义明显的术语,包括您提到的一些术语。例如,Intel's optimization manual 说(我的重点):

2.3.2.4 微操作队列和循环流检测器 (LSD)

...(具有索引寻址模式的微融合微指令在 SnB 上的 IDQ 中未分层)

... 对于以 索引寻址 为主的代码(通常 发生在数组处理中),重新编码算法以使用基(或基+位移)寻址可以 有时通过融合加载加操作和存储指令来提高性能。

索引寻址模式包括使用idx*scale 的任何组合,无论它是使用基本reg 还是使用disp32,或两者兼而有之。 (idx 单独是不可编码的;[rax*1] 实际上被编码为 disp32+idx*1disp32=0。)在某些时候他们说“任何带有索引的寻址模式”或类似的,否则可能不清楚它们到底是什么的意思。当然testing with performance counters可以验证解释。

但他们不会为事物编造名字。当没有明显的英语短语时,他们可以坚持某些东西,他们会写(仍在 Sandybridge 部分):

常见的加载延迟为五个周期。使用简单寻址时 模式,base plus offset小于2048,加载延迟可以是四个周期。

在表 2-19 中,它们有两列,一列用于 Base + Offset > 2048;Base + Index [+ Offset],另一个用于Base + Offset < 2048,延迟低 1 个周期(256b AVX 负载除外)。 (有趣的是,[rdi+8] 的延迟比 [rdi-8] 低 1c。)

(从技术上讲,他们可能应该说“位移”,因为整个寻址模式在 x86 术语中形成一个偏移量或有效地址,当添加到段基址时形成一个线性地址。但“偏移量”也用于用非 x86 通用术语描述寻址模式的直接常数部分。幸运的是,现在您通常不必考虑 x86 分段。)


在第 1 卷手册中,英特尔确实使用了您描述的一些术语。他们将仅具有位移组​​件的寻址模式描述为“直接”(某种),[reg] 描述为“间接”,因为在谈论指令集及其支持的寻址模式时确实会使用这些术语。

vol.1 3.7.5 Specifying an Offset

以下寻址模式建议使用常见的组合 地址组件。

  • 位移——一个位移单独代表一个 直接(未计算)到操作数的偏移量。因为位移是 在指令中编码,这种形式的地址有时是 称为绝对或静态地址。它通常用于访问 静态分配的标量操作数。

  • Base ⎯ 单独的base 表示操作数的间接偏移。 ...

  • (Index ∗ Scale) + Displacement ⎯ 这种地址模式提供了一种有效的方式来索引静态数组...
  • 底座 + 索引 + 位移 ...
  • Base + (Index ∗ Scale) + Displacement ⎯ 一起使用所有寻址组件可以提高效率 当数组元素的大小为 2、4 或 8 字节时,对二维数组进行索引。

但正如您所看到的,它们不会为更复杂的形式编造名称。

不过,它们确实区分了即时操作数、寄存器操作数和内存操作数。 (3.7 操作数寻址)。不过,它们通常很少或根本没有区分使用寄存器编码的 r/m32 操作数与必须是寄存器的其他操作数。


分支指令术语

直接与间接也适用于分支机构。这有点像谈论寻址模式以达到接下来将要运行的代码字节。

6.3.7 64 位模式下的分支函数

...

地址大小会影响用于 JCXZ 和 LOOP 的 RCX 的大小;它们还会影响内存的地址计算 间接分支。这些地址默认为 64 位;但它们可以被地址大小覆盖为 32 位 前缀。

内存间接是jmp [rax],其中 RIP 的最终值来自内存,而不是像 jmp rax 这样设置 RIP=RAX 的寄存器间接分支。 x86 没有用于加载/存储的内存间接寻址模式;采用分支后的代码提取在术语中引入了额外的间接级别。 (有点)。

vol.2 manual entry for jmp 确实谈到了间接与相对或绝对跳跃。 (尽管请注意 x86 没有绝对直接 near 跳转(为此将地址放入寄存器中),只有使用立即指针(ptr16:16ptr16:32)指定的绝对远地址或间接使用内存位置。)

在描述接近间接跳转时,jmp r/m32(或 64),他们说“在 GP reg 或内存中间接指定的绝对偏移量”。 (“绝对偏移量”是相对于 CS 段基数的)。

分段使 x86 寻址更难以讨论,尤其是在比较可以显式包含段的特殊寻址模式与不包含段的特殊寻址模式时。


命名寻址模式被高估了

记住 x86 寻址模式在一般情况的子集方面可以做什么要容易得多,而不是用 Indexed、Based 等名称分别记住所有不同的可能性。

您在诸如 https://www.tutorialspoint.com/microprocessor/microprocessor_8086_addressing_modes.htmhttp://www.geeksforgeeks.org/addressing-modes/ 之类的教程中看到了对寻址模式进行分类的重要内容。后者甚至有一个测验,要求您将 C 语句与一些寻址模式名称进行匹配。

对于不太灵活的 16 位寻址模式,您可以尝试命名它们的数量很少,而基于与索引实际上确实为您提供了不同的寄存器选择。但是当你在编程时,你真正需要记住的是你可以选择[bx|bp] + [di|si] + disp0/8/16 的任何子集。这就是di/si(dst/src 索引)和bx/bp 的名称。


这样的术语在比较不同 ISA 的功能时很有用。例如,Wikipedia says 说像 PDP-8 这样的旧 ISA 大量使用内存间接,因为它们的寄存器很少,而且寄存器的寻址范围只有 8 位。

维基百科还说:

请注意,没有公认的命名各种寻址模式的方式。

对模式的命名没有意义。如果您正在写东西,请确保清楚您的意思,而不依赖于某些术语的特定技术含义。例如如果您说“索引寻址模式”,请确保读者从上下文中知道您是否包含base+index*scale

我想知道命名模式的某些愿望是否源于早于 8086 的 8 位微控制器。您可能想在https://retrocomputing.stackexchange.com/ 上询问这个问题。我不太了解 8 位 CPU 上可用的寻址模式,这些寻址模式大多是固定的一字节指令。

【讨论】:

    猜你喜欢
    • 2015-05-09
    • 2012-05-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多