gcc assembly x86-64

¿Por qué GCC generó mov% eax,% eax y qué significa?



assembly x86-64 (1)

GCC 4.4.3 generó el siguiente ensamblaje x86_64. La parte que me confunde es el mov %eax,%eax . Mover el registro a sí mismo? ¿Por qué?

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

El código de C ++ para esta función es:

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;

Un le_uint32_t es una clase que envuelve operaciones de byte-swap en máquinas big-endian. En x86 no hace nada. La función used_p() calcula un puntero desde el mapa base + desplazamiento y devuelve un puntero del tipo correcto.


En x86-64, las instrucciones de 32 bits se extienden implícitamente a cero: se borran los bits 32-63. Así que a veces es por eso que verás instrucciones que parecen extrañas.

Sin embargo, el mov anterior también es de 32 bits, por lo que la mitad alta de %rax ya está borrada. El mov %eax,%eax parece ser un NOP.