inline ASM function calling conventions.

kinke noone at nowhere.com
Sun Sep 30 12:32:08 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?

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
         }
     }
}


More information about the Digitalmars-d-learn mailing list