hea*_*low 6 x86 assembly cpu-registers accumulator
如果您正在编写程序集,那么将值分配给哪个寄存器重要吗?假设您将累积/中间值存储在 %ebx 而不是 %eax 中,后者传统上用于此目的。这是不好的做法吗?会影响性能吗?
换句话说,您是否可以将它们等同于存储空间,还是应该坚持将它们用于特定目的?
首先也是最重要的,您必须使用支持您想要使用的指令的寄存器。x86(以及其他架构,尽管较少)上的许多指令对寄存器的支持方式有一些限制。
以某些双寄存器乘法和除法指令为例,它们在特定用途中特别涉及 eax 和 edx。
接下来,您要使用高效的寄存器,即寄存器:
哪些编码更短(这里有关于 x64 指令长度的很好的讨论)。短编码可以更好地利用缓存资源,从而允许更大的程序更有效地运行。
不受阻碍,即由于调用约定,也就是说它们的使用不会产生额外的(软件/调用约定定义的)开销 - 除非该开销已经支付!
这是所产生的值的最终目的地:例如,如果是第二个参数,则对应于要传递的第二个值的寄存器(同样根据调用约定)。如果我们可以将值放置在正确的寄存器中(根据传递或返回值的需要),那么我们可以放弃数据移动(也称为复制)指令。
在任何只有您的代码运行的地方,您都可以将任何您想要的寄存器用于您想要的任何目的。然而,有两个主要的时候前提是错误的:
您需要将堆栈指针用于其预期目的,或者当信号处理程序运行时,它们会破坏实际上很重要的部分内存。
您的系统有一个调用约定。每当您调用其他人的库函数(或系统调用)时,您都需要将参数放在他们想要的地方,无论您想在哪里,他们都会将返回值放在标准位置。
您的调用约定还会让函数在不保存的情况下销毁某些寄存器:易失性寄存器与非易失性寄存器。例如,通常 FLAGS、EAX、ECX 和 EDX 在 32 位 x86 调用约定中是易失性的,而其余的整数寄存器则保留在callABI 兼容函数中。有关系统调用和用户空间函数调用约定,请参阅i386 和 x86-64 上的 UNIX 和 Linux 系统调用的调用约定是什么。
如果您正在编写程序集,那么将值分配给哪个寄存器重要吗?
对于 80x86;您使用哪个寄存器很重要的情况包括:
遵守其他人的调用约定(在正确的寄存器中传递值,通过首选“调用者保存”寄存器来避免“被调用者保存”的堆栈使用)
使用具有隐含寄存器的指令(MUL、DIV、MOVSQ/D/W/B、STOSQ/D/W/B、XLATB、AAA、CWD... - 有很多)
当段不完全相同(例如mov [ds:bp], ...vs. mov [bx],...)时,试图避免段寄存器前缀的成本。
避免由于“MOD/RM”字段的限制而无法编码的地址计算(例如mov [di+si], ...) 大多数与 32/64 位代码无关,任何 reg 都可以是基础或(ESP/RSP 除外)索引。
避免 64 位代码中的 REX 前缀(例如mov ebx,1vs. mov r8d,1)
假设您将累积/中间值存储在 %ebx 而不是 %eax 中,后者传统上用于此目的。这是不好的做法吗?会影响性能吗?
一般来说; 没关系(不是不好的做法,也不会影响性能);然而,这可能取决于周围的代码(稍后如何使用该值)并且可能会提高性能或降低性能。
更具体地说,即使所有寄存器都相同,也难以实现最佳寄存器分配(NP 完全问题);和 80x86(在某些情况下所有寄存器都不相同)使得实现最佳寄存器分配变得更加困难。(并将寄存器分配与指令调度联系起来,例如以不同的顺序执行操作以最小化数据进/出寄存器的移动,其中特定指令需要它们。)
\n\n\n假设您将累积/中间值存储在 %ebx 而不是传统上用于此目的的 %eax 中。这是不好的做法吗?会影响性能吗?
\n
在极少数情况下,它会影响性能。例如,对于adc eax, imm32指令,有比其他寄存器的编码更短的特殊编码(参见https://www.felixcloutier.com/x86/adc);汇编程序通常使用这种较短的编码。
然而,在最新的 Intel 处理器上,较短的编码需要更多的 \xc2\xb5ops 并且具有更高的延迟;请参阅哪个 Intel 微架构引入了 ADC reg,0 单 uop 特殊情况?
\n| 归档时间: |
|
| 查看次数: |
1194 次 |
| 最近记录: |