2

I got the 2 following definition that compile (and work) just fine using XCode LLVM-GCC compiler:

#define SAVE_STACK(v)__asm { mov v, ESP }
#define RESTORE_STACK __asm {sub ESP, s }

However when I change the compiler to Apple LLVM I got the following error:

Expected '(' after 'asm'

I replace the {} with () but that doesn't do the trick, I google on that error couldn't find anything useful... anyone?

McBob
  • 1,011
  • 2
  • 13
  • 25
  • You'll want to use `__asm__("asm code goes here")`, and you'll need to use [AT&T assembly syntax](http://www.ibm.com/developerworks/linux/library/l-gas-nasm/index.html) rather than Intel syntax (and GCC's [extended asm syntax](http://gcc.gnu.org/onlinedocs/gcc-4.7.2/gcc/Extended-Asm.html#Extended-Asm) for accessing named variables). – ildjarn Nov 09 '12 at 03:46
  • @ildjarn Or just use the standard asm keyword. Also I thought clang did have some support intel style inline assembly, though I can't find what I thought was there. The back end does support producing intel style assembly files (`-mllvm -x86-asm-syntax=intel`) and if you just have clang produce the assembly file (`-S`) it will happily insert whatever text you want from an asm statement into the assembly result. – bames53 Nov 09 '12 at 20:01
  • @bames53 : `asm` is only supported in gnu* modes; `__asm__` is supported in all modes. – ildjarn Nov 09 '12 at 20:40
  • @ildjarn Ah, that's only in the case in C. `asm` is part of ISO C++ and clang supports it, including the GNU register extensions, in any C++ mode. – bames53 Nov 09 '12 at 20:57
  • @bames53 : Ah, that's what I get for skimming the docs. Thanks, good to know. :-] – ildjarn Nov 09 '12 at 21:01

2 Answers2

4

The __asm {...} style of inline assembly is non-standard and not supported by clang. Instead C++ specifies inline assembly syntax as asm("..."), note the quotes. Also clang uses AT&T assembly syntax so the macros would need to be rewritten to be safe.

However, some work has been going on to improve support for Microsoft's non-standard assembly syntax, and Intel style assembly along with it. There's an option -fenable-experimental-ms-inline-asm that enables what's been done so far, although I'm not sure when it was introduced or how good the support is in the version of clang you're using. A simple attempt with the code you show seems to work with a recent version of clang from the SVN trunk.

#define SAVE_STACK(v)__asm { mov v, ESP }
#define RESTORE_STACK __asm {sub ESP, s }

int main() {
    int i;
    int s;
    SAVE_STACK(i);
    RESTORE_STACK;
}

clang++ tmp.cpp -fms-extensions -fenable-experimental-ms-inline-asm -S -o -

        .def     main;
        .scl    2;
        .type   32;
        .endef
        .text
        .globl  main
        .align  16, 0x90
main:                                   # @main
# BB#0:                                 # %entry
        pushq   %rax
        #APP
        .intel_syntax
        mov dword ptr [rsp + 4], ESP
        .att_syntax
        #NO_APP
        #APP
        .intel_syntax
        sub ESP, dword ptr [rsp]
        .att_syntax
        #NO_APP
        xorl    %eax, %eax
        popq    %rdx
        ret

And the command clang++ tmp.cpp -fms-extensions -fenable-experimental-ms-inline-asm produces an executable that runs.

It does still produce warnings like the following though.

warning: MS-style inline assembly is not supported [-Wmicrosoft]

bames53
  • 86,085
  • 15
  • 179
  • 244
  • Does the phrase "improve support for Microsoft's non-standard assembly syntax" imply that the assembly syntax that GCC uses is more standard? – zneak Mar 10 '13 at 17:12
  • @zneak Yes, the the `asm("...")` syntax is part of the C++ standard, whereas Microsoft's `__asm { ... };` is not. – bames53 Mar 10 '13 at 17:14
  • I just looked it up and it's not a very strong statement from the standard. §7.4 says "_An `asm` declaration has the form __asm-definition:__ `asm (` __string-literal__ `) ;`. The `asm` declaration is conditionally-supported; its meaning is implementation-defined._" So strictly speaking, the only thing non-standard about Microsoft's implementation is that it doesn't accept a string literal (and has curly braces), and GCC's operands and clobber lists don't match the standard form either. – zneak Mar 10 '13 at 17:49
  • @zneak gcc has a non-standard extension to the standard `asm` statement, but gcc also accepts and makes actual use of the standard `asm("")` statement (i.e., without its extension). VC++ recognizes _and ignores_ the standard syntax in favor of a completely different keyword and syntax. What's more, given VC++'s implementation defined assembly language, VC++ could use the pure standard `asm` statement without even the extension gcc uses. – bames53 Mar 10 '13 at 18:38
  • 1
    If it did use the pure standard syntax, programs made for VC++ could compile with GCC and produce incorrect results because of the absence of a clobber list. The standard value of `asm` is void because it does nothing else than declare the existence of the syntax, which breaks any chance of interoperability. This is why I find it unfair to tax Microsoft's implementation as non-standard while saying GCC's is more compliant, especially since there would be no way to answer this question without using the non-standard ASM operands and clobber lists for GCC. – zneak Mar 10 '13 at 21:45
  • I don't agree the there was no value in standardizing the asm statement. Although the content is down to implementations because so much of what asm statements deal with is far outside the scope of C++, that does not 'break any chance' that vendors could work to produce interoperable implementations. I also don't agree that I'm being unfair to point out that GCC allows some useful applications of the standard asm statement while VC++ does not allow any. Certainly it's unfortunate that GCC implemented it such that many normal uses of asm require an extension, but 'some' is better than 'none'. – bames53 Mar 11 '13 at 02:32
4

I have a problem using the XCode development environment the following code compiled correctly. Switching to my makefile I received the following error message Expected '(' after 'asm'

#define DebugBreak()  { __asm { int 3 }; }
int main(int argc, const char *argv[])
{
    DebugBreak();
}

Note that the definition for DebugBreak() came from my code that compiled under Visual Studio.

The way that I fix this in my make file was to added the argument -fasm-blocks

CFLAGS += -std=c++11 -stdlib=libc++ -O2 -fasm-blocks

Charlie
  • 978
  • 1
  • 7
  • 27
Robert Booth
  • 301
  • 2
  • 3