5

I'm just exploring including assembly inside C++ source code. It seems it starts with a call to asm() but I've also seen _asm() and __asm(). What are the differences between the underscores? If relevant I'm most interested in GNU compiler.

EDIT: from this forum

_asm - simply invokes the inline assembler
__asm - is treated like an intrinsic function call

Not sure if this is true or baloney?

Celeritas
  • 14,489
  • 36
  • 113
  • 194
  • And what about `__asm__()`? – Aracthor Mar 12 '16 at 03:12
  • 1
    For the record, don't. Write .asm files that you can assemble using an assembler, such as YASM, and then link them in as externals. This is because inline assemblers behave differently in different compilers, namely on Windows. Further, IIRC 64-bit inline assembly isnt supported in a loy of compilers. – Qix - MONICA WAS MISTREATED Mar 12 '16 at 03:34
  • 1
    @Qix: With GCC's inline assembly syntax you can specify the data flow for short assembly blocks, which is incredibly useful for things like defining short atomic primitives which can then be inlined into the rest of your code. It ends up being much shorter and easier than .asm blocks and it lets GCC allocate the registers. I agree that for anything longer you would want to have assembly in its own file, but that's not the only case you'd want to use assembly for. – Dietrich Epp Mar 12 '16 at 04:12
  • See also [the end of this answer](http://stackoverflow.com/a/34522750/224132) for guides to using GNU C inline asm to make code that doesn't suck (e.g. avoid tons of extra `mov` instructions at the start/end, and let the compiler choose scratch regs for you). And also some explanation of why GNU C inline asm is one of the hardest ways to learn assembly. That question is linked from [the x86 tag wiki](http://stackoverflow.com/tags/x86/info), but many of the points are not x86-specific. – Peter Cordes Mar 12 '16 at 05:17
  • I posted examples of MSVC and GNU C functions wrapping the `idiv` instruction over on the [other question](http://stackoverflow.com/questions/3323445/what-is-the-difference-between-asm-and-asm) that this is a dup of. MSVC wastes about 8 instructions getting into / out of inline asm through memory instead of registers. Mostly just because I finally got curious enough to try it and see just how bad MSVC syntax is for this sort of thing. – Peter Cordes Mar 12 '16 at 15:56
  • This isn't a duplicate. The other question is about the different inline assembly syntaxes of different compilers. This question is about different inline assembly keywords used by the same compiler. – Ross Ridge Mar 12 '16 at 16:03

3 Answers3

7

C++ doesn't have a standard, portable way to include inline assembly. Inline assembly is, almost by definition, a non-standard, non-portable thing.

However, if you've profiled your application and discovered that it needs tuning in a particular area that isn't served well enough by optimized C++ and/or intrinsics, I'd recommend putting the assembly into its own file(s) that are conditionally assembled by the appropriate tool for each platform the code is intended to run on. You would also want a native C++ implementation for platforms whose assembly language you don't support.

As an aside, I've used GNU's inline asm variants in the past, and I have to say they tend to make your code look really ugly and opaque to another programmer. If you're writing bare-metal code that simply has to have maximum bandwidth, well, okay, but if you want something long-term maintainable... maybe favor that over performance.

Aiken Drum
  • 573
  • 1
  • 3
  • 24
  • Good advice. I would emphasise that you really need to take a good hard look at your reasons for including assembly. Unless you are writing for a microcontroller or are writing a device driver or system software it is almost always not worth the downside of unmaintainable and non-portable code. Well written C code can be made almost as fast as the best hand written assembly, and will often be faster as it is difficult make the best use of the multitude of instructions that are available on a typical processor. Also, compilers automatically use optimising tricks you may not be aware of. – Trevor Mar 12 '16 at 04:22
  • ASM can be very maintainable and portable - finding other devs that can do such things, though, is the tricky part. – Qix - MONICA WAS MISTREATED Mar 12 '16 at 07:33
  • 2
    So to confirm `asm()` technically isn't part of the C++ language, it's more a construct of the compiler? – Celeritas Mar 12 '16 at 11:37
  • What do you mean write a separate file containing assembly and include it when compiling the C++? Is [this](http://stackoverflow.com/questions/8054362/mixing-c-and-assembly-files) what you had in mind? – Celeritas Mar 12 '16 at 11:48
  • That's *almost* what they are talking about. It shows creating a separate file and how to compile/link it. However, the fact that they are making a 'naked' function means that what they put in the asm file is probably different than what you need (for example they have no prologue and no return statement, etc). Also, 'asm' **is** mentioned in the c standard as something that c compilers can optionally support. But the details of *how* they support it are left undefined. – David Wohlferd Mar 12 '16 at 20:38
  • @DavidWohlferd if `asm` is mentioned in the c standard, what does @AikenDrum mean by "C++ doesn't have a standard, ...way to include inline assembly. " – Celeritas Mar 12 '16 at 23:08
  • Examples: If your asm modifies the contents of a register, do you have to restore it when you are done? Can asm (safely) read/write the contents of global variables? When optimizing, where does the asm go in relation to all the intermingled instructions being generated? How are inputs/outputs passed to/from the asm? Since the standards don't address any of these points, every compiler is free to implement their own solutions. And they do. – David Wohlferd Mar 13 '16 at 01:15
  • @Celeritas Sorry, had a major windstorm and extended power outage here. :) The naked function in that question you referenced is a function for which C++ won't generate any code at all, whereas normally even a blank function has a hidden prologue and epilogue to handle the stack and return. However, the chosen answer to the question does indeed include an example of my suggestion of having an asm file and referencing its symbol(s) in C++. As for asm(), yes, it's mentioned in the standard, but no standard exists for its actual contents, which is what I meant. Apologies for any confusion. – Aiken Drum Mar 15 '16 at 10:59
  • @Qix I suppose asm can be portable within the same architecture. My background is in embedded stuff that runs on multiple architectures, so the concept of portable asm is a bit more foreign to me. Writing portable asm for MIPS, PowerPC, x86, x64, and ARM is impossible, especially if you're doing finicky stuff like vector operations. You basically have to #ifdef to hell and back or use separate files or something. – Aiken Drum Mar 15 '16 at 11:06
3

With the GNU C/C++ compiler the asm, _asm, __asm, and __asm__ keywords all mean and do the same thing. The asm keyword is the one you should normally when writing inline assembly for GCC. In most cases where you see any of the other keywords used it's a mistake and the author is needlessly typing extra characters. The __asm__ keyword exists only for headers files that need to be compatible with when one of GCC's strict conformance options are used.

GCC's use of the asm keyword isn't compatible with the C and C++ standards. These standards allow programs to use asm as an identifier, for example, in variable or function names. Normally GCC doesn't allow this, but in it's strict conformance modes (eg. -std=c99) it doesn't treat asm a keyword so it can be used as identifier. Header files that use inline assembly and meant to be used in various different projects can use the __asm__ keyword instead of the asm.

The other two keywords _asm and __asm shouldn't be used at all as they don't seem to be formally documented.

Ross Ridge
  • 38,414
  • 7
  • 81
  • 112
0

@Aiken Drum provides a good answer so I won't restate his points (although I think they need careful consideration) but I think your question is more asking about the differences between the keywords.

Essentially there are no differences with the underscore versions, they are just used by different compilers. You need to identify the correct version for your compiler and compiler settings. For gcc/clang I believe this is asm or __asm__ (may be affected by compiler options) and for MSVC this is __asm. Intel uses asm, __asm and __asm__. I'm not sure what compiler uses _asm.

The many differences are another good reason to avoid inline assembler, but you really should avoid assembler full stop.

Trevor
  • 311
  • 2
  • 6