NASM - The Netwide Assembler
NASM Forum => Using NASM => Topic started by: hhh3h on August 15, 2012, 10:25:51 PM
-
Hello, I'm trying to determine the difference between these two 64-bit calling conventions:
- Windows x64 calling convention (a.k.a. what MS calls "native").
- x86-64.org "System V" calling convention:
The first convention is described in multiple articles, blogs, and documentation all over the internet. It seems pretty simple: There the first 4 arguments are passed in registers and additional arguments are passed on the stack. As for the registers, there are 4 for integers and 4 for floating-point types. The MS docs are really useful because they show examples like this (http://msdn.microsoft.com/en-us/library/zthk2dkh.aspx):
func1(int a, int b, int c, int d, int e);
// a in RCX, b in RDX, c in R8, d in R9, e pushed on stack
func2(float a, double b, float c, double d, float e);
// a in XMM0, b in XMM1, c in XMM2, d in XMM3, e pushed on stack
func3(int a, double b, int c, float d);
// a in RCX, b in XMM1, c in R8, d in XMM3
But for the 2nd convention, all there is is page 17 of http://www.x86-64.org/documentation/abi.pdf (http://www.x86-64.org/documentation/abi.pdf). No examples or anything else that I can find except a tiny little thing here (http://www.amd64.org/fileadmin/user_upload/pub/64bit_Linux-Myths_and_Facts.pdf) on slide 28 that only demonstrates a function with 2 args.
Can anyone give me a hand with a few examples of passing function args using the 2nd convention? Either that or perhaps a good reference that explains it clearly? I would appreciate it.
-
The first is used only in Windows API calls (and other internal Windows calls, or callbacks)
The second is used in many NON windows OS's. Wiki explains calling conventions http://en.wikipedia.org/wiki/X86_calling_conventions. I prefer this one over they way Microsoft does it, as it uses more registers to pass params.
Microsoft:
The registers RCX, RDX, R8, R9 are used for integer and pointer arguments (in that order left to right), and XMM0, XMM1, XMM2, XMM3 are used for floating point arguments. Additional arguments are pushed onto the stack (right to left)
Linux (System V)
The registers RDI, RSI, RDX, RCX, R8, and R9 are used for integer and memory address arguments while XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6 and XMM7 are used for floating point arguments. For system calls, R10 is used instead of RCX
-
The stack frame setup for a 64-bit Windows function call is nearly identical in concept to the 32-bit version. Stack space is still allocated for the first four function parameters ( called register shadow space ). It's a pretty clean mapping if you already know the C calling convention.
System V x64 ABI blows any pre-conceived notion of stack setup right out of the water. Any knowledge you may have had previously regarding calling convention has been made obsolete.
Wiring in the NASMX source code portability to account for both Windows and Linux in either 32-bit or 64-bit was quite an undertaking mostly due to the x64 differences.
I flip back and forth between the two calling conventions when discussing which is better as each plays to the strengths of its respective target OS.
-
Another decent reference: http://www.agner.org/optimize/calling_conventions.pdf (http://www.agner.org/optimize/calling_conventions.pdf)
-
Thank you for the explaination. Sorry for the delay in responding but I have bought a book called Assembly Language Step By Step second edition by Duntermann. I'm about 1/3 done. I know it won't cover this topic, but its just to give me more general background so I don't keep having to ask so many questions.
-
i dont see what is not cleared about the system v calling convention in the abi.pdf
it is a little tehnical, but its all there:
first you classify what your passing
args go in RCX, RDX, R8, R9
if they are floats they go into xmm registers and if floats are returned they are returned there
MEMORY types are passed thru the stack(basicaly anything too big to fit into a register)
things are returned in rax
and syscalls now use "syscall" instead of "int somehex"
theres a bit more in the A.2.1 part of the abi.pdf
oh and linux 32bit and amd64 syscalls have different arguments
here's an example of a triangle i had problems with and asked here http://forum.nasm.us/index.php?topic=1454.0
also heres some general code for filehandling under linux
;open
mov rdx, 600o
mov rsi, 0
lea rdi, [file]
mov rax, 2
syscall
mov [fd], rax
you get the file descriptor in rax
;read8
mov rdx, 8
mov rsi, buff
mov rdi, [fd]
mov rax, 0
syscall
buff is where to write sayd read thing
;print8 to stdout
mov rdx, 8
mov rsi, buff
mov rdi, 1
mov rax, 1
syscall
hope this helps a little, im still learning asm so...
i have some linux syscalls in some link somewhere (i think:)) if you need
funny thing is i have to learn to use the stack now because of strtod()
-
oh, forgot to say(but is in the examples) syscalls use rax as the first arg
and since i cant edit...
also some links i found while scouring
on syscalls
http://rayseyfarth.com/asm/pdf/ch12-system-calls.pdf
on x64 asm
http://software.intel.com/en-us/articles/introduction-to-x64-assembly/
idk why i didnt read this yet
http://www.osronline.com/ddkx/kmarch/64bitamd_7qqv.htm
and some syscall numbers
http://www.acsu.buffalo.edu/~charngda/linux_syscalls_64bit.html
and some more of the same syscall numbers(from the kernel source)
http://os1a.cs.columbia.edu/lxr/source/arch/x86/include/asm/unistd_64.h