【问题标题】:Assembly pointer, absolute address汇编指针,绝对地址
【发布时间】:2019-11-20 15:17:43
【问题描述】:

我是新人,我只是将计算机科学作为一种爱好。 在汇编中使用基指针,它允许我通过从基指针中减去某个偏移量来引用特定的内存位置。 得到的是绝对地址。 EBP - 偏移量 = 绝对地址。但是这个减法是在哪里进行的呢?

绝对地址是在哪个寄存器中计算的?

我举一个我的困惑的例子。

如果我有MOV dword ptr[EBP], 10 在这种情况下,EBP 寄存器的值表示绝对地址。

但是如果我有MOV dword ptr[EBP - 4], 10 在这种情况下,必须从 ebp 地址中减去 4 个字节。

这个操作是在哪个寄存器里做的,这个计算的结果写在哪里?

【问题讨论】:

标签: pointers assembly x86 cpu-architecture addressing-mode


【解决方案1】:

如果您希望将地址计算结果保存在寄存器中,请使用 LEA 而不是加载或存储,或者同时使用。

当用于实际内存访问时,地址计算发生在 AGU 内部的加载或存储地址执行单元中,并且不会写回架构寄存器。它只传递给 TLB 以转换为物理然后写入存储缓冲区。 (或者对于负载,用于探测 L1d 缓存)。这个内部添加有一些延迟,英特尔 CPU 在某些情况下甚至会尝试跳过它,如果他们猜错了就不得不重播 uop。 (Is there a penalty when base+offset is in a different page than the base?)

与 ARM 或其他一些 ISA 不同,x86没有具有将最终地址写回基址寄存器的任何寻址模式。

CPU 由很多个晶体管组成。其中一些用于与命名寄存器分开的内部缓冲区和加法器。 [reg] 之外的寻址模式的要点在于,您可以使用它们修改您当前在寄存器中的任何值。

【讨论】:

  • 感谢您,我发现了地址生成单元。那么计算绝对地址的所有算术运算都是在这个单元内完成的吗?即使只需要计算地址,但不需要访问内存,如LEA的情况,是否涉及AGU?
  • @Tony92:在几个 CPU 中(如有序 Atom)是的。否则不,LEA 在 ALU 执行单元上运行,就像它是移位和加法指令一样,在所有乱序执行 x86 CPU 上运行,因此它不会与实际负载竞争。请参阅 agner.org/optimize 获取指令表和微架构指南。也可以stackoverflow.com/tags/x86/info 获取更多链接。
  • 我无法理解的事情 [ebp - 4],在 ALU 或 AGU 中的地址计算在哪里完成?如果我使用 MOV(可以访问内存)地址由 AGU 计算,如果我使用 LEA(无法访问内存)地址由 ALU 计算?
  • @Tony92:不同的微架构实现它的方式不同。最初的 8086 是内部微编码的,没有流水线,也没有专用的 AGU。许多有序 uarch 在 AGU 硬件上运行 LEA。大多数乱序 uarch 在 ALU 执行单元上运行 LEA,就像任何其他移位或加法指令一样。但是 AMD K8/K10 在 AGU 单元上运行它。请参阅LEA or ADD instruction? 上的 cmets。没有软件可见的差异,只有性能调整注意事项和“有趣的事实”CPU 如何在底层知识下工作。
  • @Tony92:但是,如果它可以帮助您记住 LEA 的功能,那么可以将 LEA 视为另一个 ALU 指令,不同于通过 AGU 访问内存。
【解决方案2】:

正如 Jester 所说,它不是用户可见的。

大多数处理器都有多个寄存器,称为寄存器数组,用于保存在应用程序执行期间必须快速访问的数据和指令。 其中之一是Memory address register (MAR)

CPU 使用 MAR 来存储这些数据将在系统 RAM 上放置的地址,或者从哪里访问它们。

PS:因为我不是以英语为母语的人,所以我不能 100% 确定它会回答你的问题

【讨论】:

  • 这就是没有虚拟内存的玩具 CPU 的工作方式,是的。但例如 Ice Lake 可以通过其多端口缓存在每个时钟执行 2 次加载和 2 次存储。存储地址 uop 只是将物理地址写入存储缓冲区,以供以后在存储指令退出时使用(变为非推测性的)。请参阅x86 registers: MBR/MDR and instruction registers - 真正的 x86 CPU 没有像单个 MAR 这样简单的东西,当然它们有缓存。
  • 好吧,据我所知,MAR 仍在使用中……不是吗? link
  • 以 Sandybridge-family / Skylake-client 为例,如果私有 L1d 和 L2 中的负载丢失,则对整个缓存线的请求通过环形总线到达 L3 的切片。如果未命中,则请求通过环形总线发送到 DDR4 内存控制器之一。 DDR SDRAM 寻址不会一次将整个地址放在任何特定总线上;它将它分解为行/列。发送行选择命令后,内存控制器发出读取突发命令,地址线上的列地址为en.wikipedia.org/wiki/…
  • 所以实际上没有全宽的外部“地址总线”;有 64 条并行数据线,因此 8x 8 字节的突发填充了高速缓存线,但地址被分割。有关 DDR SDRAM 的更多详细信息,另请参阅What Every Programmer Should Know About Memory。当然,跟踪动态加载和存储请求的组件必须以某种方式跟踪地址,但将每个地址缓冲区称为 MAR 没有用或有趣,因为它们通常直接连接到任何“地址总线”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-31
  • 2012-01-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多