85

I remember back in the day with the old borland DOS compiler you could do something like this:

asm {
 mov ax,ex
 etc etc...
}

Is there a semi-platform independent way to do this now? I have a need to make a BIOS call, so if there was a way to do this without asm code, that would be equally useful to me.

kristianp
  • 5,496
  • 37
  • 56
Nathan
  • 11,938
  • 12
  • 55
  • 62
  • See also the links in the [inline-assembly tag wiki](https://stackoverflow.com/tags/inline-assembly/info) for how to get this right. It's hard, and the best suggestion is https://gcc.gnu.org/wiki/DontUseInlineAsm. For performance, whenever possible tweak your source code to help the compiler make better code, instead of using inline asm. (e.g. by looking at the compiler's asm output to see what it fails to optimize or what it does wrong.) – Peter Cordes Oct 27 '17 at 08:49

5 Answers5

87

Using GCC

__asm__("movl %edx, %eax\n\t"
        "addl $2, %eax\n\t");

Using VC++

__asm {
  mov eax, edx
  add eax, 2
}
Niall
  • 4,983
  • 1
  • 20
  • 12
  • 1
    C++Builder, from CodeGear, also supports the __asm keyword. – stukelly Sep 14 '08 at 14:20
  • 1
    VS compiler does not support inline assembly ! I had burned my finger trying to do that a few years ago ! – Jay D May 02 '12 at 07:04
  • 3
    @JayD: the VS compiler supports inline assembly depending on the target. For example, 32-bit x86 is supported; 64-bit x86-64 is not. – Michael Burr May 02 '12 at 07:11
  • 3
    Yes this is legal gcc syntax, but buggy unless you put that inside a function with `__attribute__((naked))` which contains *only* inline asm. **If you modify registers, you *must* use GNU C Extended Asm constraints / clobbers to tell the compiler about it**; stepping on the compiler's registers can cause really weird results. (Testing one case with optimization disabled doesn't prove it's safe, either). See https://gcc.gnu.org/onlinedocs/gcc/Using-Assembly-Language-with-C.html / https://stackoverflow.com/tags/inline-assembly/info / http://ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html – Peter Cordes Apr 03 '19 at 14:10
21

In GCC, there's more to it than that. In the instruction, you have to tell the compiler what changed, so that its optimizer doesn't screw up. I'm no expert, but sometimes it looks something like this:

    asm ("lock; xaddl %0,%2" : "=r" (result) : "0" (1), "m" (*atom) : "memory");

It's a good idea to write some sample code in C, then ask GCC to produce an assembly listing, then modify that code.

Martin Del Vecchio
  • 3,558
  • 2
  • 27
  • 36
10

A good start would be reading this article which talk about inline assembly in C/C++:

http://www.codeproject.com/KB/cpp/edujini_inline_asm.aspx

Example from the article:

#include <stdio.h>


int main() {
    /* Add 10 and 20 and store result into register %eax */
    __asm__ ( "movl $10, %eax;"
                "movl $20, %ebx;"
                "addl %ebx, %eax;"
    );

    /* Subtract 20 from 10 and store result into register %eax */
    __asm__ ( "movl $10, %eax;"
                    "movl $20, %ebx;"
                    "subl %ebx, %eax;"
    );

    /* Multiply 10 and 20 and store result into register %eax */
    __asm__ ( "movl $10, %eax;"
                    "movl $20, %ebx;"
                    "imull %ebx, %eax;"
    );

    return 0 ;
}
Espo
  • 41,399
  • 21
  • 132
  • 159
  • 1
    Those are all unsafe: you're modifying EAX and EBX without telling the compiler about it. Never use GNU C Basic Asm inside a function (except as the body of an `__attribute__((naked))` function.) Only ever GNU C Extended asm like `asm("sub %1, %0" : "+r"(dst) : "ri"(20));` for example. https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html and https://stackoverflow.com/tags/inline-assembly/info The article you linked does go on to discuss Extended Asm, but is missing clobbers on some temporary registers in its larger example of `asm volatile`. – Peter Cordes Mar 28 '21 at 16:05
  • The article also follows the anti-pattern of starting the asm template with a `mov %1, %%eax` instead of asking for the input in a register in the first place. – Peter Cordes Mar 28 '21 at 16:09
3

For Microsoft compilers, inline assembly is supported only for x86. For other targets you have to define the whole function in a separate assembly source file, pass it to an assembler and link the resulting object module.

You're highly unlikely to be able to call into the BIOS under a protected-mode operating system and should use whatever facilities are available on that system. Even if you're in kernel mode it's probably unsafe - the BIOS may not be correctly synchronized with respect to OS state if you do so.

Spike0xff
  • 1,246
  • 1
  • 15
  • 24
Mike Dimmick
  • 9,662
  • 2
  • 23
  • 48
  • Mike, what do you mean by "Non-x86 Microsoft compilers do not support in-line assembly", of course you can have e.g. ARM (non-x86) inline assembly, just search for it. –  Sep 21 '17 at 09:56
  • 2
    "Inline assembly is not supported on the ARM and x64 processors." - https://learn.microsoft.com/en-gb/cpp/assembler/inline/inline-assembler . *Inline* assembler means use of `__asm` blocks, and I'm talking specifically about Microsoft's compilers. You can still create a separate .asm file, assemble that with the Microsoft assembler (ML/ML64/armasm) and link the resulting .obj with a C/C++ program using CL. The other answers indicate that you can do inline assembly with other compilers. – Mike Dimmick Sep 21 '17 at 16:58
1

use of asm or __asm__ function ( in compilers have difference )

also you can write fortran codes with fortran function

asm("syscall");
fortran("Print *,"J");