inline ASM function calling conventions.

Basile B. b2.temp at gmx.com
Sun Sep 30 11:53:17 UTC 2018


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


More information about the Digitalmars-d-learn mailing list