【发布时间】:2012-08-08 06:39:23
【问题描述】:
GCC 4.4.3 生成了以下 x86_64 程序集。让我困惑的部分是mov %eax,%eax。将寄存器移动到自身?为什么?
23b6c: 31 c9 xor %ecx,%ecx ; the 0 value for shift
23b6e: 80 7f 60 00 cmpb $0x0,0x60(%rdi) ; is it shifted?
23b72: 74 03 je 23b77
23b74: 8b 4f 64 mov 0x64(%rdi),%ecx ; is shifted so load shift value to ecx
23b77: 48 8b 57 38 mov 0x38(%rdi),%rdx ; map base
23b7b: 48 03 57 58 add 0x58(%rdi),%rdx ; plus offset to value
23b7f: 8b 02 mov (%rdx),%eax ; load map_used value to eax
23b81: 89 c0 mov %eax,%eax ; then what the heck is this? promotion from uint32 to 64-bit size_t?
23b83: 48 d3 e0 shl %cl,%rax ; shift rax/eax by cl/ecx
23b86: c3 retq
这个函数的C++代码是:
uint32_t shift = used_is_shifted ? shift_ : 0;
le_uint32_t le_map_used = *used_p();
size_t map_used = le_map_used;
return map_used << shift;
le_uint32_t 是一个在大端机器上包装字节交换操作的类。在 x86 上它什么也不做。 used_p() 函数从映射基址 + 偏移量计算一个指针,并返回一个正确类型的指针。
【问题讨论】:
-
啊 GCC 和它臭名昭著的随机代码生成器..
mov绝对没有意义。即使它是为了对齐(看起来不像),这将是一种完全脑残的方式来实现它——它不是真正的nop,所以它实际上需要时间。 -
AFAIR 这是 gcc-4.3 中的一个错误,它已在 4.6 左右修复。
-
我没有 GCC 4.3.x 或 4.4.x,但 4.5.4 和 4.6.3 都不会为我发出虚假的
mov。