gccassemblygcc4.8

What‘s the purpose for the Shift operation in the REGSITER_TM_CLONES?


When looking at the assembly code, I don't quite understand what it means to shift operations in register_tm_clones. What is the role of the shift operation?

Comparing assembly code with source code, I thought I had understand the purpose of SUB RAX,6020F8H.The operation is related to the SIZE in source code.Becaause the value of SIZE is zero , I guessed the assembly code is the implement of (TMC_END - TMC_LIST).During debugging, I found that the FOR could only be executed once, or even skipped the size++ to execute the IF statement directly.

source code:

register_tm_clones (void)
{
  void (*fn) (void *, size_t);
  size_t size;

#ifdef HAVE_GAS_HIDDEN
  size = (__TMC_END__ - __TMC_LIST__) / 2;
#else
  for (size = 0; __TMC_LIST__[size * 2] != NULL; size++)
    continue;
#endif
  if (size == 0)
    return;

  fn = _ITM_registerTMCloneTable;
  __asm ("" : "+r" (fn));
  if (fn)
    fn (__TMC_LIST__, size);
}
#endif /* USE_TM_CLONE_REGISTRY */

assembly code:

 register_tm_clones proc near
    mov     eax, 6020F8h  ;.bss 
    push    rbp             
    sub     rax, 6020F8h  ;.bss 
    sar     rax, 3          
    mov     rbp, rsp      ; return address
    mov     rdx, rax        
    shr     rdx, 3Fh        
    add     rax, rdx        
    sar     rax, 1          
    jnz     short loc_400C24

 loc_400C22:                             
    pop     rbp             
    retn                    

 loc_400C24:                             
    mov     edx, 0          
    test    rdx, rdx        
    jz      short loc_400C22 
    pop     rbp             
    mov     rsi, rax        
    mov     edi, 6020F8h    
    jmp     rdx            
 register_tm_clones endp

I would like to know the role of this assembly code for specific operation. Of course, the main still want to know the purpose of the shift operation here. If I can understand this, it's more possible for me to solve other problems. (Maybe I've had some mistakes in my previous understanding of the code, and I hope you can point it out)


Solution

  • The for is not present in the assembly code. It is never seen by the compiler because it is removed by the preprocessor if HAVE_GAS_HIDDEN is set which happens to be the case here.

    The sar rax, 3is due to pointer arithmetic, as the size of the items in the __TMC_LIST__ is 8 bytes, being 2^3.

    The two other shifts are the signed division by two. It's implemented that way to follow the rounding rules for negative numbers. Of course that is not needed but the poor compiler does not know that __TMC_END__ - __TMC_LIST__ >= 0.