2012-08-10 3 views
23

GCC 4.4.3에서 다음 x86_64 어셈블리가 생성되었습니다. 나를 혼란스럽게하는 부분은 mov %eax,%eax입니다. 레지스터를 자신에게로 이동 하시겠습니까? 왜? 이 기능에 대한GCC에서 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++ 코드는 다음과 같습니다

le_uint32_t
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; 

는 빅 엔디안 시스템에서 바이트 스왑 작업을 래핑하는 클래스입니다. x86에서는 아무것도하지 않습니다. used_p() 함수는지도 기본 + 오프셋에서 포인터를 계산하고 올바른 유형의 포인터를 반환합니다.

+2

참조 http://stackoverflow.com/questions/2703394/whats-the-point-of-lea-eax-eax – nos

+0

@nos : 아마도 가능합니다. 그러나 GCC는 어떤 이유로 그곳에 nop을 원하는가? 맞출 것이 없습니다. –

+0

SHL 명령의 주소가 바이트로만 정렬됩니다. 정렬 할 항목이있는 경우 (다음 명령에 착륙 할 필요가없는 점프 어딘가), 그렇지 않습니다. 이것은 단지 최적화 도구 버그처럼 보입니다. 다른 플래그와 더 최근의 gcc 버전 (4.4.3은 상당히 오래되었습니다)을 시험해보고 어떤 효과가 있는지보십시오. –

답변

22

x86-64에서 32 비트 명령어는 암시 적으로 0으로 확장됩니다. 비트 32-63이 지워집니다. 때로는 이상한 모양의 지침이 나오는 이유가 있습니다.

그러나 앞의 mov도 32 비트이므로 %rax의 상위 절반이 이미 지워져 있습니다. mov %eax,%eax은 NOP 인 것 같습니다.

+0

이런 종류의 NOP는 또한 파이프 라인 최적화의 목적을 수행 할 수 있습니다. – mathk

관련 문제