【发布时间】:2016-11-06 15:50:22
【问题描述】:
int sarl_n(int x, char n){
x <<= 2;
x >>= n;
return x;
}
当我使用“gcc -m32 -S sarl_n.c”组装时,它会发出以下代码:
.cfi_startproc
movl 4(%esp), %eax
movsbl 8(%esp), %ecx
sall $2, %eax
sarl %cl, %eax #This is the part which I don't understand
ret
.cfi_endproc
为什么 gcc 使用“迷你寄存器”%cl 而不是大寄存器%ecx?
编辑:我使用 O2 选项来获得更短的汇编代码
【问题讨论】:
-
我猜这是为了优化目的:8 位长的 %cl 比 16 位的 %ecx 存储小结果更好。
-
尝试使用
-O2选项组装它以获得更合理的输出。 -
简单:这是唯一存在的指令版本。请参阅指令集参考。在任何情况下,计数都会被屏蔽,所以没关系。
-
指令将
eax右移cl中的位数。由于对于 32 位 int,移位的最大有用大小是 32(实际上按照 C 标准,我认为它只能是 31),因此该指令不需要全宽寄存器。只需要 5 位,因此英特尔的工程师使用了 8 位寄存器。可能还有一些遗留问题。自 8086 天(70 年代末)以来,cl一直用于轮班计数。 -
@Gene:移位计数被屏蔽到 0..31 范围(或者当操作数大小 = 64 位时为 0..63)。见the SAR insn set ref manual entry。无论如何,关键是
%cl是机器码中的一个隐式操作数:除了操作码本身之外,没有任何位表示“cl”。编译器不可能使用任何其他寄存器,除了 BMI2SARX r32_dest, r/m32_src, r32_count,如果您启用了-march=haswell或-mbmi2,它将使用它。