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