在英特尔文档中,我们有ADC
的下一个定义:
Op / En操作数1操作数2 .....
RM ModRM:reg(r,w)ModRM:r / m(r)
MI ModRM:r / m(r,w)imm8
我是AL / AX / EAX / RAX imm8
现在是asm
代码的一个小例子:
asm (
"adc -Ox12(%rbp), %rax \n\t" //1
"adc -Ox12(%rbp), %rdx \n\t" //2
"adc -Ox12(%rbp), %r8 \n\t" //3
"adc -Ox12(%rbp), %R11 \n\t" //4
"adc %r8 , %rdx \n\t" //5
"adc %r8 , %rax \n\t" //6
"adc $3 , %rdx \n\t" //7
"adc $3 , %rax \n\t" //8
);
你能告诉我哪一组是每组中最快的指令吗?为什么?
我有这个问题,因为在英特尔他们引用%RAX
寄存器。对方慢了吗?
答案 0 :(得分:2)
Note: For everything below I'm assuming modern 80x86 (anything from the last 10 years or so).
For the first group; the first instruction has a (very slightly) increased chance of causing a cache miss or a dependency stall (caused by either RBP, RAX or the carry flag being modified by instructions leading up to it).
For all other instructions, there's a dependency on eflags (they have to wait until the carry flag from the previous instruction is known) and they will all suffer equally from that. More specifically I'd expect the "carry flag dependency" to limit execution to 1 cycle per instruction (with no instructions happening in parallel). That is the most likely bottleneck.
The registers used make no difference (other than dependencies on the previous use of the register).
答案 1 :(得分:2)
即使adc $3 , %rax
也无法使用特殊的rax-only编码REX.W + 15 id ADC RAX, imm32
。
REX.W
+ 15 03 00 00 00
是6个字节。 (adc rax, imm32
)REX.W
+ 83 mod/rm 03
是3个字节。 (adc r/m32, imm8
,其中mod / rm字节将rax
编码为目标,/2
字段中的reg
作为操作码的一部分.still-src操作共享操作) The (16bit version of) both encodings were introduced with 8086。请参阅x86 wiki中的链接。显然,累加器预计会一直用于所有事情,和/或他们没有考虑将来的指令集扩展,所以他们认为值得在特殊al
和{{上花费那么多操作码1}}所有ALU立即指令的版本。
如果查看双操作数整数ALU指令(ax
,and
,or
,sub
等),每个指令都有一个特殊的单字节 - test
和al
/ ax
/ eax
目的地的短时编码,具有全尺寸立即操作数。 (即rax
,而非imm32
符号扩展为32或64b)。每个指令都有两个额外的操作码。
这仅影响x86代码大小。一旦指令被解码,它们的运行方式就没有进一步的区别。请参阅http://agner.org/optimize/以了解有关CPU内部的更多信息。
AMD64本可以将这些技术从64位模式中解放出来,从而释放出更多的编码空间,但他们对于杀死32位可能并不乐观。如果您希望指令在32和64位模式下工作,如果两种模式下的编码相同,则需要较少的解码器晶体管。不过,他们本可以使用imm8
或其他东西的编码空间。不是新奇的SIMD功能,只是简单的一些基本指令。在标志设置操作之前,几乎不能在没有setcc r32
的情况下使用setcc
将完整寄存器归零。无论如何,AMD错过了从x86中删除一些错误的绝佳机会。