It's even possible on most compilers to include a little bit of assembly code right inside your C or C++ file, called "inline assembly" because the assembly is inside the C/C++. How you do this depends on what compiler you're using.
The downside of inline assembly is you're tied to a particular combination of hardware instruction set, and software interface to access it. The upside is you can access the full feature set of the bare hardware, without needing to write the entire program in assembly.
Microsoft Inline Assembly:Here's a simple example in Microsoft Visual C++ inline assembly:int foo(void) {Note that now:
Note also that I've used the "leave" instruction to clean up foo's stack frame (mov esp,ebp; pop ebp;) before returning. The compiler secretly generates the corresponding function prologue at the start of the function. Microsoft Outside Variable Access:In Microsoft Visual C or C++, you can read and write variables from the program by just giving their names.Simple example: void *frame;Complicated example: int foo(void) {This is clearly very convenient! But what happens if we try to do the same thing with a variable named "al"? (Remember, "al" is a register on x86!) |
GCC Inline Assembly:Here's an example of how to declare a little assembly snippet inside C++ code using gcc, the default compiler on Linux/UNIX/MacOS:int foo(void) { __asm__( /* Assembly function body */ " mov $100,%eax \n" " ret \n" ); return 1; // never gets here, due to ret } Note that:
The bottom line is just to use the __asm__ keyword, which takes the assembly code as a big string. Because the string needs newlines (assembly is line-oriented), even the "macro stringification" trick doesn't help here. GCC Outside Variable Access:Accessing outside variables is truly hideous in gcc inline assembly.Simple example: void *frame; /* Frame pointer */Complicated example: int foo(void) { int joe=1234, fred; __asm__( " mov %1,%%eax\n" " add $2,%%eax\n" " mov %%eax,%0\n" :"=r" (fred) /* %0: Output variable list */ :"r" (joe) /* %1: Input variable list */ :"%eax" /* Overwritten registers ("Clobber list") */ ); return fred; }The __asm__ keyword can take up to four strings, separated by colons:
GCC Whole Function in AssemblyPartly because GCC's inline assembly syntax is so horrible, it's often easier to just write the whole function (argument access, frame setup, and value return) in assembly. There doesn't seem to be a way to do this in Visual C++, although (in either case) it's easy enough to separately compile a whole file full of pure assembly code and just link it in.To write a function in assembly, just:
extern "C" long my_fn(long in); /* Prototype */ __asm__( /* Assembly function body */ "my_fn:\n" " mov %rdi,%rax\n" " add $100,%rax\n" " ret\n" ); int foo(void) { return my_fn(3); }This is actually a pretty clean way to do inline assembly in gcc, although you do have to remember the calling convention (%rdi, %rsi, etc) to find your arguments! |
CS 301 Lecture Note, 2014, Dr. Orion Lawlor, UAF Computer Science Department.