From the wikipedia x86 calling convention, it says that for the Microsoft x64 calling convention:
The registers RBX, RBP, RDI, RSI, RSP, R12, R13, R14, and R15 are considered nonvolatile (callee-saved).
But for System V AMD64 ABI:
If the callee wishes to use registers RBX, RBP, and R12–R15, it must restore their original values before returning control to the caller.
It did not mention anything about rdi and rsi.
I also read that %rax, %rcx, %rdx, %rdi, %rsi, %rsp, and %r8-r11 are considered caller-save registers (from a pdf)
My question is, is calling convention various across different platform?(I try to write some libc function in asm for unix environment)
I could not find any article discussing about this topic, resources to this topic will be helpful as well. I wanted to know the advantage and disadvantage of these conventions.
RDI and RSI are call-preserved in Windows x64, like EDI & ESI in most 32-bit conventions.
They're call-clobbered (and used for arg-passing) in AMD64 System V, the calling convention used on all x86-64 systems other than Windows and UEFI.
Yes, in all mainstream1 function-calling conventions I'm aware of, the arg-passing registers are call-clobbered. (Except for system-call calling conventions, where normally all regs are preserved except a return value, including arg-passing. Except that x86-64 syscall destroys RCX and R11...)
Specifically in x86-64 System V, all registers other than RBX, RBP, RSP, and R12-R15 are call-clobbered. (That includes xmm0-15, x87/mmx registers, and AVX512 zmm0-31 and k0-k7 mask regs.)
What registers are preserved through a linux x86-64 function call shows the table from the ABI doc.
The calling convention / ABI defines the status of registers as call-preserved or call-clobbered. Different conventions can make different choices.
And yes, Microsoft Windows chose a different calling convention from everyone else: Why does Windows64 use a different calling convention from all other OSes on x86-64? In Windows x64, RDI and RSI are call-preserved, like in most 32-bit calling conventions.
But in x86-64 System V, the designers chose registers from scratch, and (as my answer on that linked question shows) found that using RDI and RSI for the first 2 args saved instructions (when building SPECint with an early x86-64 port of gcc). Probably because gcc at the time liked to inline memset or memcpy using rep stosd, or the library implementation used that.
(It makes no sense to say that RDI and RSI are intrinsically call-clobbered, the x86-64 ISA doesn't define that. It's up to each platform / ABI to choose that.)
Terminology:
I hate the "caller saved" vs. "callee saved" terminology: It's confusing to think from 2 different perspectives (caller and callee), and wrongly implies that every register does get saved somewhere on every call. Also, the names only differ by 1 letter, so aren't very visually distinct when reading.
"Preserved" vs. "clobbered" are great; they work from either perspective. (What a callee will do to your regs, or what you're allowed to do to the caller's regs.) They're also even more self-explanatory than "non-volatile" vs. "volatile" which are also pretty decent terms used in MS docs, although not great choices for a C calling convention since volatile is a type qualifier in C with a different meaning.
Footnote 1: The Irvine32 function library for toy programs for asm beginners makes every register call-preserved, except the return value if there is one. (Void functions preserve even EAX and st0 / xmm0).
It has functions like ReadDec to read a base-10 integer from stdin, as if they were toy system calls.
(What is the Irvine32 library and why do we use it?)
Presumably the implementation just saves/restores registers at the library function entry points, and does something more efficient internally if there are any internal-use-only functions.
Preserve-everything (except the return value if any) conventions like this are possible but not efficient, so no sane compiler / ABI architect would choose that for any ISA, except to simplify things for total beginners by removing the potential bug of having a function call clobber a value in a register you didn't overwrite explicitly.