从 32 位 CPU 模式开始,有可用于 x86 架构的扩展地址操作数。可以指定基地址、位移、索引寄存器和比例因子。
例如,我们想遍历一个 32 位整数列表(前两个来自 32 字节长的数据结构数组,%rdi
作为数据索引,%rbx
作为基指针)。
addl $8, %rdi # skip eight values: advance index by 8
movl (%rbx, %rdi, 4), %eax # load data: pointer + scaled index
movl 4(%rbx, %rdi, 4), %edx # load data: pointer + scaled index + displacement
据我所知,这种复杂的寻址适合单个机器代码指令。但是这种操作的成本是多少,它与使用独立指针计算的简单寻址相比如何:
addl $32, %rbx # skip eight values: move pointer forward by 32 bytes
movl (%rbx), %eax # load data: pointer
addl $4, %rbx # point next value: move pointer forward by 4 bytes
movl (%rbx), %edx # load data: pointer
在后一个示例中,我引入了一个额外的指令和一个依赖项。但是整数加法非常快,我获得了更简单的地址操作数,并且不再有乘法。另一方面,由于允许的缩放因子是 2 的幂,所以乘法归结为位移,这也是一个非常快的操作。尽管如此,两个加法和移位可以用一个加法代替。
这两种方法的性能和代码大小有什么区别?是否有使用扩展寻址操作数的最佳实践?
或者,从 C 程序员的角度来问,哪个更快:数组索引还是指针运算?
是否有任何用于大小/性能调整的程序集编辑器?我希望我能看到每条汇编指令的机器码大小、时钟周期的执行时间或依赖图。有成千上万的装配怪胎会从这种应用程序中受益,所以我敢打赌,这样的东西已经存在了!