【问题标题】:How could this assembly be possible?这个大会怎么可能?
【发布时间】: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”。编译器不可能使用任何其他寄存器,除了 BMI2 SARX r32_dest, r/m32_src, r32_count,如果您启用了 -march=haswell-mbmi2,它将使用它。

标签: c gcc assembly x86


【解决方案1】:

下面这行(以前的版本)有问题的原因

sarl    %cl, 8(%ebp)    #This is the part which I don't understand

或(当前版本)

sarl    %cl, %eax       #This is the part which I don't understand

使用%cl 而不是%ecx 是,SAR 操作码仅支持%cl 寄存器作为变量算术移位的输入(通过%cl 次)。

here,我引用:

SAR r/m32, CL     MC   Valid   Valid   Signed divide* r/m32 by 2, CL times.

【讨论】:

  • 如果 r/m32 的部分是 r/m8 ...我会理解,因为 r/m32 表示 32 位的寄存器,对吧?
  • 是的。 r/m32 确实表示 32 位内存地址(如您以前版本中的 8(%ebp))或 32 位寄存器(如当前版本中的 %eax)。 CLIntel 语法 用于 AT&T 语法 %clAT&T 语法还会反转源/目标顺序。所以 AT&T 语法中的 sarl %cl, %eaxIntel 语法 中的 SAR EAX, CL
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-06-24
  • 2011-01-31
  • 1970-01-01
  • 1970-01-01
  • 2020-05-25
  • 2018-11-06
  • 1970-01-01
相关资源
最近更新 更多