Why “mov rcx, rax” is required when calling printf in x64 assembler?

前端 未结 2 1957
闹比i
闹比i 2021-01-27 08:13

I am trying to learn x64 assembler. I wrote \"hello world\" and tried to call printf using the following code:

EXTERN printf: PROC

PUBLIC hello_world_asm

.data         


        
相关标签:
2条回答
  • 2021-01-27 08:56

    It isn't required, this code just wastes an instruction by doing an lea into RAX and then copying to RCX, when it could do

    lea   rcx, hello_msg
    call  printf              ; printf(rcx, rdx, r8, r9, stack...)
    

    printf on 64-bit Windows ignores RAX as an input; RAX is the return-value register in the Windows x64 calling convention (and can also be clobbered by void functions). The first 4 args go in RCX, RDX, R8, and R9 (if they're integer/pointer like here).

    Also note that FP args in xmm0..3 have to be mirrored to the corresponding integer register for variadic functions like printf (MS's docs), but for integer args it's not required to movq xmm0, rcx.


    In the x86-64 System V calling convention, variadic functions want al = the number of FP args passed in registers. (So you'd xor eax,eax to zero it). But the x64 Windows convention doesn't need that; it's optimized to make variadic functions easy to implement (instead of for higher performance / more register args for normal functions).

    A few 32-bit calling conventions pass an arg in EAX, for example Irvine32, or gcc -m32 -mregparm=1. But no standard x86-64 calling conventions do. You can do whatever you like with private asm functions you write, but you have to follow the standard calling conventions when calling library functions.


    Also note that lea rax, offset hello_msg was weird; LEA uses memory-operand syntax and machine encoding (and gives you the address instead of the data). offset hello_msg is an immediate, not a memory operand. But MASM accepts it as a memory operand anyway in this context.

    You could use mov ecx, offset hello_msg in position-dependent code, otherwise you want a RIP-relative LEA. I'm not sure of the MASM syntax for that.

    0 讨论(0)
  • 2021-01-27 08:56

    The Windows 64-bit (x64/AMD64) calling convention passes the first four integer arguments in RCX, RDX, R8 and R9.

    The return value is stored in RAX and it is volatile so a C/C++ compiler is allowed to use it as generic storage in a function.

    0 讨论(0)
提交回复
热议问题