X86-64 calling conventions

rumbu via Digitalmars-d digitalmars-d at puremagic.com
Tue Dec 6 11:44:09 PST 2016


I know already that the D calling convention x86-64 is not the 
same as the one of the corresponding C compiler (register order 
is reversed on Windows and Linux) - details here: 
http://forum.dlang.org/post/mailman.1981.1415996395.9932.digitalmars-d@puremagic.com


But even with extern(C), there is something wrong on x86-64 when 
passing arrays as parameters.

In x86-32, the D calling convention is clear for arrays (even 
that's not documented, credits go to the std.bigint creator - Don 
Clungston):

void foo(uint[] x, uint p1, uint p2) will be translated to

push x.ptr;
push x.length;
push p1;
push p2;
call foo;

In a "naked" asm context, it's easy to access parameters
p2 = [ESP + 4]
p1 = [ESP + 8]
x.length = [ESP + 12]
x.ptr = [ESP + 16]

---

Now, on x86-64 (Windows), following the same schema, I expected 
something like this:

mov RCX, x.ptr;
mov RDX, x.length;
mov R8, p1;
mov R9, p2;
(standard Windows x86-64 calling convention)

Instead, the compiler generates something very strange:

mov R8, p2   //somehow ok, third parameter (even I expected to be 
the fourth)
mov RDX, p1  //somehow ok, second parameter (even I expected to 
be the third)
mov [RBP-0x10], x.length //why?
mov [RBP-0x08], x.ptr //why?
lea RCX, [RBP-0x10] //pointer to x.length?

Finally we have:
p2 = R8
p1 = RDX
x.length = [RCX]
x.ptr = ?

Now the questions:

1. Is there any intention to correct the registry reversing 
behaviour for extern(D)?
2. Will someone fully document the ABI for x86-32 and x86-64?
3. How do I find in a naked asm context on x86-64 the starting 
address of an array passed as parameter?

Thanks.




More information about the Digitalmars-d mailing list