Search code examples
linuxassemblyx86-64cpu-registersatt

Assembly - Why strtol clobbers %rcx register?


Context :

Linux 64.

GCC 4.8.2 (with -O3 -march=native)

The x86_64 abi under my left hand, opened at page 21.

The C code :

int main (int argc, char ** argv) {

     printf("%d %s\n", atoi(argv[2]),argv[1] );
}

The assembly code :

(notice that the compiler replaced atoi with strtol by itself)

...
    movl    $10, %edx
    movq    16(%rsi), %rdi
    movq    8(%rsi), %rbx
    xorl    %esi, %esi
    call    strtol
    movl    $.LC0, %edi
    movq    %rbx, %rdx
    movl    %eax, %esi
    xorl    %eax, %eax
    call    printf
    xorl    %eax, %eax
    popq    %rbx
...

The question :

%rcx should be reserved for the 4th input integer argument.

strtol has 3 input args (respectively registers %rdi, %rsi, %rdx) and one return, %eax.

Why then is %rcx clobbered ? This code won't make it :

...
    movl    $10, %edx
    movq    16(%rsi), %rdi
    movq    8(%rsi), %rcx <-- look I replaced with %ecx
    xorl    %esi, %esi
    call    strtol
    movl    $.LC0, %edi
    movq    %rcx, %rdx <-- look I replaced with %ecx
    movl    %eax, %esi
    xorl    %eax, %eax
    call    printf
    xorl    %eax, %eax
    popq    %rbx
...

Thanks


Solution

  • In each calling convention I know there are some registers that may be modified by the called function and some which must not be modified.

    In 32-bit programs ecx may be modified while ebx must not be modified - or, to be more exact - must be re-stored before returning. For 64-bit programs this rule seems to be the same.

    Indeed most functions modify most registers; for this reason there is a "popq %rbx" at the end of the code you posted because rbx must not be modified by the function. rcx may be modified and strtol obviously does that!