December 06, 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.