Thread overview
syntactic sugar for asm functions
Feb 27, 2002
Pavel Minayev
Feb 27, 2002
DigitalMars
Feb 27, 2002
Walter
Feb 27, 2002
Pavel Minayev
Feb 27, 2002
Walter
Feb 27, 2002
Pavel Minayev
Feb 27, 2002
Walter
February 27, 2002
I remember I've raised this topic long ago, but it wasn't much discussed and I've thought it's time to raise it again since D now has inline asm.

What about allowing function body to be a single asm statement?

    extern(C) uint crc32(void* data, int len) asm
    {
        // assembler goes here
    }

This is a very nice feature Borland Pascal implementations have, it makes the code somewhat neater compared to:

    extern(C) uint crc32(void* data, int len)
    {
        asm
        {
            // assembler goes here
        }
    }

Not a big change anyhow... what do you think of it?


February 27, 2002
Actually... I prefer the 2nd form and think it is much more obvious as to intent.

Gary.

Pavel Minayev <evilone@omen.ru> wrote in message news:a5ietg$p0l$1@digitaldaemon.com...
> I remember I've raised this topic long ago, but it wasn't much discussed and I've thought it's time to raise it again since D now has inline asm.
>
> What about allowing function body to be a single asm statement?
>
>     extern(C) uint crc32(void* data, int len) asm
>     {
>         // assembler goes here
>     }
>
> This is a very nice feature Borland Pascal implementations have, it makes the code somewhat neater compared to:
>
>     extern(C) uint crc32(void* data, int len)
>     {
>         asm
>         {
>             // assembler goes here
>         }
>     }
>
> Not a big change anyhow... what do you think of it?
>
>


February 27, 2002
"Pavel Minayev" <evilone@omen.ru> wrote in message news:a5ietg$p0l$1@digitaldaemon.com...
> What about allowing function body to be a single asm statement?
>     extern(C) uint crc32(void* data, int len) asm
>     {
>         // assembler goes here
>     }
> This is a very nice feature Borland Pascal implementations have,
> it makes the code somewhat neater compared to:
>     extern(C) uint crc32(void* data, int len)
>     {
>         asm
>         {
>             // assembler goes here
>         }
>     }
> Not a big change anyhow... what do you think of it?

I think the second one is better because I see an attribute as part of the interface a function presents to the world, and how it's implemented is an internal issue. In the C world, there's that declspec(naked) attribute which is just in the wrong place. Hence, in D, the naked pseudo-op appears inside the AsmStatement.


February 27, 2002
"Walter" <walter@digitalmars.com> wrote in message news:a5j6os$14dc$1@digitaldaemon.com...

> I think the second one is better because I see an attribute as part of the interface a function presents to the world, and how it's implemented is an internal issue. In the C world, there's that declspec(naked) attribute
which
> is just in the wrong place. Hence, in D, the naked pseudo-op appears
inside
> the AsmStatement.

Was I speaking of naked p-op in asm blocks? No! Let it be as it is now. What I want is to have a clear way to identify that the whole function is written in assembler. There are some reasons for it other than just size of code:

1) It eliminates a nasty "missing return" bug: even though
   you have a RET inside your asm block, you have to add one
   just to stop compiler from complaining... I wonder if it
   gets optimized away BTW?

        extern(Windows) int foo(int n)
        {
            asm
            {
                enter 0, 0;
                mov EAX, [EBP+8];
                mul EAX;
                leave;
                ret 4;
            }
            return 0;    // stupid!
        }

2) It makes it possible for the compiler to check which calling
   convention is used for the function, and stop with an error
   if it is the default extern(D) (since it's implementation-
   defined, and thus shouldn't be used with assembler code).

3) It clearly states that an implicit naked pseudoop should
   be applied to the function.


February 27, 2002
"Pavel Minayev" <evilone@omen.ru> wrote in message news:a5jaq0$16du$1@digitaldaemon.com...
> "Walter" <walter@digitalmars.com> wrote in message news:a5j6os$14dc$1@digitaldaemon.com...
> > I think the second one is better because I see an attribute as part of
the
> > interface a function presents to the world, and how it's implemented is
an
> > internal issue. In the C world, there's that declspec(naked) attribute
> which
> > is just in the wrong place. Hence, in D, the naked pseudo-op appears
> inside
> > the AsmStatement.
> Was I speaking of naked p-op in asm blocks? No!

True, but it is relevant. Read on...

> Let it be as it
> is now. What I want is to have a clear way to identify that the
> whole function is written in assembler.

"naked" serves that purpose.

> There are some reasons
> for it other than just size of code:
> 1) It eliminates a nasty "missing return" bug: even though
>    you have a RET inside your asm block, you have to add one
>    just to stop compiler from complaining... I wonder if it
>    gets optimized away BTW?
>
>         extern(Windows) int foo(int n)
>         {
>             asm
>             {
>                 enter 0, 0;
>                 mov EAX, [EBP+8];
>                 mul EAX;
>                 leave;
>                 ret 4;
>             }
>             return 0;    // stupid!
>         }

Yes, that is stupid. Using inline asm should prevent any messages about missing return bugs.

        extern(Windows) int foo(int n)
        {
            asm
            {
                naked;
                enter 0, 0;
                mov EAX, n[EBP];
                mul EAX;
                leave;
                ret 4;
            }
    }


> 2) It makes it possible for the compiler to check which calling
>    convention is used for the function, and stop with an error
>    if it is the default extern(D) (since it's implementation-
>    defined, and thus shouldn't be used with assembler code).

The presumption is that if you use naked inline asm, you know what you're doing and accept the risk that calling conventions differ/change. To be more forgiving of calling convention changes, do not use naked.

> 3) It clearly states that an implicit naked pseudoop should
>    be applied to the function.

Yes, it's an alternate way of doing that, but I don't see what it adds that's worth the special case in the grammar.



February 27, 2002
"Walter" <walter@digitalmars.com> wrote in message news:a5jc7h$171k$1@digitaldaemon.com...

> > Let it be as it
> > is now. What I want is to have a clear way to identify that the
> > whole function is written in assembler.
>
> "naked" serves that purpose.

I thought it means that programmer is responsible for prolog/epilog code, nothing more... so you could write:

    extern(Windows) int foo(int n)
    {
        asm { enter 0, 0; }
        n = (n + 2) * 3 / 4;
        asm
        {
            mov EAX, [EBP+8]
            leave
            ret
        }
    }


> Yes, that is stupid. Using inline asm should prevent any messages about missing return bugs.

Either this, or check for RET in asm blocks... but that's not very portable. So it's better to assume that this smart guy who wrote that knows what he's doing. =)

> The presumption is that if you use naked inline asm, you know what you're doing and accept the risk that calling conventions differ/change. To be
more
> forgiving of calling convention changes, do not use naked.

Using asm with extern(D) doesn't make sence at all, because the convention is not specified, and, in general, may vary from function to function (for optimization reasons). So it should be prohibited, IMO.

> > 3) It clearly states that an implicit naked pseudoop should
> >    be applied to the function.
>
> Yes, it's an alternate way of doing that, but I don't see what it adds that's worth the special case in the grammar.

1 less level in the indentation =)



February 27, 2002
"Pavel Minayev" <evilone@omen.ru> wrote in message news:a5jhsb$19i2$1@digitaldaemon.com...
> "Walter" <walter@digitalmars.com> wrote in message news:a5jc7h$171k$1@digitaldaemon.com...
> > > Let it be as it
> > > is now. What I want is to have a clear way to identify that the
> > > whole function is written in assembler.
> > "naked" serves that purpose.
> I thought it means that programmer is responsible for
> prolog/epilog code, nothing more... so you could write:
>     extern(Windows) int foo(int n)
>     {
>         asm { enter 0, 0; }
>         n = (n + 2) * 3 / 4;
>         asm
>         {
>             mov EAX, [EBP+8]
>             leave
>             ret
>         }
>     }

Yes, you're correct, but I think you'll also see that naked serves the purpose of indicating the whole thing is in assembly, too.


> > Yes, that is stupid. Using inline asm should prevent any messages about missing return bugs.
> Either this, or check for RET in asm blocks... but that's not very portable. So it's better to assume that this smart guy who wrote that knows what he's doing. =)

There are many ways to return using asm, not just with a RET, so the assumption is the programmer knows what he's doing.