Optimization 寻址方式效率

Optimization 寻址方式效率,optimization,assembly,x86,cpu,addressing-mode,Optimization,Assembly,X86,Cpu,Addressing Mode,有人能告诉我“即时”寻址模式是否更有效吗 比通过[eax]或任何其他方式添加更有效 假设我有一个长函数,包含一些读取和 有些写入(比如5次读取,5次写入)到内存中的某个int值 mov some_addr, 12 //immediate adressing //other code mov eax, aome_addr //other code mov some_addr, eax // and so on 对 mov

有人能告诉我“即时”寻址模式是否更有效吗 比通过[eax]或任何其他方式添加更有效

假设我有一个长函数,包含一些读取和 有些写入(比如5次读取,5次写入)到内存中的某个int值

     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

哪个更快?

使用寄存器寻址最快


请参见

使用寄存器寻址是最快的


请参见

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

vs

因此,在加载指令、使用缓存等时,它有一些含义,因此它可能会更快一些,但在具有一些读写操作的长函数中-我认为它不太重要

(十六进制代码中的零应该由链接器来填充(仅此而已)

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

我做了一些测试,我真的很想知道他们揭示了什么。太多了,我没有进一步调查:-)

在大多数运行中的性能优于

C7 04 25 00 00 00 00 CC    movl $0xfeedbacc,s_var
BA ED FE
我真的很惊讶,现在我想知道Maratyszcza会如何解释这一点。我已经有了一个想法,但我愿意…有什么好玩的…不,看到这些(示例)结果

可能肯定会支持他的说法,即指令解码器每个周期最多需要8个字节,但它没有显示实际解码的字节数

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

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

注意:这些测量可能严重依赖于运行它们的(微)体系结构。上述值在Atom N450上运行测试代码时给出(恒定TSC,boot@1.6GHz,在测试运行期间固定为1.0GHz),这不太可能代表整个x86(-64)平台

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


/更新]

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

vs

因此,在加载指令、使用缓存等时,它有一些含义,因此它可能会更快一些,但在具有一些读写操作的长函数中-我认为它不太重要

(十六进制代码中的零应该由链接器来填充(仅此而已)

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

我做了一些测试,我真的很想知道他们揭示了什么。太多了,我没有进一步调查:-)

在大多数运行中的性能优于

C7 04 25 00 00 00 00 CC    movl $0xfeedbacc,s_var
BA ED FE
我真的很惊讶,现在我想知道Maratyszcza会如何解释这一点。我已经有了一个想法,但我愿意…有什么好玩的…不,看到这些(示例)结果

可能肯定会支持他的说法,即指令解码器每个周期最多需要8个字节,但它没有显示实际解码的字节数

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

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

注意:这些测量可能严重依赖于运行它们的(微)体系结构。上述值在Atom N450上运行测试代码时给出(恒定TSC,boot@1.6GHz,在测试运行期间固定为1.0GHz),这不太可能代表整个x86(-64)平台

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


/更新]

事实上,编码的差异是寄存器访问速度更快的原因。无论寻址模式如何,微操作都是相同的,但是冗长的直接寻址指令很容易使指令解码器暂停。在上面的示例中,对于CPU解码器,寄存器寻址指令的长度为3字节,立即寻址指令的长度为7字节。在Intel Atom上,解码器每周期最多只能解码8字节或2条指令,在Intel Nehalem和AMD推土机上,最多可以解码16字节或4条指令。请注意,典型指令的长度为3-5字节,因此额外的4字节即时地址是以未解码指令为代价的。Allrite我可以接受这个答案,因为排序otf“可能[eax]更快”没有人确定:/-我也认为可能是真的,尽管“dirrect immediate”在逻辑上是最简单的,因为
s_var
是一个全局变量,它的地址将处于低位32,因此您可以使用
mov$s_var,%eax
将它的地址放入带有5字节mov immediate而不是LEA的寄存器中。(不过,rip相对寻址需要LEA。)您的结果只有
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
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