1

有人可以告诉我“立即”寻址模式是否比通过 [eax] 或任何其他方式寻址更有效。

假设我对内存中的某个 int 值有一些读取和一些写入(比如 5 次读取、5 次写入)的长功能

     mov some_addr, 12      //immediate adressing
     //other code
     mov eax, aome_addr
     //other code
     mov some_addr, eax    // and so on

相对

     mov eax, some_addr

     mov [eax], 12      // addressing thru [eax]
     //other code
     mov ebx, [eax]
     //other code
     mov [eax], ebx    // and so on

哪个更快?

4

2 回答 2

4

可能寄存器间接访问稍微快一些,但可以肯定的是它的编码更短,例如(警告 - 气体语法)

67 89 18                   mov %ebx, (%eax)
67 8b 18                   mov (%eax), %ebx

对比

89 1c 25 00 00 00 00       mov %ebx, some_addr
8b 1c 25 00 00 00 00       mov some_addr, %ebx

所以它在加载指令、使用缓存等时会产生一些影响,因此它可能会更快一些,但在一个带有一些读写的函数中——我认为这并不重要......

(十六进制代码中的零应该由链接器填充(只是这么说)。)

[更新日期="2012-09-30 ~21h30 CEST":

我已经进行了一些测试,我真的很想知道他们揭示了什么。以至于我没有进一步调查:-)

48 8D 04 25 00 00 00 00    leaq s_var,%rax
C7 00 CC BA ED FE          movl $0xfeedbacc,(%rax)

在大多数运行中表现优于

C7 04 25 00 00 00 00 CC    movl $0xfeedbacc,s_var
BA ED FE

我真的很惊讶,现在我想知道 Maratyszcza 将如何解释这一点。我已经有了一个想法,但我愿意......这很有趣......不,看到这些(示例)结果

movl to s_var
All 000000000E95F890 244709520
Avg 00000000000000E9 233
Min 00000000000000C8 200
Max 0000000000276B22 2583330
leaq s_var, movl to (reg)
All 000000000BF77C80 200768640
Avg 00000000000000BF 191
Min 00000000000000AA 170
Max 00000000001755C0 1529280

可能肯定会支持他的说法,即指令解码器每个周期最多占用 8 个字节,但它没有显示真正解码了多少字节。

leaq/movl对中,每条指令(包括操作数)小于 8 个字节,因此很可能每条指令在一个周期内分派,而单条指令则被movl分成两条。仍然我相信这不是解码器放慢速度,因为即使有 11 个字节,movl它的工作也是在第三个字节之后完成的——然后它只需要等待地址和立即数中的管道流,这两者不需要解码。

由于这是 64 位模式代码,我还使用 1 字节较短的 rip-relative 寻址进行了测试——结果(几乎)相同。

注意:这些测量可能在很大程度上取决于它们运行的​​(微)架构。以上数值是在 Atom N450(恒定 TSC,boot@1.6GHz,在测试运行期间固定在 1.0GHz)上运行测试代码时给出的,这不太可能代表整个 x86(-64) 平台。

注意:测量是在运行时进行的,没有进一步的分析,例如发生的任务/上下文切换或其他干预中断!

/更新]

于 2012-09-26T13:49:45.800 回答
3

使用寄存器寻址是最快的。

请参阅寄存器寻址模式与直接寻址模式

于 2012-09-26T12:47:32.890 回答