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?

Hello, i think this should be here (https://dlang.org/spec/abi.html) because myself i never remember them correctly without playing a bit with a disassembler.
After playing a bit:

Linux x86_64:

extern(D) void Foo(MyStruct* s1, MyStruct* s2, MyStruct* s3, MyStruct* s4)
{
    asm
    {
        naked;
        // rcx -> s1
        // rdx -> s2
        // rsi -> s3
        // rdi -> s4
        ret;
    }
}

====================

Linux x86 / Window x86:

extern(D) void Foo(MyStruct* s1, MyStruct* s2, MyStruct* s3, MyStruct* s4)
{
    asm
    {
        naked;
        // ebx -> s1
        // edx -> s2
        // ecx -> s3
        // eax -> s4
        ret;
    }
}

====================

Win64 has a different calling convention than Linux64, i cant remember the difference.

====================

Linux x86_64 example:

module runnable;

import std.stdio;

alias writeInt = writeln!int;

struct MyStruct{int i;}

extern(D) void foo(MyStruct* s1, MyStruct* s2, MyStruct* s3, MyStruct* s4)
{
    asm
    {
        naked;
mov RAX, RDI; // move s4 here since we call something...

        push    RDX;    // save s2
        push    RSI;    // save s3
        push    RAX;    // save s4
        mov     RDI, MyStruct.i.offsetof[RCX];
        call    writeInt;
        pop     RAX;    // restore...
        pop     RSI;
        pop     RDX;

        push    RSI;  // save s3
        push    RAX;  // save s4
        mov     RDI, MyStruct.i.offsetof[RDX];
        call    writeInt;
        pop     RAX; // restore
        pop     RSI;

        push    RAX; // save s4
        mov     RDI, MyStruct.i.offsetof[RSI];
        call    writeInt;
        pop     RAX; // restore


        mov     RDI, MyStruct.i.offsetof[RAX];
        call    writeInt;

        ret;
    }
}

void main()
{
    MyStruct s1 = MyStruct(1);
    MyStruct s2 = MyStruct(2);
    MyStruct s3 = MyStruct(3);
    MyStruct s4 = MyStruct(4);
    foo(&s1, &s2, &s3, &s4);
}

here too :

https://run.dlang.io/is/CWd4aO

Reply via email to