0

I have the below snippet of code, and here I want to pass the value of variable num by register rax, but it seems in the assembly code, clang doesn't use rax directly. Rather, it saves the value of num on the stack and then passes the value on the stack to the rsi register which the behavior is different from GCC. Why? BTW, I didn't use any optimization flags in the compilation command.

C Code:

#include <stdio.h>
int main(void) {
  register long num asm("rax") = 0x100000000;
  printf("%ld\n", num);
  return 0;
}

Assembly Code (Clang):

main:                                   # @main
        pushq   %rbp
        movq    %rsp, %rbp
        subq    $16, %rsp
        movl    $0, -4(%rbp)
        movabsq $4294967296, %rax               # imm = 0x100000000
        movq    %rax, -16(%rbp)
        movq    -16(%rbp), %rsi  # <- here, for calling printf, the parameter is not passed directly from register, -
                                 # but indirectly from a stack location. Why?
        movabsq $.L.str, %rdi
        movb    $0, %al
        callq   printf
        xorl    %eax, %eax
        addq    $16, %rsp
        popq    %rbp
        retq
.L.str:
        .asciz  "%ld\n"

Assembly Code (GCC):

.LC0:
        .string "%ld\n"
main:
        pushq   %rbp
        movq    %rsp, %rbp
        movabsq $4294967296, %rax
        movq    %rax, %rsi    # <-
        movl    $.LC0, %edi
        movl    $0, %eax
        call    printf
        movl    $0, %eax
        popq    %rbp
        ret
0

2 Answers 2

1

Why? BTW, I didn't use any optimization flags in the compilation command.

Without optimization, compiler is free to generate suboptimal code with extra moves.

With -O2 clang-11 produces nearly exactly the same code as GCC:

        pushq   %rax
        movabsq $4294967296, %rsi               # imm = 0x100000000
        movl    $.L.str, %edi
        xorl    %eax, %eax
        callq   printf
...
Sign up to request clarification or add additional context in comments.

2 Comments

But in this case, the rax is not used for storing the value 0x100000000 here.
Becavalier, You don't use num in any inline assembly statements, so the compiler has no reason to load the value into eax.
1

register ... asm("regname") GNU C explicit-register variables
don't break or affect the calling convention in any way.

As documented in the manual, the only guaranteed behaviour is for operands to extended asm statements like asm("..." : "=r"(var)), forcing which reg "r" picks.

It doesn't make callers pass args in the wrong registers to function calls.

Any behaviour other than around an asm statement is just an implementation detail. (GCC used to document stronger behaviour, but they decided to undocument = unsupport stuff other than this. The actual behaviour was never calling-convention breaking.)

e.g. Un-optimized clang output does happen to materialize the value in RAX, and it's still there when calling printf because its low byte is 0, and clang only merged a 0 (number of args in XMM regs) into the low byte of RAX (AL), unlike GCC avoiding false dependencies by zeroing the whole RAX.


Other ways of getting a custom calling convention for a single function call:

None that I know of, unless the convention you want is one of the one the compiler already knows. e.g. you can put __attribute__((ms_abi)) or __attribute__((sysv_abi)) on a function prototype.

Other than that, you can in theory put a call instruction in an inline-asm statement, but only if you adjust RSP around it to avoid stepping on the red-zone, and declare clobbers on every call-clobbered register (including integer, MMX, x87, and zmm0..31 and k0..7 or ymm0..15, MPX bnd0..3, maybe that's all for now. And of course "memory"). Or read-write or matching-constraint operands for arg-passing registers. This is highly not recommended, and a huge pain.

See also these Q&As for examples, but really it would be best to avoid this if you can:

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.