Page 1 of 1

Inline assembly in the GNU compiler

Posted: Sat Jun 25, 2011 7:28 pm
by lpcstr
I've been using GCC pretty much exclusively for the last several months, and I really like it compared to MSVC, but there is one aspect of GCC that I cant stand and luckily have not had to use too much, until now, and that is inline ASM.

First off, I can't stand AT&T syntax, which is the default. I refuse to even look at the stuff, I'll run it through a conversion program if I have to. That by itself isn't too much of a problem since GCC does have a -masm=intel option, but the other problem I have is how you inline the code. It's extremely clumsy and confusing for me. In MSVC, it's so easy and clean there is no contest.

Code: Select all

int FuncAdd(int a, int b)
{
    _asm
    {
        mov eax, a
        add eax, b
    }
}
It doesn't get any simpler or cleaner than that, at least not from my point of view. I realise GCC has to support more architectures than I could even name off the top of my head, and this is probably why they chose to do it the way they did, but I need something that works for me, and I don't target hardware other than x86/AMD64. I've read that Apples' GCC has a option -fasm-blocks which allows you to use the same style asm syntax as MSVC. Is there some sort of identical extension I could use with GCC?

Re: Inline assembly in the GNU compiler

Posted: Sat Jun 25, 2011 8:58 pm
by NickJohnson
In general, inline assembly is a bad idea. It's a compiler-specific extension (as you have seen) and is therefore even less portable than assembly. I would highly recommend using an external assembler (which could also be more easily set to use Intel syntax) and then linking the assembler-generated object files with the compiler-generated ones. If you're using just C, this should be quite straightforward, and even if you're using C++, the name mangling is not that hard to deal with. You should also make sure to read up on whichever C calling convention (most likely cdecl) you're using.

Re: Inline assembly in the GNU compiler

Posted: Sat Jun 25, 2011 11:07 pm
by Brynet-Inc
I'm not sure how this obvious solution escapes most opponents of inline assembler, oh right, they're also opposed of learning.. that was stupid, I feel very silly now.

Re: Inline assembly in the GNU compiler

Posted: Sat Jun 25, 2011 11:56 pm
by lpcstr
NickJohnson wrote:In general, inline assembly is a bad idea. It's a compiler-specific extension (as you have seen) and is therefore even less portable than assembly. I would highly recommend using an external assembler (which could also be more easily set to use Intel syntax) and then linking the assembler-generated object files with the compiler-generated ones. If you're using just C, this should be quite straightforward, and even if you're using C++, the name mangling is not that hard to deal with. You should also make sure to read up on whichever C calling convention (most likely cdecl) you're using.
You're right. I haven't had much experience with the GCC assembler, but it seems pretty easy to work with compared to the inline assembly.

Code: Select all

.intel_syntax noprefix

.globl FuncAdd

FuncAdd:
	push	ebp
	mov		ebp,	esp
	mov		eax,	DWORD [ebp+4]
	add		eax,	DWORD [ebp+8]
	pop		ebp
	ret

Re: Inline assembly in the GNU compiler

Posted: Sun Jun 26, 2011 1:23 am
by gerryg400

Code: Select all

int FuncAdd(int a, int b)
{
    _asm
    {
        mov eax, a
        add eax, b
    }
}
If you do this to the Microsoft compiler does it know that you've modified the eax register ? The 'complexity' with inline gcc assembler is generally about telling the compiler what you're doing with its registers in a way that allows it to continue with its optimising. This type of feature requires that you learn the syntax. IMHO, it's a small price to pay.

In general I agree with NickJohnson tho, and keep inline assembler to simple things like writing to ports and modifying special purpose registers. I try never to tell the compiler what to do with the eax register.

Re: Inline assembly in the GNU compiler

Posted: Sun Jun 26, 2011 7:58 am
by NickJohnson
berkus wrote:Inline assembly is not hard at all, all you need is just READ a single page in gcc manual. I know it's too hard for most coders, to READ.
I never said that it was hard, just that it was nonstandard and unnecessary (in the vast majority of cases.) I would make a similar argument against nested functions, even though they're very straightforward to use. A little -pedantic can't hurt.

Re: Inline assembly in the GNU compiler

Posted: Sun Jun 26, 2011 8:53 am
by JamesM
gerryg400 wrote:

Code: Select all

int FuncAdd(int a, int b)
{
    _asm
    {
        mov eax, a
        add eax, b
    }
}
If you do this to the Microsoft compiler does it know that you've modified the eax register ? The 'complexity' with inline gcc assembler is generally about telling the compiler what you're doing with its registers in a way that allows it to continue with its optimising. This type of feature requires that you learn the syntax. IMHO, it's a small price to pay.

In general I agree with NickJohnson tho, and keep inline assembler to simple things like writing to ports and modifying special purpose registers. I try never to tell the compiler what to do with the eax register.
Yes, it does.

GCC style inline assembler is pointlessly complicated - ARM's compiler does it in the same (far superior) way as MSVC, by allowing any C expression as a register or memory location.

Re: Inline assembly in the GNU compiler

Posted: Sun Jun 26, 2011 10:19 am
by Owen
JamesM wrote:
gerryg400 wrote:

Code: Select all

int FuncAdd(int a, int b)
{
    _asm
    {
        mov eax, a
        add eax, b
    }
}
If you do this to the Microsoft compiler does it know that you've modified the eax register ? The 'complexity' with inline gcc assembler is generally about telling the compiler what you're doing with its registers in a way that allows it to continue with its optimising. This type of feature requires that you learn the syntax. IMHO, it's a small price to pay.

In general I agree with NickJohnson tho, and keep inline assembler to simple things like writing to ports and modifying special purpose registers. I try never to tell the compiler what to do with the eax register.
Yes, it does.

GCC style inline assembler is pointlessly complicated - ARM's compiler does it in the same (far superior) way as MSVC, by allowing any C expression as a register or memory location.
If my memory is correct, MSVC only allows variables to be used as memory operands. In ARMCC, __asm { mov r0, #0 } doesn't guarantee that r0 is actually r0; ARMCC's inline assembler is a high level assembler, and r0-r12 are actually implicitly defined variables. I'd say ARMCC's embedded assembler is a closer analogue of GCC inline assembly in some regards - but embedded assembler is never inlined.

This all said: There is not real need for the complexity of GCC inline assembler - if the compiler parsed the assembler source and understood the applicable constraints

Re: Inline assembly in the GNU compiler

Posted: Sun Jun 26, 2011 10:30 am
by Love4Boobies
NickJohnson wrote:
berkus wrote:Inline assembly is not hard at all, all you need is just READ a single page in gcc manual. I know it's too hard for most coders, to READ.
I never said that it was hard, just that it was nonstandard and unnecessary (in the vast majority of cases.) I would make a similar argument against nested functions, even though they're very straightforward to use. A little -pedantic can't hurt.
The advantage to using inline assembly is that you don't need to know what ABI the compiler uses. Although using a different compiler is probably out of the question (as almost none of them use the asm keyword similarly), compilers may be configurable. With external assembly, you need different object files for every compiler setting.

Re: Inline assembly in the GNU compiler

Posted: Sun Jun 26, 2011 11:01 am
by Owen
Another advantage: Let me see you write something like this without inline assembler:

Code: Select all

template<typename T> 
inline T atomicSwap(volatile T& lhs, const T& rhs)
{
    __asm__ ("xchg %[lhs], %[rhs]" : [lhs] "+m" (lhs), [rhs] "+r" (rhs));
    return rhs;
}