On Sunday, 30 September 2018 at 10:46:33 UTC, Sjoerd Nijboer wrote:
I'm kinda puzzled.

I'm having trouble getting started with inline asm in D.
Suppowse I have the following:

void Foo(MyStrunct* first_arg, MyStrunct* second_arg)
{
    asm
    {
        naked;
        version(X86)
        {
            /* Do something with the content of I and J. */
        }
        version(X86_64)
        {
            /* Do something with the content of I and J. *?
        }
    }
}

void Bar()
{
    MyStrunct heapStructA, heapStructB;

    // do some initialization.

    Foo(heapStructA, heapStructB);
}

Suppose I would like to pass first_arg and second_arg by register to `Foo`, what calling convention should I use? I'm having trouble identifying the correct calling convention I should be using for X86 and X86_64 in D.

I've tried a couple using https://godbolt.org/ and DMD parameters '-g -m32', but I can't seem to find any that will pass by register. Is there one? Will it also work for LDC and GDC?

1) `asm {}` is supported by DMD and LDC, but not by GDC.
2) `extern(D)` reverses the args - `foo(a, b)` is actually `foo(b, a)` on a lower level. 3) The 32-bit x86 D calling convention (independent from OS) is specified here: https://dlang.org/spec/abi.html#function_calling_conventions All args are passed on the stack, except for the last one under certain circumstances, see point 38.12.3.3. 4) For x86_64, there are 2 (completely different) ABIs, Win64 and the System V one. Specs can be found online.

In your case:

void Foo(MyStrunct* first_arg, MyStrunct* second_arg)
{
    asm { naked; }
    version (D_InlineAsm_X86)
    {
        // first_arg is on the stack, at [ESP+4]
        // second_arg is in EAX
    }
    else version (D_InlineAsm_X86_64)
    {
        version (Win64)
        {
            // first_arg is in RDX
            // second_arg is in RCX
        }
        else
        {
            // first_arg is in RSI
            // second_arg is in RDI
        }
    }
}

Reply via email to